Import images: add file handler
[blender-addons.git] / space_view3d_pie_menus / pie_origin.py
blob1fde987df0ac9fe5daf116459fd8c69c3aa4f6a2
1 # SPDX-FileCopyrightText: 2016-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 bl_info = {
6 "name": "Hotkey: 'Ctrl Alt X'",
7 "description": "Origin Snap/Place Menu",
8 "author": "pitiwazou, meta-androcto",
9 "version": (0, 1, 2),
10 "blender": (2, 80, 0),
11 "location": "3D View",
12 "warning": "",
13 "doc_url": "",
14 "category": "Origin Pie"
17 import bpy
18 from bpy.types import (
19 Menu,
20 Operator,
24 # Pivot to selection
25 class PIE_OT_PivotToSelection(Operator):
26 bl_idname = "object.pivot2selection"
27 bl_label = "Pivot To Selection"
28 bl_description = "Pivot Point To Selection"
29 bl_options = {'REGISTER', 'UNDO'}
31 @classmethod
32 def poll(cls, context):
33 return context.active_object is not None
35 def execute(self, context):
36 saved_location = context.scene.cursor.location.copy()
37 bpy.ops.view3d.snap_cursor_to_selected()
38 bpy.ops.object.mode_set(mode='OBJECT')
39 bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
40 context.scene.cursor.location = saved_location
42 return {'FINISHED'}
44 # Pivot to Bottom
46 def origin_to_bottom(ob):
47 if ob.type != 'MESH':
48 return
50 init = 0
51 for x in ob.data.vertices:
52 if init == 0:
53 a = x.co.z
54 init = 1
55 elif x.co.z < a:
56 a = x.co.z
58 for x in ob.data.vertices:
59 x.co.z -= a
61 ob.location.z += a
63 class PIE_OT_PivotBottom(Operator):
64 bl_idname = "object.pivotobottom"
65 bl_label = "Pivot To Bottom"
66 bl_description = ("Set the Pivot Point To Lowest Point\n"
67 "Needs an Active Object of the Mesh type")
68 bl_options = {'REGISTER', 'UNDO'}
70 @classmethod
71 def poll(cls, context):
72 obj = context.active_object
73 return obj is not None and obj.type == "MESH"
75 def execute(self, context):
76 bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
77 bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
79 for ob in context.selected_objects:
80 origin_to_bottom(ob)
82 return {'FINISHED'}
85 # Pivot to Bottom
86 class PIE_OT_PivotBottom_edit(Operator):
87 bl_idname = "object.pivotobottom_edit"
88 bl_label = "Pivot To Bottom"
89 bl_description = ("Set the Pivot Point To Lowest Point\n"
90 "Needs an Active Object of the Mesh type")
91 bl_options = {'REGISTER', 'UNDO'}
93 @classmethod
94 def poll(cls, context):
95 obj = context.active_object
96 return obj is not None and obj.type == "MESH"
98 def execute(self, context):
99 bpy.ops.object.mode_set(mode='OBJECT')
100 bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)
101 bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
103 for ob in context.selected_objects:
104 origin_to_bottom(ob)
106 bpy.ops.object.mode_set(mode='EDIT')
108 return {'FINISHED'}
111 # Pivot to Cursor Edit Mode
112 class PIE_OT_PivotToCursor_edit(Operator):
113 bl_idname = "object.pivot2cursor_edit"
114 bl_label = "Pivot To Cursor"
115 bl_description = "Pivot Point To Cursor"
116 bl_options = {'REGISTER', 'UNDO'}
118 @classmethod
119 def poll(cls, context):
120 return context.active_object is not None
122 def execute(self, context):
123 bpy.ops.object.mode_set(mode='OBJECT')
124 bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
125 bpy.ops.object.mode_set(mode='EDIT')
127 return {'FINISHED'}
130 # Origin to Center of Mass Edit Mode
131 class PIE_OT_OriginToMass_edit(Operator):
132 bl_idname = "object.origintomass_edit"
133 bl_label = "Origin"
134 bl_description = "Origin to Center of Mass"
135 bl_options = {'REGISTER', 'UNDO'}
137 @classmethod
138 def poll(cls, context):
139 return context.active_object is not None
141 def execute(self, context):
142 bpy.ops.object.mode_set(mode='OBJECT')
143 bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS', center='MEDIAN')
144 bpy.ops.object.mode_set(mode='EDIT')
146 return {'FINISHED'}
149 # Origin to Geometry Edit Mode
150 class PIE_OT_OriginToGeometry_edit(Operator):
151 bl_idname = "object.origintogeometry_edit"
152 bl_label = "Origin to Geometry"
153 bl_description = "Origin to Geometry"
154 bl_options = {'REGISTER', 'UNDO'}
156 @classmethod
157 def poll(cls, context):
158 return context.active_object is not None
160 def execute(self, context):
161 bpy.ops.object.mode_set(mode='OBJECT')
162 bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='MEDIAN')
163 bpy.ops.object.mode_set(mode='EDIT')
165 return {'FINISHED'}
168 # Origin to Geometry Edit Mode
169 class PIE_OT_GeometryToOrigin_edit(Operator):
170 bl_idname = "object.geometrytoorigin_edit"
171 bl_label = "Geometry to Origin"
172 bl_description = "Geometry to Origin"
173 bl_options = {'REGISTER', 'UNDO'}
175 @classmethod
176 def poll(cls, context):
177 return context.active_object is not None
179 def execute(self, context):
180 bpy.ops.object.mode_set(mode='OBJECT')
181 bpy.ops.object.origin_set(type='GEOMETRY_ORIGIN', center='MEDIAN')
182 bpy.ops.object.mode_set(mode='EDIT')
184 return {'FINISHED'}
187 # Origin To Selected Edit Mode #
188 def vfeOrigin_pie(context):
189 try:
190 cursorPositionX = context.scene.cursor.location[0]
191 cursorPositionY = context.scene.cursor.location[1]
192 cursorPositionZ = context.scene.cursor.location[2]
193 bpy.ops.view3d.snap_cursor_to_selected()
194 bpy.ops.object.mode_set()
195 bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='MEDIAN')
196 bpy.ops.object.mode_set(mode='EDIT')
197 context.scene.cursor.location[0] = cursorPositionX
198 context.scene.cursor.location[1] = cursorPositionY
199 context.scene.cursor.location[2] = cursorPositionZ
200 return True
201 except:
202 return False
205 class PIE_OT_SetOriginToSelected_edit(Operator):
206 bl_idname = "object.setorigintoselected_edit"
207 bl_label = "Set Origin to Selected"
208 bl_description = "Set Origin to Selected"
210 @classmethod
211 def poll(cls, context):
212 return (context.area.type == "VIEW_3D" and context.active_object is not None)
214 def execute(self, context):
215 check = vfeOrigin_pie(context)
216 if not check:
217 self.report({"ERROR"}, "Set Origin to Selected could not be performed")
218 return {'CANCELLED'}
220 return {'FINISHED'}
223 # Pie Origin/Pivot - Shift + S
224 class PIE_MT_OriginPivot(Menu):
225 bl_idname = "ORIGIN_MT_pivotmenu"
226 bl_label = "Origin Menu"
228 def draw(self, context):
229 layout = self.layout
230 obj = context.object
231 pie = layout.menu_pie()
232 if obj and obj.type == 'MESH' and obj.mode in {'OBJECT'}:
233 # 4 - LEFT
234 pie.operator("object.origin_set", text="Origin to Center of Mass",
235 icon='NONE').type = 'ORIGIN_CENTER_OF_MASS'
236 # 6 - RIGHT
237 pie.operator("object.origin_set", text="Origin to Cursor",
238 icon='PIVOT_CURSOR').type = 'ORIGIN_CURSOR'
239 # 2 - BOTTOM
240 pie.operator("object.pivotobottom", text="Origin to Bottom",
241 icon='TRIA_DOWN')
242 # 8 - TOP
243 pie.operator("object.pivot2selection", text="Origin To Selection",
244 icon='SNAP_INCREMENT')
245 # 7 - TOP - LEFT
246 pie.operator("object.origin_set", text="Geometry To Origin",
247 icon='NONE').type = 'GEOMETRY_ORIGIN'
248 # 9 - TOP - RIGHT
249 pie.operator("object.origin_set", text="Origin To Geometry",
250 icon='NONE').type = 'ORIGIN_GEOMETRY'
252 elif obj and obj.type == 'MESH' and obj.mode in {'EDIT'}:
253 # 4 - LEFT
254 pie.operator("object.origintomass_edit", text="Origin to Center of Mass",
255 icon='NONE')
256 # 6 - RIGHT
257 pie.operator("object.pivot2cursor_edit", text="Origin to Cursor",
258 icon='PIVOT_CURSOR')
259 # 2 - BOTTOM
260 pie.operator("object.pivotobottom_edit", text="Origin to Bottom",
261 icon='TRIA_DOWN')
262 # 8 - TOP
263 pie.operator("object.setorigintoselected_edit", text="Origin To Selected",
264 icon='SNAP_INCREMENT')
265 # 7 - TOP - LEFT
266 pie.operator("object.geometrytoorigin_edit", text="Geometry To Origin",
267 icon='NONE')
268 # 9 - TOP - RIGHT
269 pie.operator("object.origintogeometry_edit", text="Origin To Geometry",
270 icon='NONE')
272 else:
273 # 4 - LEFT
274 pie.operator("object.origin_set", text="Origin to Center of Mass",
275 icon='NONE').type = 'ORIGIN_CENTER_OF_MASS'
276 # 6 - RIGHT
277 pie.operator("object.origin_set", text="Origin To 3D Cursor",
278 icon='PIVOT_CURSOR').type = 'ORIGIN_CURSOR'
279 # 2 - BOTTOM
280 pie.operator("object.pivot2selection", text="Origin To Selection",
281 icon='SNAP_INCREMENT')
282 # 8 - TOP
283 pie.operator("object.origin_set", text="Origin To Geometry",
284 icon='NONE').type = 'ORIGIN_GEOMETRY'
285 # 7 - TOP - LEFT
286 pie.operator("object.origin_set", text="Geometry To Origin",
287 icon='NONE').type = 'GEOMETRY_ORIGIN'
290 classes = (
291 PIE_MT_OriginPivot,
292 PIE_OT_PivotToSelection,
293 PIE_OT_PivotBottom,
294 PIE_OT_PivotToCursor_edit,
295 PIE_OT_OriginToMass_edit,
296 PIE_OT_PivotBottom_edit,
297 PIE_OT_OriginToGeometry_edit,
298 PIE_OT_GeometryToOrigin_edit,
299 PIE_OT_SetOriginToSelected_edit
302 addon_keymaps = []
305 def register():
306 for cls in classes:
307 bpy.utils.register_class(cls)
309 wm = bpy.context.window_manager
310 if wm.keyconfigs.addon:
311 # Origin/Pivot
312 km = wm.keyconfigs.addon.keymaps.new(name='3D View Generic', space_type='VIEW_3D')
313 kmi = km.keymap_items.new('wm.call_menu_pie', 'X', 'PRESS', ctrl=True, alt=True)
314 kmi.properties.name = "ORIGIN_MT_pivotmenu"
315 addon_keymaps.append((km, kmi))
318 def unregister():
319 for cls in classes:
320 bpy.utils.unregister_class(cls)
322 wm = bpy.context.window_manager
323 kc = wm.keyconfigs.addon
324 if kc:
325 for km, kmi in addon_keymaps:
326 km.keymap_items.remove(kmi)
327 addon_keymaps.clear()
330 if __name__ == "__main__":
331 register()