1 # SPDX-License-Identifier: GPL-2.0-or-later
4 "name": "Hotkey: 'Ctrl Alt X'",
5 "description": "Origin Snap/Place Menu",
6 "author": "pitiwazou, meta-androcto",
12 "category": "Origin Pie"
16 from bpy
.types
import (
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'}
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
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'}
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
62 for x
in o
.data
.vertices
:
69 for x
in o
.data
.vertices
:
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'}
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
96 for x
in o
.data
.vertices
:
103 for x
in o
.data
.vertices
:
107 bpy
.ops
.object.mode_set(mode
='EDIT')
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'}
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')
131 # Origin to Center of Mass Edit Mode
132 class PIE_OT_OriginToMass_edit(Operator
):
133 bl_idname
= "object.origintomass_edit"
135 bl_description
= "Origin to Center of Mass"
136 bl_options
= {'REGISTER', 'UNDO'}
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')
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'}
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')
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'}
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')
188 # Origin To Selected Edit Mode #
189 def vfeOrigin_pie(context
):
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
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"
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
)
218 self
.report({"ERROR"}, "Set Origin to Selected could not be performed")
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
):
232 pie
= layout
.menu_pie()
233 if obj
and obj
.type == 'MESH' and obj
.mode
in {'OBJECT'}:
235 pie
.operator("object.origin_set", text
="Origin to Center of Mass",
236 icon
='NONE').type = 'ORIGIN_CENTER_OF_MASS'
238 pie
.operator("object.origin_set", text
="Origin to Cursor",
239 icon
='PIVOT_CURSOR').type = 'ORIGIN_CURSOR'
241 pie
.operator("object.pivotobottom", text
="Origin to Bottom",
244 pie
.operator("object.pivot2selection", text
="Origin To Selection",
245 icon
='SNAP_INCREMENT')
247 pie
.operator("object.origin_set", text
="Geometry To Origin",
248 icon
='NONE').type = 'GEOMETRY_ORIGIN'
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'}:
255 pie
.operator("object.origintomass_edit", text
="Origin to Center of Mass",
258 pie
.operator("object.pivot2cursor_edit", text
="Origin to Cursor",
261 pie
.operator("object.pivotobottom_edit", text
="Origin to Bottom",
264 pie
.operator("object.setorigintoselected_edit", text
="Origin To Selected",
265 icon
='SNAP_INCREMENT')
267 pie
.operator("object.geometrytoorigin_edit", text
="Geometry To Origin",
270 pie
.operator("object.origintogeometry_edit", text
="Origin To Geometry",
275 pie
.operator("object.origin_set", text
="Origin to Center of Mass",
276 icon
='NONE').type = 'ORIGIN_CENTER_OF_MASS'
278 pie
.operator("object.origin_set", text
="Origin To 3D Cursor",
279 icon
='PIVOT_CURSOR').type = 'ORIGIN_CURSOR'
281 pie
.operator("object.pivot2selection", text
="Origin To Selection",
282 icon
='SNAP_INCREMENT')
284 pie
.operator("object.origin_set", text
="Origin To Geometry",
285 icon
='NONE').type = 'ORIGIN_GEOMETRY'
287 pie
.operator("object.origin_set", text
="Geometry To Origin",
288 icon
='NONE').type = 'GEOMETRY_ORIGIN'
293 PIE_OT_PivotToSelection
,
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
308 bpy
.utils
.register_class(cls
)
310 wm
= bpy
.context
.window_manager
311 if wm
.keyconfigs
.addon
:
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
))
321 bpy
.utils
.unregister_class(cls
)
323 wm
= bpy
.context
.window_manager
324 kc
= wm
.keyconfigs
.addon
326 for km
, kmi
in addon_keymaps
:
327 km
.keymap_items
.remove(kmi
)
328 addon_keymaps
.clear()
331 if __name__
== "__main__":