1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
22 "name": "Hotkey: 'Alt X'",
23 "description": "V/E/F Align tools",
24 "author": "pitiwazou, meta-androcto",
26 "blender": (2, 80, 0),
27 "location": "Mesh Edit Mode",
30 "category": "Edit Align Pie"
34 from bpy
.types
import (
38 from bpy
.props
import EnumProperty
42 class PIE_MT_Align(Menu
):
43 bl_idname
= "PIE_MT_align"
44 bl_label
= "Pie Align"
46 def draw(self
, context
):
48 pie
= layout
.menu_pie()
50 box
= pie
.split().box().column()
52 row
= box
.row(align
=True)
54 align_1
= row
.operator("alignxyz.all", text
="Neg")
56 align_1
.side
= 'NEGATIVE'
58 row
= box
.row(align
=True)
60 align_3
= row
.operator("alignxyz.all", text
="Neg")
62 align_3
.side
= 'NEGATIVE'
64 row
= box
.row(align
=True)
66 align_5
= row
.operator("alignxyz.all", text
="Neg")
68 align_5
.side
= 'NEGATIVE'
70 box
= pie
.split().box().column()
72 row
= box
.row(align
=True)
74 align_2
= row
.operator("alignxyz.all", text
="Pos")
76 align_2
.side
= 'POSITIVE'
78 row
= box
.row(align
=True)
80 align_4
= row
.operator("alignxyz.all", text
="Pos")
82 align_4
.side
= 'POSITIVE'
84 row
= box
.row(align
=True)
86 align_6
= row
.operator("alignxyz.all", text
="Pos")
88 align_6
.side
= 'POSITIVE'
90 pie
.operator("align.2xyz", text
="Align To Y-0").axis
= '1'
92 pie
.operator("align.selected2xyz",
93 text
="Align Y").axis
= 'Y'
95 pie
.operator("align.selected2xyz",
96 text
="Align X").axis
= 'X'
98 pie
.operator("align.selected2xyz",
99 text
="Align Z").axis
= 'Z'
101 pie
.operator("align.2xyz", text
="Align To X-0").axis
= '0'
103 pie
.operator("align.2xyz", text
="Align To Z-0").axis
= '2'
107 class PIE_OT_AlignSelectedXYZ(Operator
):
108 bl_idname
= "align.selected2xyz"
109 bl_label
= "Align to X, Y, Z"
110 bl_description
= "Align Selected Along the chosen axis"
111 bl_options
= {'REGISTER', 'UNDO'}
116 ('X', "X", "X Axis"),
117 ('Y', "Y", "Y Axis"),
120 description
="Choose an axis for alignment",
125 def poll(cls
, context
):
126 obj
= context
.active_object
127 return obj
and obj
.type == "MESH"
129 def execute(self
, context
):
131 'X': [(0, 1, 1), (True, False, False)],
132 'Y': [(1, 0, 1), (False, True, False)],
133 'Z': [(1, 1, 0), (False, False, True)]
135 chosen_value
= values
[self
.axis
][0]
136 constraint_value
= values
[self
.axis
][1]
137 bpy
.ops
.transform
.resize(
139 constraint_axis
=constraint_value
,
140 orient_type
='GLOBAL',
142 use_proportional_edit
=False,
147 # ################# #
149 # ################# #
151 class PIE_OT_AlignToXYZ0(Operator
):
152 bl_idname
= "align.2xyz"
153 bl_label
= "Align To X, Y or Z = 0"
154 bl_description
= "Align Active Object To a chosen X, Y or Z equals 0 Location"
155 bl_options
= {'REGISTER', 'UNDO'}
160 ('0', "X", "X Axis"),
161 ('1', "Y", "Y Axis"),
164 description
="Choose an axis for alignment",
169 def poll(cls
, context
):
170 obj
= context
.active_object
171 return obj
and obj
.type == "MESH"
173 def execute(self
, context
):
174 bpy
.ops
.object.mode_set(mode
='OBJECT')
175 align
= int(self
.axis
)
176 for vert
in bpy
.context
.object.data
.vertices
:
179 bpy
.ops
.object.editmode_toggle()
185 class PIE_OT_AlignXYZAll(Operator
):
186 bl_idname
= "alignxyz.all"
187 bl_label
= "Align to Front/Back Axis"
188 bl_description
= "Align to a Front or Back along the chosen Axis"
189 bl_options
= {'REGISTER', 'UNDO'}
194 ('0', "X", "X Axis"),
195 ('1', "Y", "Y Axis"),
198 description
="Choose an axis for alignment",
204 ('POSITIVE', "Front", "Align on the positive chosen axis"),
205 ('NEGATIVE', "Back", "Align acriss the negative chosen axis"),
207 description
="Choose a side for alignment",
212 def poll(cls
, context
):
213 obj
= context
.active_object
214 return obj
and obj
.type == "MESH"
216 def execute(self
, context
):
218 bpy
.ops
.object.mode_set(mode
='OBJECT')
221 for vert
in bpy
.context
.object.data
.vertices
:
228 if self
.side
== 'POSITIVE':
229 if vert
.co
[axe
] > maxv
:
232 if vert
.co
[axe
] < maxv
:
235 bpy
.ops
.object.mode_set(mode
='OBJECT')
237 for vert
in bpy
.context
.object.data
.vertices
:
240 bpy
.ops
.object.mode_set(mode
='EDIT')
247 PIE_OT_AlignSelectedXYZ
,
257 bpy
.utils
.register_class(cls
)
259 wm
= bpy
.context
.window_manager
260 if wm
.keyconfigs
.addon
:
262 km
= wm
.keyconfigs
.addon
.keymaps
.new(name
='Mesh')
263 kmi
= km
.keymap_items
.new('wm.call_menu_pie', 'X', 'PRESS', alt
=True)
264 kmi
.properties
.name
= "PIE_MT_align"
265 addon_keymaps
.append((km
, kmi
))
270 bpy
.utils
.unregister_class(cls
)
272 wm
= bpy
.context
.window_manager
273 kc
= wm
.keyconfigs
.addon
275 for km
, kmi
in addon_keymaps
:
276 km
.keymap_items
.remove(kmi
)
277 addon_keymaps
.clear()
280 if __name__
== "__main__":