Pose library: fix asset creation operator poll when no object active
[blender-addons.git] / space_view3d_pie_menus / pie_origin.py
blob5605b229a07e22c896e367a0cfd7516e0b7750d6
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 bl_info = {
4 "name": "Hotkey: 'Ctrl Alt X'",
5 "description": "Origin Snap/Place Menu",
6 "author": "pitiwazou, meta-androcto",
7 "version": (0, 1, 2),
8 "blender": (2, 80, 0),
9 "location": "3D View",
10 "warning": "",
11 "doc_url": "",
12 "category": "Origin Pie"
15 import bpy
16 from bpy.types import (
17 Menu,
18 Operator,
22 # Pivot to selection
23 class PIE_OT_PivotToSelection(Operator):
24 bl_idname = "object.pivot2selection"
25 bl_label = "Pivot To Selection"
26 bl_description = "Pivot Point To Selection"
27 bl_options = {'REGISTER', 'UNDO'}
29 @classmethod
30 def poll(cls, context):
31 return context.active_object is not None
33 def execute(self, context):
34 saved_location = context.scene.cursor.location.copy()
35 bpy.ops.view3d.snap_cursor_to_selected()
36 bpy.ops.object.mode_set(mode='OBJECT')
37 bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
38 context.scene.cursor.location = saved_location
40 return {'FINISHED'}
42 # Pivot to Bottom
45 class PIE_OT_PivotBottom(Operator):
46 bl_idname = "object.pivotobottom"
47 bl_label = "Pivot To Bottom"
48 bl_description = ("Set the Pivot Point To Lowest Point\n"
49 "Needs an Active Object of the Mesh type")
50 bl_options = {'REGISTER', 'UNDO'}
52 @classmethod
53 def poll(cls, context):
54 obj = context.active_object
55 return obj is not None and obj.type == "MESH"
57 def execute(self, context):
58 bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
59 bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
60 o = context.active_object
61 init = 0
62 for x in o.data.vertices:
63 if init == 0:
64 a = x.co.z
65 init = 1
66 elif x.co.z < a:
67 a = x.co.z
69 for x in o.data.vertices:
70 x.co.z -= a
72 o.location.z += a
74 return {'FINISHED'}
77 # Pivot to Bottom
78 class PIE_OT_PivotBottom_edit(Operator):
79 bl_idname = "object.pivotobottom_edit"
80 bl_label = "Pivot To Bottom"
81 bl_description = ("Set the Pivot Point To Lowest Point\n"
82 "Needs an Active Object of the Mesh type")
83 bl_options = {'REGISTER', 'UNDO'}
85 @classmethod
86 def poll(cls, context):
87 obj = context.active_object
88 return obj is not None and obj.type == "MESH"
90 def execute(self, context):
91 bpy.ops.object.mode_set(mode='OBJECT')
92 bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
93 bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
94 o = context.active_object
95 init = 0
96 for x in o.data.vertices:
97 if init == 0:
98 a = x.co.z
99 init = 1
100 elif x.co.z < a:
101 a = x.co.z
103 for x in o.data.vertices:
104 x.co.z -= a
106 o.location.z += a
107 bpy.ops.object.mode_set(mode='EDIT')
109 return {'FINISHED'}
112 # Pivot to Cursor Edit Mode
113 class PIE_OT_PivotToCursor_edit(Operator):
114 bl_idname = "object.pivot2cursor_edit"
115 bl_label = "Pivot To Cursor"
116 bl_description = "Pivot Point To Cursor"
117 bl_options = {'REGISTER', 'UNDO'}
119 @classmethod
120 def poll(cls, context):
121 return context.active_object is not None
123 def execute(self, context):
124 bpy.ops.object.mode_set(mode='OBJECT')
125 bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
126 bpy.ops.object.mode_set(mode='EDIT')
128 return {'FINISHED'}
131 # Origin to Center of Mass Edit Mode
132 class PIE_OT_OriginToMass_edit(Operator):
133 bl_idname = "object.origintomass_edit"
134 bl_label = "Origin"
135 bl_description = "Origin to Center of Mass"
136 bl_options = {'REGISTER', 'UNDO'}
138 @classmethod
139 def poll(cls, context):
140 return context.active_object is not None
142 def execute(self, context):
143 bpy.ops.object.mode_set(mode='OBJECT')
144 bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS', center='MEDIAN')
145 bpy.ops.object.mode_set(mode='EDIT')
147 return {'FINISHED'}
150 # Origin to Geometry Edit Mode
151 class PIE_OT_OriginToGeometry_edit(Operator):
152 bl_idname = "object.origintogeometry_edit"
153 bl_label = "Origin to Geometry"
154 bl_description = "Origin to Geometry"
155 bl_options = {'REGISTER', 'UNDO'}
157 @classmethod
158 def poll(cls, context):
159 return context.active_object is not None
161 def execute(self, context):
162 bpy.ops.object.mode_set(mode='OBJECT')
163 bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='MEDIAN')
164 bpy.ops.object.mode_set(mode='EDIT')
166 return {'FINISHED'}
169 # Origin to Geometry Edit Mode
170 class PIE_OT_GeometryToOrigin_edit(Operator):
171 bl_idname = "object.geometrytoorigin_edit"
172 bl_label = "Geometry to Origin"
173 bl_description = "Geometry to Origin"
174 bl_options = {'REGISTER', 'UNDO'}
176 @classmethod
177 def poll(cls, context):
178 return context.active_object is not None
180 def execute(self, context):
181 bpy.ops.object.mode_set(mode='OBJECT')
182 bpy.ops.object.origin_set(type='GEOMETRY_ORIGIN', center='MEDIAN')
183 bpy.ops.object.mode_set(mode='EDIT')
185 return {'FINISHED'}
188 # Origin To Selected Edit Mode #
189 def vfeOrigin_pie(context):
190 try:
191 cursorPositionX = context.scene.cursor.location[0]
192 cursorPositionY = context.scene.cursor.location[1]
193 cursorPositionZ = context.scene.cursor.location[2]
194 bpy.ops.view3d.snap_cursor_to_selected()
195 bpy.ops.object.mode_set()
196 bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')
197 bpy.ops.object.mode_set(mode='EDIT')
198 context.scene.cursor.location[0] = cursorPositionX
199 context.scene.cursor.location[1] = cursorPositionY
200 context.scene.cursor.location[2] = cursorPositionZ
201 return True
202 except:
203 return False
206 class PIE_OT_SetOriginToSelected_edit(Operator):
207 bl_idname = "object.setorigintoselected_edit"
208 bl_label = "Set Origin to Selected"
209 bl_description = "Set Origin to Selected"
211 @classmethod
212 def poll(cls, context):
213 return (context.area.type == "VIEW_3D" and context.active_object is not None)
215 def execute(self, context):
216 check = vfeOrigin_pie(context)
217 if not check:
218 self.report({"ERROR"}, "Set Origin to Selected could not be performed")
219 return {'CANCELLED'}
221 return {'FINISHED'}
224 # Pie Origin/Pivot - Shift + S
225 class PIE_MT_OriginPivot(Menu):
226 bl_idname = "ORIGIN_MT_pivotmenu"
227 bl_label = "Origin Menu"
229 def draw(self, context):
230 layout = self.layout
231 obj = context.object
232 pie = layout.menu_pie()
233 if obj and obj.type == 'MESH' and obj.mode in {'OBJECT'}:
234 # 4 - LEFT
235 pie.operator("object.origin_set", text="Origin to Center of Mass",
236 icon='NONE').type = 'ORIGIN_CENTER_OF_MASS'
237 # 6 - RIGHT
238 pie.operator("object.origin_set", text="Origin to Cursor",
239 icon='PIVOT_CURSOR').type = 'ORIGIN_CURSOR'
240 # 2 - BOTTOM
241 pie.operator("object.pivotobottom", text="Origin to Bottom",
242 icon='TRIA_DOWN')
243 # 8 - TOP
244 pie.operator("object.pivot2selection", text="Origin To Selection",
245 icon='SNAP_INCREMENT')
246 # 7 - TOP - LEFT
247 pie.operator("object.origin_set", text="Geometry To Origin",
248 icon='NONE').type = 'GEOMETRY_ORIGIN'
249 # 9 - TOP - RIGHT
250 pie.operator("object.origin_set", text="Origin To Geometry",
251 icon='NONE').type = 'ORIGIN_GEOMETRY'
253 elif obj and obj.type == 'MESH' and obj.mode in {'EDIT'}:
254 # 4 - LEFT
255 pie.operator("object.origintomass_edit", text="Origin to Center of Mass",
256 icon='NONE')
257 # 6 - RIGHT
258 pie.operator("object.pivot2cursor_edit", text="Origin to Cursor",
259 icon='PIVOT_CURSOR')
260 # 2 - BOTTOM
261 pie.operator("object.pivotobottom_edit", text="Origin to Bottom",
262 icon='TRIA_DOWN')
263 # 8 - TOP
264 pie.operator("object.setorigintoselected_edit", text="Origin To Selected",
265 icon='SNAP_INCREMENT')
266 # 7 - TOP - LEFT
267 pie.operator("object.geometrytoorigin_edit", text="Geometry To Origin",
268 icon='NONE')
269 # 9 - TOP - RIGHT
270 pie.operator("object.origintogeometry_edit", text="Origin To Geometry",
271 icon='NONE')
273 else:
274 # 4 - LEFT
275 pie.operator("object.origin_set", text="Origin to Center of Mass",
276 icon='NONE').type = 'ORIGIN_CENTER_OF_MASS'
277 # 6 - RIGHT
278 pie.operator("object.origin_set", text="Origin To 3D Cursor",
279 icon='PIVOT_CURSOR').type = 'ORIGIN_CURSOR'
280 # 2 - BOTTOM
281 pie.operator("object.pivot2selection", text="Origin To Selection",
282 icon='SNAP_INCREMENT')
283 # 8 - TOP
284 pie.operator("object.origin_set", text="Origin To Geometry",
285 icon='NONE').type = 'ORIGIN_GEOMETRY'
286 # 7 - TOP - LEFT
287 pie.operator("object.origin_set", text="Geometry To Origin",
288 icon='NONE').type = 'GEOMETRY_ORIGIN'
291 classes = (
292 PIE_MT_OriginPivot,
293 PIE_OT_PivotToSelection,
294 PIE_OT_PivotBottom,
295 PIE_OT_PivotToCursor_edit,
296 PIE_OT_OriginToMass_edit,
297 PIE_OT_PivotBottom_edit,
298 PIE_OT_OriginToGeometry_edit,
299 PIE_OT_GeometryToOrigin_edit,
300 PIE_OT_SetOriginToSelected_edit
303 addon_keymaps = []
306 def register():
307 for cls in classes:
308 bpy.utils.register_class(cls)
310 wm = bpy.context.window_manager
311 if wm.keyconfigs.addon:
312 # Origin/Pivot
313 km = wm.keyconfigs.addon.keymaps.new(name='3D View Generic', space_type='VIEW_3D')
314 kmi = km.keymap_items.new('wm.call_menu_pie', 'X', 'PRESS', ctrl=True, alt=True)
315 kmi.properties.name = "ORIGIN_MT_pivotmenu"
316 addon_keymaps.append((km, kmi))
319 def unregister():
320 for cls in classes:
321 bpy.utils.unregister_class(cls)
323 wm = bpy.context.window_manager
324 kc = wm.keyconfigs.addon
325 if kc:
326 for km, kmi in addon_keymaps:
327 km.keymap_items.remove(kmi)
328 addon_keymaps.clear()
331 if __name__ == "__main__":
332 register()