Merge branch 'blender-v2.92-release'
[blender-addons.git] / space_view3d_pie_menus / pie_modes_menu.py
blobc7ec302f7c2abb6a04812622cfdc404b0cef7e97
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: 'Ctrl Tab'",
23 "description": "Switch between 3d view object/edit modes",
24 "author": "pitiwazou, meta-androcto, italic",
25 "version": (0, 1, 2),
26 "blender": (2, 80, 0),
27 "location": "3D View",
28 "warning": "",
29 "doc_url": "",
30 "category": "Mode Switch Pie"
33 import bpy
34 from bpy.types import (
35 Menu,
36 Operator
40 class PIE_OT_ClassObject(Operator):
41 bl_idname = "class.object"
42 bl_label = "Class Object"
43 bl_description = "Edit/Object Mode Switch"
44 bl_options = {'REGISTER', 'UNDO'}
46 def execute(self, context):
47 if context.object.mode == "OBJECT":
48 bpy.ops.object.mode_set(mode="EDIT")
49 else:
50 bpy.ops.object.mode_set(mode="OBJECT")
51 return {'FINISHED'}
54 class PIE_OT_ClassTexturePaint(Operator):
55 bl_idname = "class.pietexturepaint"
56 bl_label = "Class Texture Paint"
57 bl_description = "Texture Paint"
58 bl_options = {'REGISTER', 'UNDO'}
60 def execute(self, context):
61 if context.object.mode == "EDIT":
62 bpy.ops.object.mode_set(mode="OBJECT")
63 bpy.ops.paint.texture_paint_toggle()
64 else:
65 bpy.ops.paint.texture_paint_toggle()
66 return {'FINISHED'}
69 class PIE_OT_ClassWeightPaint(Operator):
70 bl_idname = "class.pieweightpaint"
71 bl_label = "Class Weight Paint"
72 bl_description = "Weight Paint"
73 bl_options = {'REGISTER', 'UNDO'}
75 def execute(self, context):
76 if context.object.mode == "EDIT":
77 bpy.ops.object.mode_set(mode="OBJECT")
78 bpy.ops.paint.weight_paint_toggle()
79 else:
80 bpy.ops.paint.weight_paint_toggle()
81 return {'FINISHED'}
84 class PIE_OT_ClassVertexPaint(Operator):
85 bl_idname = "class.pievertexpaint"
86 bl_label = "Class Vertex Paint"
87 bl_description = "Vertex Paint"
88 bl_options = {'REGISTER', 'UNDO'}
90 def execute(self, context):
91 if context.object.mode == "EDIT":
92 bpy.ops.object.mode_set(mode="OBJECT")
93 bpy.ops.paint.vertex_paint_toggle()
94 else:
95 bpy.ops.paint.vertex_paint_toggle()
96 return {'FINISHED'}
99 class PIE_OT_ClassParticleEdit(Operator):
100 bl_idname = "class.pieparticleedit"
101 bl_label = "Class Particle Edit"
102 bl_description = "Particle Edit (must have active particle system)"
103 bl_options = {'REGISTER', 'UNDO'}
105 def execute(self, context):
106 if context.object.mode == "EDIT":
107 bpy.ops.object.mode_set(mode="OBJECT")
108 bpy.ops.particle.particle_edit_toggle()
109 else:
110 bpy.ops.particle.particle_edit_toggle()
111 return {'FINISHED'}
114 # Set Mode Operator #
115 class PIE_OT_SetObjectModePie(Operator):
116 bl_idname = "object.set_object_mode_pie"
117 bl_label = "Set the object interactive mode"
118 bl_description = "I set the interactive mode of object"
119 bl_options = {'REGISTER'}
121 mode: bpy.props.StringProperty(name="Interactive mode", default="OBJECT")
123 def execute(self, context):
124 if (context.active_object):
125 try:
126 bpy.ops.object.mode_set(mode=self.mode)
127 except TypeError:
128 msg = context.active_object.name + " It is not possible to enter into the interactive mode"
129 self.report(type={"WARNING"}, message=msg)
130 else:
131 self.report(type={"WARNING"}, message="There is no active object")
132 return {'FINISHED'}
135 # Edit Selection Modes
136 class PIE_OT_ClassVertex(Operator):
137 bl_idname = "class.vertex"
138 bl_label = "Class Vertex"
139 bl_description = "Vert Select Mode"
140 bl_options = {'REGISTER', 'UNDO'}
142 def execute(self, context):
143 if context.object.mode != "EDIT":
144 bpy.ops.object.mode_set(mode="EDIT")
145 bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT')
146 if bpy.ops.mesh.select_mode != "EDGE, FACE":
147 bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT')
148 return {'FINISHED'}
151 class PIE_OT_ClassEdge(Operator):
152 bl_idname = "class.edge"
153 bl_label = "Class Edge"
154 bl_description = "Edge Select Mode"
155 bl_options = {'REGISTER', 'UNDO'}
157 def execute(self, context):
158 if context.object.mode != "EDIT":
159 bpy.ops.object.mode_set(mode="EDIT")
160 bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='EDGE')
161 if bpy.ops.mesh.select_mode != "VERT, FACE":
162 bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='EDGE')
163 return {'FINISHED'}
166 class PIE_OT_ClassFace(Operator):
167 bl_idname = "class.face"
168 bl_label = "Class Face"
169 bl_description = "Face Select Mode"
170 bl_options = {'REGISTER', 'UNDO'}
172 def execute(self, context):
173 if context.object.mode != "EDIT":
174 bpy.ops.object.mode_set(mode="EDIT")
175 bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE')
176 if bpy.ops.mesh.select_mode != "VERT, EDGE":
177 bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE')
178 return {'FINISHED'}
181 class PIE_OT_VertsEdgesFaces(Operator):
182 bl_idname = "verts.edgesfaces"
183 bl_label = "Verts Edges Faces"
184 bl_description = "Vert/Edge/Face Select Mode"
185 bl_options = {'REGISTER', 'UNDO'}
187 def execute(self, context):
188 if context.object.mode != "EDIT":
189 bpy.ops.object.mode_set(mode="EDIT")
190 bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT')
191 if bpy.ops.mesh.select_mode != "VERT, EDGE, FACE":
192 bpy.ops.object.mode_set(mode="EDIT")
193 bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='VERT')
194 bpy.ops.mesh.select_mode(use_extend=True, use_expand=False, type='EDGE')
195 bpy.ops.mesh.select_mode(use_extend=True, use_expand=False, type='FACE')
196 return {'FINISHED'}
199 # Menus
200 class PIE_MT_ObjectEditotherModes(Menu):
201 """Edit/Object Others modes"""
202 bl_idname = "MENU_MT_objecteditmodeothermodes"
203 bl_label = "Edit Selection Modes"
205 def draw(self, context):
206 layout = self.layout
207 pie = layout.menu_pie()
208 box = pie.split().column()
210 box.operator("class.vertex", text="Vertex", icon='VERTEXSEL')
211 box.operator("class.edge", text="Edge", icon='EDGESEL')
212 box.operator("class.face", text="Face", icon='FACESEL')
213 box.operator("verts.edgesfaces", text="Vertex/Edges/Faces", icon='OBJECT_DATAMODE')
216 class PIE_MT_ObjectEditMode(Menu):
217 """Modes Switch"""
218 bl_idname = "PIE_MT_objecteditmode"
219 bl_label = "Mode Switch (Ctrl Tab)"
221 def draw(self, context):
222 layout = self.layout
223 ob = context.object
224 # No Object Selected #
225 if not ob or not ob.select_get():
226 message = "No Active Object Selected"
227 pie = layout.menu_pie()
228 pie.separator()
229 pie.separator()
230 pie.separator()
231 box = pie.box()
232 box.label(text=message, icon="INFO")
234 elif ob and ob.type == 'MESH' and ob.mode in {'OBJECT', 'SCULPT', 'VERTEX_PAINT',
235 'WEIGHT_PAINT', 'TEXTURE_PAINT',
236 'PARTICLE_EDIT', 'GPENCIL_EDIT'}:
237 pie = layout.menu_pie()
238 # 4 - LEFT
239 pie.operator("class.pieweightpaint", text="Weight Paint", icon='WPAINT_HLT')
240 # 6 - RIGHT
241 pie.operator("class.pietexturepaint", text="Texture Paint", icon='TPAINT_HLT')
242 # 2 - BOTTOM
243 pie.menu("MENU_MT_objecteditmodeothermodes", text="Edit Modes", icon='EDITMODE_HLT')
244 # 8 - TOP
245 pie.operator("class.object", text="Object/Edit Toggle", icon='OBJECT_DATAMODE')
246 # 7 - TOP - LEFT
247 pie.operator("sculpt.sculptmode_toggle", text="Sculpt", icon='SCULPTMODE_HLT')
248 # 9 - TOP - RIGHT
249 pie.operator("class.pievertexpaint", text="Vertex Paint", icon='VPAINT_HLT')
250 # 1 - BOTTOM - LEFT
251 pie.separator()
252 # 3 - BOTTOM - RIGHT
253 if context.object.particle_systems:
254 pie.operator("class.pieparticleedit", text="Particle Edit", icon='PARTICLEMODE')
255 else:
256 pie.separator()
258 elif ob and ob.type == 'MESH' and ob.mode in {'EDIT'}:
259 pie = layout.menu_pie()
260 # 4 - LEFT
261 pie.operator("class.pieweightpaint", text="Weight Paint", icon='WPAINT_HLT')
262 # 6 - RIGHT
263 pie.operator("class.pietexturepaint", text="Texture Paint", icon='TPAINT_HLT')
264 # 2 - BOTTOM
265 pie.menu("MENU_MT_objecteditmodeothermodes", text="Edit Modes", icon='EDITMODE_HLT')
266 # 8 - TOP
267 pie.operator("class.object", text="Edit/Object Toggle", icon='OBJECT_DATAMODE')
268 # 7 - TOP - LEFT
269 pie.operator("sculpt.sculptmode_toggle", text="Sculpt", icon='SCULPTMODE_HLT')
270 # 9 - TOP - RIGHT
271 pie.operator("class.pievertexpaint", text="Vertex Paint", icon='VPAINT_HLT')
272 # 1 - BOTTOM - LEFT
273 pie.separator()
274 # 3 - BOTTOM - RIGHT
275 if context.object.particle_systems:
276 pie.operator("class.pieparticleedit", text="Particle Edit", icon='PARTICLEMODE')
277 else:
278 pie.separator()
280 elif ob and ob.type == 'CURVE':
281 pie = layout.menu_pie()
282 # 4 - LEFT
283 pie.separator()
284 # 6 - RIGHT
285 pie.separator()
286 # 2 - BOTTOM
287 pie.separator()
288 # 8 - TOP
289 pie.operator("object.editmode_toggle", text="Edit/Object", icon='OBJECT_DATAMODE')
290 # 7 - TOP - LEFT
291 pie.separator()
292 # 9 - TOP - RIGHT
293 pie.separator()
294 # 1 - BOTTOM - LEFT
295 pie.separator()
296 # 3 - BOTTOM - RIGHT
297 pie.separator()
299 elif ob and ob.type == 'ARMATURE':
300 pie = layout.menu_pie()
301 # 4 - LEFT
302 pie.operator(PIE_OT_SetObjectModePie.bl_idname, text="Object", icon="OBJECT_DATAMODE").mode = "OBJECT"
303 # 6 - RIGHT
304 pie.operator(PIE_OT_SetObjectModePie.bl_idname, text="Pose", icon="POSE_HLT").mode = "POSE"
305 # 2 - BOTTOM
306 pie.operator(PIE_OT_SetObjectModePie.bl_idname, text="Edit", icon="EDITMODE_HLT").mode = "EDIT"
307 # 8 - TOP
308 pie.operator("object.editmode_toggle", text="Edit Mode", icon='OBJECT_DATAMODE')
309 # 7 - TOP - LEFT
310 pie.separator()
311 # 9 - TOP - RIGHT
312 pie.separator()
313 # 1 - BOTTOM - LEFT
314 pie.separator()
315 # 3 - BOTTOM - RIGHT
316 pie.separator()
318 elif ob and ob.type == 'FONT':
319 pie = layout.menu_pie()
320 pie.separator()
321 pie.separator()
322 pie.separator()
323 pie.operator("object.editmode_toggle", text="Edit/Object Toggle", icon='OBJECT_DATAMODE')
324 pie.separator()
325 pie.separator()
326 pie.separator()
327 # 3 - BOTTOM - RIGHT
328 pie.separator()
330 elif ob and ob.type == 'SURFACE':
331 pie = layout.menu_pie()
332 pie.separator()
333 pie.separator()
334 pie.separator()
335 pie.operator("object.editmode_toggle", text="Edit/Object Toggle", icon='OBJECT_DATAMODE')
336 pie.separator()
337 pie.separator()
338 pie.separator()
339 # 3 - BOTTOM - RIGHT
340 pie.separator()
342 elif ob and ob.type == 'META':
343 pie = layout.menu_pie()
344 pie.separator()
345 pie.separator()
346 pie.separator()
347 pie.operator("object.editmode_toggle", text="Edit/Object Toggle", icon='OBJECT_DATAMODE')
348 pie.separator()
349 pie.separator()
350 pie.separator()
351 # 3 - BOTTOM - RIGHT
352 pie.separator()
354 elif ob and ob.type == 'LATTICE':
355 pie = layout.menu_pie()
356 pie.separator()
357 pie.separator()
358 pie.separator()
359 pie.operator("object.editmode_toggle", text="Edit/Object Toggle", icon='OBJECT_DATAMODE')
360 pie.separator()
361 pie.separator()
362 pie.separator()
364 if ob and ob.type == 'GPENCIL':
365 pie = layout.menu_pie()
366 # 4 - LEFT
367 pie.operator(PIE_OT_SetObjectModePie.bl_idname, text="Sculpt", icon="SCULPTMODE_HLT").mode = "SCULPT_GPENCIL"
368 # 6 - RIGHT
369 pie.operator(PIE_OT_SetObjectModePie.bl_idname, text="Draw", icon="GREASEPENCIL").mode = "PAINT_GPENCIL"
370 # 2 - BOTTOM
371 pie.operator(PIE_OT_SetObjectModePie.bl_idname, text="Edit", icon="EDITMODE_HLT").mode = "EDIT_GPENCIL"
372 # 8 - TOP
373 pie.operator(PIE_OT_SetObjectModePie.bl_idname, text="Object", icon="OBJECT_DATAMODE").mode = "OBJECT"
374 # 7 - TOP - LEFT
375 pie.separator()
376 # 9 - TOP - RIGHT
377 pie.separator()
378 # 1 - BOTTOM - LEFT
379 pie.separator()
380 # 3 - BOTTOM - RIGHT
381 pie.operator(PIE_OT_SetObjectModePie.bl_idname, text="Weight Paint", icon="WPAINT_HLT").mode = "WEIGHT_GPENCIL"
385 elif ob and ob.type in {"LIGHT", "CAMERA", "EMPTY", "SPEAKER"}:
386 message = "Active Object has only Object Mode available"
387 pie = layout.menu_pie()
388 pie.separator()
389 pie.separator()
390 pie.separator()
391 box = pie.box()
392 box.label(text=message, icon="INFO")
395 classes = (
396 PIE_MT_ObjectEditMode,
397 PIE_OT_ClassObject,
398 PIE_OT_ClassVertex,
399 PIE_OT_ClassEdge,
400 PIE_OT_ClassFace,
401 PIE_MT_ObjectEditotherModes,
402 PIE_OT_ClassTexturePaint,
403 PIE_OT_ClassWeightPaint,
404 PIE_OT_ClassVertexPaint,
405 PIE_OT_ClassParticleEdit,
406 PIE_OT_VertsEdgesFaces,
407 PIE_OT_SetObjectModePie,
410 addon_keymaps = []
413 def register():
414 for cls in classes:
415 bpy.utils.register_class(cls)
417 wm = bpy.context.window_manager
418 if wm.keyconfigs.addon:
419 # Select Mode
420 km = wm.keyconfigs.addon.keymaps.new(name='Object Non-modal')
421 kmi = km.keymap_items.new('wm.call_menu_pie', 'TAB', 'PRESS', ctrl=True)
422 kmi.properties.name = "PIE_MT_objecteditmode"
423 addon_keymaps.append((km, kmi))
425 km = wm.keyconfigs.addon.keymaps.new(name='Grease Pencil Stroke Edit Mode')
426 kmi = km.keymap_items.new('wm.call_menu_pie', 'TAB', 'PRESS', ctrl=True)
427 kmi.properties.name = "PIE_MT_objecteditmode"
428 addon_keymaps.append((km, kmi))
431 def unregister():
432 for cls in classes:
433 bpy.utils.unregister_class(cls)
435 wm = bpy.context.window_manager
436 kc = wm.keyconfigs.addon
437 if kc:
438 for km, kmi in addon_keymaps:
439 km.keymap_items.remove(kmi)
440 addon_keymaps.clear()
443 if __name__ == "__main__":
444 register()