Refactor: Node Wrangler: PreviewNode operator
[blender-addons.git] / mesh_tools / vertex_align.py
blob1ab0a52df851353612f982ef66a06ded478da18f
1 # SPDX-FileCopyrightText: 2019-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 # Note: Property group was moved to __init__
7 bl_info = {
8 "name": "Vertex Align",
9 "author": "",
10 "version": (0, 1, 7),
11 "blender": (2, 61, 0),
12 "location": "View3D > Tool Shelf",
13 "description": "",
14 "warning": "",
15 "doc_url": "",
16 "category": "Mesh",
20 import bpy
21 from bpy.props import (
22 BoolVectorProperty,
23 FloatVectorProperty,
25 from mathutils import Vector
26 from bpy.types import Operator
29 # Edit Mode Toggle
30 def edit_mode_out():
31 bpy.ops.object.mode_set(mode='OBJECT')
34 def edit_mode_in():
35 bpy.ops.object.mode_set(mode='EDIT')
38 def get_mesh_data_():
39 edit_mode_out()
40 ob_act = bpy.context.active_object
41 me = ob_act.data
42 edit_mode_in()
43 return me
46 def list_clear_(l):
47 l[:] = []
48 return l
51 class va_buf():
52 list_v = []
53 list_0 = []
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")
63 @classmethod
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):
69 try:
70 me = get_mesh_data_()
71 list_0 = [v.index for v in me.vertices if v.select]
73 if len(list_0) == 1:
74 list_clear_(va_buf.list_v)
75 for v in me.vertices:
76 if v.select:
77 va_buf.list_v.append(v.index)
78 bpy.ops.mesh.select_all(action='DESELECT')
79 else:
80 self.report({'WARNING'}, "Please select just One Vertex")
81 return {'CANCELLED'}
82 except:
83 self.report({'WARNING'}, "Storing selection could not be completed")
84 return {'CANCELLED'}
86 self.report({'INFO'}, "Selected Vertex coordinates are stored")
88 return {'FINISHED'}
91 # Align to original
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'}
98 @classmethod
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):
104 layout = self.layout
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):
116 edit_mode_out()
117 ob_act = context.active_object
118 me = ob_act.data
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")
125 edit_mode_in()
126 return {'CANCELLED'}
128 elif len(va_buf.list_v) != 0:
129 if len(list_0) == 0:
130 self.report({'INFO'}, "No vertices selected. Operation Cancelled")
131 edit_mode_in()
132 return {'CANCELLED'}
134 elif len(list_0) != 0:
135 vo = (me.vertices[va_buf.list_v[0]].co).copy()
136 if cen1[0] is True:
137 for i in list_0:
138 v = (me.vertices[i].co).copy()
139 me.vertices[i].co = Vector((vo[0], v[1], v[2]))
140 if cen1[1] is True:
141 for i in list_0:
142 v = (me.vertices[i].co).copy()
143 me.vertices[i].co = Vector((v[0], vo[1], v[2]))
144 if cen1[2] is True:
145 for i in list_0:
146 v = (me.vertices[i].co).copy()
147 me.vertices[i].co = Vector((v[0], v[1], vo[2]))
148 edit_mode_in()
150 return {'FINISHED'}
153 # Align to custom coordinates
154 class Vertex_align_coord_list(Operator):
155 bl_idname = "vertex_align.coord_list_id"
156 bl_label = ""
157 bl_description = "Align to custom coordinates"
159 @classmethod
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):
165 edit_mode_out()
166 ob_act = context.active_object
167 me = ob_act.data
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")
173 edit_mode_in()
174 return {'CANCELLED'}
176 elif len(va_buf.list_0) != 0:
177 bpy.ops.vertex_align.coord_menu_id('INVOKE_DEFAULT')
179 edit_mode_in()
181 return {'FINISHED'}
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(
192 name="",
193 description="Enter the values of coordinates",
194 default=(0.0, 0.0, 0.0),
195 min=-100.0, max=100.0,
196 step=1, size=3,
197 subtype='XYZ',
198 precision=3
200 use_axis_coord = BoolVectorProperty(
201 name="Axis",
202 description="Choose Custom Coordinates axis",
203 default=(False,) * 3,
204 size=3,
206 is_not_undo = False
208 @classmethod
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):
218 layout = self.layout
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
245 edit_mode_out()
246 ob_act = context.active_object
247 me = ob_act.data
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
261 edit_mode_in()
263 return {'FINISHED'}
266 # Register
267 classes = (
268 Vertex_align_store,
269 Vertex_align_original,
270 Vertex_align_coord_list,
271 Vertex_align_coord_menu,
275 def register():
276 for cls in classes:
277 bpy.utils.register_class(cls)
280 def unregister():
281 for cls in classes:
282 bpy.utils.unregister_class(cls)
285 if __name__ == "__main__":
286 register()