GPencil Tools: Canvas rotate improvement
[blender-addons.git] / space_view3d_pie_menus / pie_align_menu.py
blob2dcf9e203ab50364140e3ee38212d34a17e9dd16
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 #####
19 # <pep8 compliant>
21 bl_info = {
22 "name": "Hotkey: 'Alt X'",
23 "description": "V/E/F Align tools",
24 "author": "pitiwazou, meta-androcto",
25 "version": (0, 1, 2),
26 "blender": (2, 80, 0),
27 "location": "Mesh Edit Mode",
28 "warning": "",
29 "doc_url": "",
30 "category": "Edit Align Pie"
33 import bpy
34 from bpy.types import (
35 Menu,
36 Operator,
38 from bpy.props import EnumProperty
41 # Pie Align - Alt + X
42 class PIE_MT_Align(Menu):
43 bl_idname = "PIE_MT_align"
44 bl_label = "Pie Align"
46 def draw(self, context):
47 layout = self.layout
48 pie = layout.menu_pie()
49 # 4 - LEFT
50 box = pie.split().box().column()
52 row = box.row(align=True)
53 row.label(text="X")
54 align_1 = row.operator("alignxyz.all", text="Neg")
55 align_1.axis = '0'
56 align_1.side = 'NEGATIVE'
58 row = box.row(align=True)
59 row.label(text="Y")
60 align_3 = row.operator("alignxyz.all", text="Neg")
61 align_3.axis = '1'
62 align_3.side = 'NEGATIVE'
64 row = box.row(align=True)
65 row.label(text="Z")
66 align_5 = row.operator("alignxyz.all", text="Neg")
67 align_5.axis = '2'
68 align_5.side = 'NEGATIVE'
69 # 6 - RIGHT
70 box = pie.split().box().column()
72 row = box.row(align=True)
73 row.label(text="X")
74 align_2 = row.operator("alignxyz.all", text="Pos")
75 align_2.axis = '0'
76 align_2.side = 'POSITIVE'
78 row = box.row(align=True)
79 row.label(text="Y")
80 align_4 = row.operator("alignxyz.all", text="Pos")
81 align_4.axis = '1'
82 align_4.side = 'POSITIVE'
84 row = box.row(align=True)
85 row.label(text="Z")
86 align_6 = row.operator("alignxyz.all", text="Pos")
87 align_6.axis = '2'
88 align_6.side = 'POSITIVE'
89 # 2 - BOTTOM
90 pie.operator("align.2xyz", text="Align To Y-0").axis = '1'
91 # 8 - TOP
92 pie.operator("align.selected2xyz",
93 text="Align Y").axis = 'Y'
94 # 7 - TOP - LEFT
95 pie.operator("align.selected2xyz",
96 text="Align X").axis = 'X'
97 # 9 - TOP - RIGHT
98 pie.operator("align.selected2xyz",
99 text="Align Z").axis = 'Z'
100 # 1 - BOTTOM - LEFT
101 pie.operator("align.2xyz", text="Align To X-0").axis = '0'
102 # 3 - BOTTOM - RIGHT
103 pie.operator("align.2xyz", text="Align To Z-0").axis = '2'
106 # Align to X, Y, Z
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'}
113 axis: EnumProperty(
114 name="Axis",
115 items=[
116 ('X', "X", "X Axis"),
117 ('Y', "Y", "Y Axis"),
118 ('Z', "Z", "Z Axis")
120 description="Choose an axis for alignment",
121 default='X'
124 @classmethod
125 def poll(cls, context):
126 obj = context.active_object
127 return obj and obj.type == "MESH"
129 def execute(self, context):
130 values = {
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(
138 value=chosen_value,
139 constraint_axis=constraint_value,
140 orient_type='GLOBAL',
141 mirror=False,
142 use_proportional_edit=False,
144 return {'FINISHED'}
147 # ################# #
148 # Align To 0 #
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'}
157 axis: EnumProperty(
158 name="Axis",
159 items=[
160 ('0', "X", "X Axis"),
161 ('1', "Y", "Y Axis"),
162 ('2', "Z", "Z Axis")
164 description="Choose an axis for alignment",
165 default='0'
168 @classmethod
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:
177 if vert.select:
178 vert.co[align] = 0
179 bpy.ops.object.editmode_toggle()
181 return {'FINISHED'}
184 # Align X Left
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'}
191 axis: EnumProperty(
192 name="Axis",
193 items=[
194 ('0', "X", "X Axis"),
195 ('1', "Y", "Y Axis"),
196 ('2', "Z", "Z Axis")
198 description="Choose an axis for alignment",
199 default='0'
201 side: EnumProperty(
202 name="Side",
203 items=[
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",
208 default='POSITIVE'
211 @classmethod
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')
219 count = 0
220 axe = int(self.axis)
221 for vert in bpy.context.object.data.vertices:
222 if vert.select:
223 if count == 0:
224 maxv = vert.co[axe]
225 count += 1
226 continue
227 count += 1
228 if self.side == 'POSITIVE':
229 if vert.co[axe] > maxv:
230 maxv = vert.co[axe]
231 else:
232 if vert.co[axe] < maxv:
233 maxv = vert.co[axe]
235 bpy.ops.object.mode_set(mode='OBJECT')
237 for vert in bpy.context.object.data.vertices:
238 if vert.select:
239 vert.co[axe] = maxv
240 bpy.ops.object.mode_set(mode='EDIT')
242 return {'FINISHED'}
245 classes = (
246 PIE_MT_Align,
247 PIE_OT_AlignSelectedXYZ,
248 PIE_OT_AlignToXYZ0,
249 PIE_OT_AlignXYZAll,
252 addon_keymaps = []
255 def register():
256 for cls in classes:
257 bpy.utils.register_class(cls)
259 wm = bpy.context.window_manager
260 if wm.keyconfigs.addon:
261 # Align
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))
268 def unregister():
269 for cls in classes:
270 bpy.utils.unregister_class(cls)
272 wm = bpy.context.window_manager
273 kc = wm.keyconfigs.addon
274 if kc:
275 for km, kmi in addon_keymaps:
276 km.keymap_items.remove(kmi)
277 addon_keymaps.clear()
280 if __name__ == "__main__":
281 register()