1 # SPDX-FileCopyrightText: 2016-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
6 "name": "Hotkey: 'Shift O'",
7 "description": "Proportional Object/Edit Tools",
8 "author": "pitiwazou, meta-androcto",
10 "blender": (2, 80, 0),
11 "location": "3D View Object & Edit modes",
14 "category": "Proportional Edit Pie"
18 from bpy
.types
import (
24 # Proportional Edit Object
25 class PIE_OT_ProportionalEditObj(Operator
):
26 bl_idname
= "proportional_obj.active"
27 bl_label
= "Proportional Edit Object"
28 bl_options
= {'REGISTER', 'UNDO'}
30 def execute(self
, context
):
31 ts
= context
.tool_settings
33 if ts
.use_proportional_edit_objects
is True:
34 ts
.use_proportional_edit_objects
= False
36 elif ts
.use_proportional_edit_objects
is False:
37 ts
.use_proportional_edit_objects
= True
42 class PIE_OT_ProportionalSmoothObj(Operator
):
43 bl_idname
= "proportional_obj.smooth"
44 bl_label
= "Proportional Smooth Object"
45 bl_options
= {'REGISTER', 'UNDO'}
47 def execute(self
, context
):
48 ts
= context
.tool_settings
49 if ts
.use_proportional_edit_objects
is False:
50 ts
.use_proportional_edit_objects
= True
51 ts
.proportional_edit_falloff
= 'SMOOTH'
53 if ts
.proportional_edit_falloff
!= 'SMOOTH':
54 ts
.proportional_edit_falloff
= 'SMOOTH'
58 class PIE_OT_ProportionalSphereObj(Operator
):
59 bl_idname
= "proportional_obj.sphere"
60 bl_label
= "Proportional Sphere Object"
61 bl_options
= {'REGISTER', 'UNDO'}
63 def execute(self
, context
):
64 ts
= context
.tool_settings
65 if ts
.use_proportional_edit_objects
is False:
66 ts
.use_proportional_edit_objects
= True
67 ts
.proportional_edit_falloff
= 'SPHERE'
69 if ts
.proportional_edit_falloff
!= 'SPHERE':
70 ts
.proportional_edit_falloff
= 'SPHERE'
74 class PIE_OT_ProportionalRootObj(Operator
):
75 bl_idname
= "proportional_obj.root"
76 bl_label
= "Proportional Root Object"
77 bl_options
= {'REGISTER', 'UNDO'}
79 def execute(self
, context
):
80 ts
= context
.tool_settings
81 if ts
.use_proportional_edit_objects
is False:
82 ts
.use_proportional_edit_objects
= True
83 ts
.proportional_edit_falloff
= 'ROOT'
85 if ts
.proportional_edit_falloff
!= 'ROOT':
86 ts
.proportional_edit_falloff
= 'ROOT'
90 class PIE_OT_ProportionalSharpObj(Operator
):
91 bl_idname
= "proportional_obj.sharp"
92 bl_label
= "Proportional Sharp Object"
93 bl_options
= {'REGISTER', 'UNDO'}
95 def execute(self
, context
):
96 ts
= context
.tool_settings
97 if ts
.use_proportional_edit_objects
is False:
98 ts
.use_proportional_edit_objects
= True
99 ts
.proportional_edit_falloff
= 'SHARP'
101 if ts
.proportional_edit_falloff
!= 'SHARP':
102 ts
.proportional_edit_falloff
= 'SHARP'
106 class PIE_OT_ProportionalLinearObj(Operator
):
107 bl_idname
= "proportional_obj.linear"
108 bl_label
= "Proportional Linear Object"
109 bl_options
= {'REGISTER', 'UNDO'}
111 def execute(self
, context
):
112 ts
= context
.tool_settings
113 if ts
.use_proportional_edit_objects
is False:
114 ts
.use_proportional_edit_objects
= True
115 ts
.proportional_edit_falloff
= 'LINEAR'
117 if ts
.proportional_edit_falloff
!= 'LINEAR':
118 ts
.proportional_edit_falloff
= 'LINEAR'
122 class PIE_OT_ProportionalConstantObj(Operator
):
123 bl_idname
= "proportional_obj.constant"
124 bl_label
= "Proportional Constant Object"
125 bl_options
= {'REGISTER', 'UNDO'}
127 def execute(self
, context
):
128 ts
= context
.tool_settings
129 if ts
.use_proportional_edit_objects
is False:
130 ts
.use_proportional_edit_objects
= True
131 ts
.proportional_edit_falloff
= 'CONSTANT'
133 if ts
.proportional_edit_falloff
!= 'CONSTANT':
134 ts
.proportional_edit_falloff
= 'CONSTANT'
138 class PIE_OT_ProportionalRandomObj(Operator
):
139 bl_idname
= "proportional_obj.random"
140 bl_label
= "Proportional Random Object"
141 bl_options
= {'REGISTER', 'UNDO'}
143 def execute(self
, context
):
144 ts
= context
.tool_settings
145 if ts
.use_proportional_edit_objects
is False:
146 ts
.use_proportional_edit_objects
= True
147 ts
.proportional_edit_falloff
= 'RANDOM'
149 if ts
.proportional_edit_falloff
!= 'RANDOM':
150 ts
.proportional_edit_falloff
= 'RANDOM'
154 class PIE_OT_ProportionalInverseSquareObj(Operator
):
155 bl_idname
= "proportional_obj.inversesquare"
156 bl_label
= "Proportional Random Object"
157 bl_options
= {'REGISTER', 'UNDO'}
159 def execute(self
, context
):
160 ts
= context
.tool_settings
161 if ts
.use_proportional_edit_objects
is False:
162 ts
.use_proportional_edit_objects
= True
163 ts
.proportional_edit_falloff
= 'INVERSE_SQUARE'
165 if ts
.proportional_edit_falloff
!= 'INVERSE_SQUARE':
166 ts
.proportional_edit_falloff
= 'INVERSE_SQUARE'
170 # Proportional Edit Edit Mode
171 class PIE_OT_ProportionalEditEdt(Operator
):
172 bl_idname
= "proportional_edt.active"
173 bl_label
= "Proportional Edit EditMode"
174 bl_options
= {'REGISTER', 'UNDO'}
176 def execute(self
, context
):
177 ts
= context
.tool_settings
178 ts
.use_proportional_edit ^
= 1
182 class PIE_OT_ProportionalConnectedEdt(Operator
):
183 bl_idname
= "proportional_edt.connected"
184 bl_label
= "Proportional Connected EditMode"
185 bl_options
= {'REGISTER', 'UNDO'}
187 def execute(self
, context
):
188 ts
= context
.tool_settings
189 ts
.use_proportional_connected ^
= 1
193 class PIE_OT_ProportionalProjectedEdt(Operator
):
194 bl_idname
= "proportional_edt.projected"
195 bl_label
= "Proportional projected EditMode"
196 bl_options
= {'REGISTER', 'UNDO'}
198 def execute(self
, context
):
199 ts
= context
.tool_settings
200 ts
.use_proportional_projected ^
= 1
204 class PIE_OT_ProportionalSmoothEdt(Operator
):
205 bl_idname
= "proportional_edt.smooth"
206 bl_label
= "Proportional Smooth EditMode"
207 bl_options
= {'REGISTER', 'UNDO'}
209 def execute(self
, context
):
210 ts
= context
.tool_settings
211 ts
.use_proportional_edit
= True
212 ts
.proportional_edit_falloff
= 'SMOOTH'
216 class PIE_OT_ProportionalSphereEdt(Operator
):
217 bl_idname
= "proportional_edt.sphere"
218 bl_label
= "Proportional Sphere EditMode"
219 bl_options
= {'REGISTER', 'UNDO'}
221 def execute(self
, context
):
222 ts
= context
.tool_settings
223 ts
.use_proportional_edit
= True
224 ts
.proportional_edit_falloff
= 'SPHERE'
228 class PIE_OT_ProportionalRootEdt(Operator
):
229 bl_idname
= "proportional_edt.root"
230 bl_label
= "Proportional Root EditMode"
231 bl_options
= {'REGISTER', 'UNDO'}
233 def execute(self
, context
):
234 ts
= context
.tool_settings
235 ts
.use_proportional_edit
= True
236 ts
.proportional_edit_falloff
= 'ROOT'
240 class PIE_OT_ProportionalSharpEdt(Operator
):
241 bl_idname
= "proportional_edt.sharp"
242 bl_label
= "Proportional Sharp EditMode"
243 bl_options
= {'REGISTER', 'UNDO'}
245 def execute(self
, context
):
246 ts
= context
.tool_settings
247 ts
.use_proportional_edit
= True
248 ts
.proportional_edit_falloff
= 'SHARP'
252 class PIE_OT_ProportionalLinearEdt(Operator
):
253 bl_idname
= "proportional_edt.linear"
254 bl_label
= "Proportional Linear EditMode"
255 bl_options
= {'REGISTER', 'UNDO'}
257 def execute(self
, context
):
258 ts
= context
.tool_settings
259 ts
.use_proportional_edit
= True
260 ts
.proportional_edit_falloff
= 'LINEAR'
264 class PIE_OT_ProportionalConstantEdt(Operator
):
265 bl_idname
= "proportional_edt.constant"
266 bl_label
= "Proportional Constant EditMode"
267 bl_options
= {'REGISTER', 'UNDO'}
269 def execute(self
, context
):
270 ts
= context
.tool_settings
271 ts
.use_proportional_edit
= True
272 ts
.proportional_edit_falloff
= 'CONSTANT'
276 class PIE_OT_ProportionalRandomEdt(Operator
):
277 bl_idname
= "proportional_edt.random"
278 bl_label
= "Proportional Random EditMode"
279 bl_options
= {'REGISTER', 'UNDO'}
281 def execute(self
, context
):
282 ts
= context
.tool_settings
283 ts
.use_proportional_edit
= True
284 ts
.proportional_edit_falloff
= 'RANDOM'
288 class PIE_OT_ProportionalInverseSquareEdt(Operator
):
289 bl_idname
= "proportional_edt.inversesquare"
290 bl_label
= "Proportional Inverese Square EditMode"
291 bl_options
= {'REGISTER', 'UNDO'}
293 def execute(self
, context
):
294 ts
= context
.tool_settings
295 ts
.use_proportional_edit
= True
296 ts
.proportional_edit_falloff
= 'INVERSE_SQUARE'
300 # Pie ProportionalEditObj - O
301 class PIE_MT_ProportionalObj(Menu
):
302 bl_idname
= "PIE_MT_proportional_obj"
303 bl_label
= "Pie Proportional Obj"
305 def draw(self
, context
):
307 pie
= layout
.menu_pie()
309 pie
.operator("proportional_obj.smooth", text
="Smooth", icon
='SMOOTHCURVE')
311 pie
.operator("proportional_obj.sphere", text
="Sphere", icon
='SPHERECURVE')
313 pie
.operator("proportional_obj.linear", text
="Linear", icon
='LINCURVE')
315 pie
.prop(context
.tool_settings
, "use_proportional_edit_objects", text
="Proportional On/Off")
317 pie
.operator("proportional_obj.root", text
="Root", icon
='ROOTCURVE')
319 pie
.operator("proportional_obj.inversesquare", text
="Inverse Square", icon
='INVERSESQUARECURVE')
321 pie
.operator("proportional_obj.sharp", text
="Sharp", icon
='SHARPCURVE')
323 pie
.menu("PIE_MT_proportional_moreob", text
="More", icon
='LINCURVE')
326 # Pie ProportionalEditEdt - O
327 class PIE_MT_ProportionalEdt(Menu
):
328 bl_idname
= "PIE_MT_proportional_edt"
329 bl_label
= "Pie Proportional Edit"
331 def draw(self
, context
):
333 pie
= layout
.menu_pie()
335 pie
.operator("proportional_edt.smooth", text
="Smooth", icon
='SMOOTHCURVE')
337 pie
.operator("proportional_edt.sphere", text
="Sphere", icon
='SPHERECURVE')
339 pie
.operator("proportional_edt.inversesquare", text
="Inverse Square", icon
='INVERSESQUARECURVE')
341 pie
.operator("proportional_edt.active", text
="Proportional On/Off", icon
='PROP_ON')
343 pie
.operator("proportional_edt.connected", text
="Connected", icon
='PROP_CON')
345 pie
.operator("proportional_edt.projected", text
="Projected", icon
='PROP_PROJECTED')
347 pie
.operator("proportional_edt.root", text
="Root", icon
='ROOTCURVE')
349 pie
.menu("PIE_MT_proportional_more", text
="More", icon
='LINCURVE')
352 # Pie ProportionalEditEdt - O
353 class PIE_MT_ProportionalMore(Menu
):
354 bl_idname
= "PIE_MT_proportional_more"
355 bl_label
= "Pie Proportional More"
357 def draw(self
, context
):
359 pie
= layout
.menu_pie()
360 box
= pie
.split().column()
361 box
.operator("proportional_edt.sharp", text
="Sharp", icon
='SHARPCURVE')
362 box
.operator("proportional_edt.linear", text
="Linear", icon
='LINCURVE')
363 box
.operator("proportional_edt.constant", text
="Constant", icon
='NOCURVE')
364 box
.operator("proportional_edt.random", text
="Random", icon
='RNDCURVE')
367 # Pie ProportionalEditEdt2
368 class PIE_MT_proportionalmoreob(Menu
):
369 bl_idname
= "PIE_MT_proportional_moreob"
370 bl_label
= "Pie Proportional More"
372 def draw(self
, context
):
374 pie
= layout
.menu_pie()
375 box
= pie
.split().column()
376 box
.operator("proportional_obj.constant", text
="Constant", icon
='NOCURVE')
377 box
.operator("proportional_obj.random", text
="Random", icon
='RNDCURVE')
381 PIE_OT_ProportionalEditObj
,
382 PIE_OT_ProportionalSmoothObj
,
383 PIE_OT_ProportionalSphereObj
,
384 PIE_OT_ProportionalRootObj
,
385 PIE_OT_ProportionalSharpObj
,
386 PIE_OT_ProportionalLinearObj
,
387 PIE_OT_ProportionalConstantObj
,
388 PIE_OT_ProportionalRandomObj
,
389 PIE_OT_ProportionalInverseSquareObj
,
390 PIE_OT_ProportionalEditEdt
,
391 PIE_OT_ProportionalConnectedEdt
,
392 PIE_OT_ProportionalProjectedEdt
,
393 PIE_OT_ProportionalSmoothEdt
,
394 PIE_OT_ProportionalSphereEdt
,
395 PIE_OT_ProportionalRootEdt
,
396 PIE_OT_ProportionalSharpEdt
,
397 PIE_OT_ProportionalLinearEdt
,
398 PIE_OT_ProportionalConstantEdt
,
399 PIE_OT_ProportionalRandomEdt
,
400 PIE_OT_ProportionalInverseSquareEdt
,
401 PIE_MT_ProportionalObj
,
402 PIE_MT_ProportionalEdt
,
403 PIE_MT_ProportionalMore
,
404 PIE_MT_proportionalmoreob
412 bpy
.utils
.register_class(cls
)
414 wm
= bpy
.context
.window_manager
415 if wm
.keyconfigs
.addon
:
416 # ProportionalEditObj
417 km
= wm
.keyconfigs
.addon
.keymaps
.new(name
='Object Mode')
418 kmi
= km
.keymap_items
.new('wm.call_menu_pie', 'O', 'PRESS', shift
=True)
419 kmi
.properties
.name
= "PIE_MT_proportional_obj"
420 addon_keymaps
.append((km
, kmi
))
422 # ProportionalEditEdt
423 km
= wm
.keyconfigs
.addon
.keymaps
.new(name
='Mesh')
424 kmi
= km
.keymap_items
.new('wm.call_menu_pie', 'O', 'PRESS', shift
=True)
425 kmi
.properties
.name
= "PIE_MT_proportional_edt"
426 addon_keymaps
.append((km
, kmi
))
431 bpy
.utils
.unregister_class(cls
)
433 wm
= bpy
.context
.window_manager
434 kc
= wm
.keyconfigs
.addon
436 for km
, kmi
in addon_keymaps
:
437 km
.keymap_items
.remove(kmi
)
438 addon_keymaps
.clear()
441 if __name__
== "__main__":