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 #####
21 "name": "Selection Restrictor",
22 "author": "Ales Sidenko",
24 "location": "3d viewer header",
26 "description": "This addon helps to restrict the selection of objects by type. "
27 "Please email me if you find a bug (sidenkoai@gmail.com)",
32 from bpy
.types
import (
36 from bpy
.props
import (
41 from bpy
.app
.handlers
import persistent
44 curve
= 'OUTLINER_OB_CURVE'
45 arm
= 'OUTLINER_OB_ARMATURE'
46 empty
= 'OUTLINER_OB_EMPTY'
47 cam
= 'OUTLINER_OB_CAMERA'
48 lamp
= 'OUTLINER_OB_LIGHT'
49 lat
= 'OUTLINER_OB_LATTICE'
50 font
= 'OUTLINER_OB_FONT'
51 meta
= 'OUTLINER_OB_META'
52 surf
= 'OUTLINER_OB_SURFACE'
53 speak
= 'OUTLINER_OB_SPEAKER'
56 show_restrictor
= False
60 # checking properties in scene to update icons when opening file
61 # or switching between scenes (executing in end of script)
64 def check_restrictors(dummy
):
78 global meshrestrictorenabled
79 global curverestrictorenabled
80 global armrestrictorenabled
81 global emptyrestrictorenabled
82 global camrestrictorenabled
83 global lamprestrictorenabled
84 global latrestrictorenabled
85 global fontrestrictorenabled
86 global metarestrictorenabled
87 global surfrestrictorenabled
88 global speakrestrictorenabled
91 if bpy
.context
.scene
.get('show_restrictor') is not None:
92 show_restrictor
= False
95 show_restrictor
= True
99 if bpy
.context
.scene
.get('meshrestrictor') is None:
100 meshrestrictorenabled
= True
103 meshrestrictorenabled
= False
106 if bpy
.context
.scene
.get('curverestrictor') is None:
107 curverestrictorenabled
= True
108 curve
= 'OUTLINER_OB_CURVE'
110 curverestrictorenabled
= False
113 if bpy
.context
.scene
.get('armrestrictor') is None:
114 armrestrictorenabled
= True
115 arm
= 'OUTLINER_OB_ARMATURE'
117 armrestrictorenabled
= False
118 arm
= 'ARMATURE_DATA'
121 if bpy
.context
.scene
.get('emptyrestrictor') is None:
122 emptyrestrictorenabled
= True
123 empty
= 'OUTLINER_OB_EMPTY'
125 emptyrestrictorenabled
= False
129 if bpy
.context
.scene
.get('camrestrictor') is None:
130 camrestrictorenabled
= True
131 cam
= 'OUTLINER_OB_CAMERA'
133 camrestrictorenabled
= False
136 if bpy
.context
.scene
.get('lamprestrictor') is None:
137 lamprestrictorenabled
= True
138 lamp
= 'OUTLINER_OB_LIGHT'
140 lamprestrictorenabled
= False
144 if bpy
.context
.scene
.get('latrestrictor') is None:
145 latrestrictorenabled
= True
146 lat
= 'OUTLINER_OB_LATTICE'
148 latrestrictorenabled
= False
152 if bpy
.context
.scene
.get('fontrestrictor') is None:
153 fontrestrictorenabled
= True
154 font
= 'OUTLINER_OB_FONT'
156 fontrestrictorenabled
= False
160 if bpy
.context
.scene
.get('metarestrictor') is None:
161 metarestrictorenabled
= True
162 meta
= 'OUTLINER_OB_META'
164 metarestrictorenabled
= False
168 if bpy
.context
.scene
.get('surfrestrictor') is None:
169 surfrestrictorenabled
= True
170 surf
= 'OUTLINER_OB_SURFACE'
172 surfrestrictorenabled
= False
173 surf
= 'SURFACE_DATA'
176 if bpy
.context
.scene
.get('speakrestrictor') is None:
177 speakrestrictorenabled
= True
178 speak
= 'OUTLINER_OB_SPEAKER'
180 speakrestrictorenabled
= False
185 # Show / Hide buttons
187 class RestrictorShow(Operator
):
188 bl_idname
= "restrictor.show"
189 bl_label
= "Show/Hide Selection Restrictors"
190 bl_option
= {'REGISTER', 'UNDO'}
191 bl_description
= "Show/Hide Selection Restrictors"
193 hide
= StringProperty()
195 def execute(self
, context
):
198 if bpy
.context
.scene
.get('show_restrictor') is None:
199 bpy
.context
.scene
['show_restrictor'] = 1
202 if bpy
.context
.scene
.get('show_restrictor') is not None:
203 del bpy
.context
.scene
['show_restrictor']
209 # Ignore the restrictor for selected objects
211 class IgnoreRestrictors(Operator
):
212 bl_idname
= "ignore.restrictors"
213 bl_label
= "Ignore Restrictor by Selected Objects"
214 bl_option
= {'REGISTER', 'UNDO'}
215 bl_description
= "Ignore or do not ignore Restrictor by selected objects"
216 ignore
= BoolProperty()
218 def execute(self
, context
):
219 if self
.ignore
is True:
220 for ob
in bpy
.context
.selected_objects
:
221 ob
['ignore_restrictors'] = 1
223 for ob
in bpy
.context
.selected_objects
:
224 if ob
.get('ignore_restrictors') is not None:
225 del ob
["ignore_restrictors"]
226 bpy
.ops
.refresh
.restrictors()
231 # Enable or Disable restrictors
235 class RestrictorMesh(Operator
):
236 bl_idname
= "restrictor.mesh"
237 bl_label
= "restrictor meshes"
238 bl_option
= {'REGISTER', 'UNDO'}
239 bl_description
= "Meshes selection restrictor"
240 mesh
= StringProperty()
242 def execute(self
, context
):
244 global meshrestrictorenabled
245 if bpy
.context
.scene
.get('meshrestrictor') is not None:
246 meshrestrictorenabled
= True
247 if bpy
.context
.scene
.get('meshrestrictor') is not None:
248 del bpy
.context
.scene
['meshrestrictor']
250 for ob
in bpy
.context
.scene
.objects
:
251 if ob
.type == 'MESH':
252 if ob
.get('ignore_restrictors') is None:
253 ob
.hide_select
= False
256 meshrestrictorenabled
= False
257 bpy
.context
.scene
['meshrestrictor'] = 1
259 for ob
in bpy
.context
.scene
.objects
:
260 if ob
.type == 'MESH':
261 if ob
.get('ignore_restrictors') is None:
262 ob
.hide_select
= True
268 # Restrictor for Curves
270 class RestrictorCurve(Operator
):
271 bl_idname
= "restrictor.curve"
272 bl_label
= "restrictor curves"
273 bl_option
= {'REGISTER', 'UNDO'}
274 bl_description
= "Curves selection restrictor"
276 def execute(self
, context
):
278 global curverestrictorenabled
280 if bpy
.context
.scene
.get('curverestrictor') is not None:
281 curverestrictorenabled
= True
282 if bpy
.context
.scene
.get('curverestrictor') is not None:
283 del bpy
.context
.scene
['curverestrictor']
284 curve
= 'OUTLINER_OB_CURVE'
285 for ob
in bpy
.context
.scene
.objects
:
286 if ob
.type == 'CURVE':
287 if ob
.get('ignore_restrictors') is None:
288 ob
.hide_select
= False
291 curverestrictorenabled
= False
292 bpy
.context
.scene
['curverestrictor'] = 1
294 for ob
in bpy
.context
.scene
.objects
:
295 if ob
.type == 'CURVE':
296 if ob
.get('ignore_restrictors') is None:
297 ob
.hide_select
= True
303 # Restrictor for Armatures
305 class RestrictorArm(Operator
):
306 bl_idname
= "restrictor.arm"
307 bl_label
= "restrictor armatures"
308 bl_option
= {'REGISTER', 'UNDO'}
309 bl_description
= "Armatures selection restrictor"
311 def execute(self
, context
):
313 global armrestrictorenabled
315 if bpy
.context
.scene
.get('armrestrictor') is not None:
316 armrestrictorenabled
= True
317 if bpy
.context
.scene
.get('armrestrictor') is not None:
318 del bpy
.context
.scene
['armrestrictor']
319 arm
= 'OUTLINER_OB_ARMATURE'
320 for ob
in bpy
.context
.scene
.objects
:
321 if ob
.type == 'ARMATURE':
322 if ob
.get('ignore_restrictors') is None:
323 ob
.hide_select
= False
326 armrestrictorenabled
= False
327 bpy
.context
.scene
['armrestrictor'] = 1
328 arm
= 'ARMATURE_DATA'
329 for ob
in bpy
.context
.scene
.objects
:
330 if ob
.type == 'ARMATURE':
331 if ob
.get('ignore_restrictors') is None:
332 ob
.hide_select
= True
338 # Restrictor for Empties
340 class RestrictorEmpty(Operator
):
341 bl_idname
= "restrictor.empty"
342 bl_label
= "Restrictor Empties"
343 bl_option
= {'REGISTER', 'UNDO'}
344 bl_description
= "Empties selection restrictor"
346 def execute(self
, context
):
348 global emptyrestrictorenabled
350 if bpy
.context
.scene
.get('emptyrestrictor') is not None:
351 emptyrestrictorenabled
= True
352 if bpy
.context
.scene
.get('emptyrestrictor') is not None:
353 del bpy
.context
.scene
['emptyrestrictor']
354 empty
= 'OUTLINER_OB_EMPTY'
355 for ob
in bpy
.context
.scene
.objects
:
356 if ob
.type == 'EMPTY':
357 if ob
.get('ignore_restrictors') is None:
358 ob
.hide_select
= False
361 emptyrestrictorenabled
= False
362 bpy
.context
.scene
['emptyrestrictor'] = 1
364 for ob
in bpy
.context
.scene
.objects
:
365 if ob
.type == 'EMPTY':
366 if ob
.get('ignore_restrictors') is None:
367 ob
.hide_select
= True
373 # Restrictor for Cameras
375 class RestrictorCam(Operator
):
376 bl_idname
= "restrictor.cam"
377 bl_label
= "restrictor cameras"
378 bl_option
= {'REGISTER', 'UNDO'}
379 bl_description
= "Cameras selection restrictor"
381 def execute(self
, context
):
383 global camrestrictorenabled
385 if bpy
.context
.scene
.get('camrestrictor') is not None:
386 camrestrictorenabled
= True
387 if bpy
.context
.scene
.get('camrestrictor') is not None:
388 del bpy
.context
.scene
['camrestrictor']
389 cam
= 'OUTLINER_OB_CAMERA'
390 for ob
in bpy
.context
.scene
.objects
:
391 if ob
.type == 'CAMERA':
392 if ob
.get('ignore_restrictors') is None:
393 ob
.hide_select
= False
396 camrestrictorenabled
= False
397 bpy
.context
.scene
['camrestrictor'] = 1
399 for ob
in bpy
.context
.scene
.objects
:
400 if ob
.type == 'CAMERA':
401 if ob
.get('ignore_restrictors') is None:
402 ob
.hide_select
= True
408 # Restrictor for Lamps
410 class RestrictorLamp(Operator
):
411 bl_idname
= "restrictor.light"
412 bl_label
= "Restrictor Lamps"
413 bl_option
= {'REGISTER', 'UNDO'}
414 bl_description
= "Lamps selection restrictor"
416 def execute(self
, context
):
418 global lamprestrictorenabled
420 if bpy
.context
.scene
.get('lamprestrictor') is not None:
421 lamprestrictorenabled
= True
422 if bpy
.context
.scene
.get('lamprestrictor') is not None:
423 del bpy
.context
.scene
['lamprestrictor']
424 lamp
= 'OUTLINER_OB_LIGHT'
425 for ob
in bpy
.context
.scene
.objects
:
426 if ob
.type == 'LIGHT':
427 if ob
.get('ignore_restrictors') is None:
428 ob
.hide_select
= False
431 lamprestrictorenabled
= False
432 bpy
.context
.scene
['lamprestrictor'] = 1
434 for ob
in bpy
.context
.scene
.objects
:
435 if ob
.type == 'LIGHT':
436 if ob
.get('ignore_restrictors') is None:
437 ob
.hide_select
= True
443 # Restrictor for Lattice
445 class RestrictorLat(Operator
):
446 bl_idname
= "restrictor.lat"
447 bl_label
= "Restrictor Lattices"
448 bl_option
= {'REGISTER', 'UNDO'}
449 bl_description
= "Lattices selection restrictor"
451 def execute(self
, context
):
453 global latrestrictorenabled
455 if bpy
.context
.scene
.get('latrestrictor') is not None:
456 latrestrictorenabled
= True
457 if bpy
.context
.scene
.get('latrestrictor') is not None:
458 del bpy
.context
.scene
['latrestrictor']
459 lat
= 'OUTLINER_OB_LATTICE'
460 for ob
in bpy
.context
.scene
.objects
:
461 if ob
.type == 'LATTICE':
462 if ob
.get('ignore_restrictors') is None:
463 ob
.hide_select
= False
465 latrestrictorenabled
= False
466 bpy
.context
.scene
['latrestrictor'] = 1
468 for ob
in bpy
.context
.scene
.objects
:
469 if ob
.type == 'LATTICE':
470 if ob
.get('ignore_restrictors') is None:
471 ob
.hide_select
= True
479 class RestrictorFont(Operator
):
480 bl_idname
= "restrictor.font"
481 bl_label
= "Restrictor Font"
482 bl_option
= {'REGISTER', 'UNDO'}
483 bl_description
= "Text selection restrictor"
485 def execute(self
, context
):
487 global fontrestrictorenabled
489 if bpy
.context
.scene
.get('fontrestrictor') is not None:
490 fontrestrictorenabled
= True
491 if bpy
.context
.scene
.get('fontrestrictor') is not None:
492 del bpy
.context
.scene
['fontrestrictor']
493 font
= 'OUTLINER_OB_FONT'
494 for ob
in bpy
.context
.scene
.objects
:
495 if ob
.type == 'FONT':
496 if ob
.get('ignore_restrictors') is None:
497 ob
.hide_select
= False
499 fontrestrictorenabled
= False
500 bpy
.context
.scene
['fontrestrictor'] = 1
502 for ob
in bpy
.context
.scene
.objects
:
503 if ob
.type == 'FONT':
504 if ob
.get('ignore_restrictors') is None:
505 ob
.hide_select
= True
511 # Restrictor for Metaballs
513 class RestrictorMeta(Operator
):
514 bl_idname
= "restrictor.meta"
515 bl_label
= "restrictor metaballs"
516 bl_option
= {'REGISTER', 'UNDO'}
517 bl_description
= "Metaballs selection restrictor"
519 def execute(self
, context
):
521 global metarestrictorenabled
523 if bpy
.context
.scene
.get('metarestrictor') is not None:
524 metarestrictorenabled
= True
525 if bpy
.context
.scene
.get('metarestrictor') is not None:
526 del bpy
.context
.scene
['metarestrictor']
527 meta
= 'OUTLINER_OB_META'
528 for ob
in bpy
.context
.scene
.objects
:
529 if ob
.type == 'META':
530 if ob
.get('ignore_restrictors') is None:
531 ob
.hide_select
= False
533 metarestrictorenabled
= False
534 bpy
.context
.scene
['metarestrictor'] = 1
536 for ob
in bpy
.context
.scene
.objects
:
537 if ob
.type == 'META':
538 if ob
.get('ignore_restrictors') is None:
539 ob
.hide_select
= True
545 # Restrictor for Surfaces
547 class RestrictorSurf(Operator
):
548 bl_idname
= "restrictor.surf"
549 bl_label
= "Restrictor Surfaces"
550 bl_option
= {'REGISTER', 'UNDO'}
551 bl_description
= "Surfaces selection restrictor"
553 def execute(self
, context
):
555 global surfrestrictorenabled
557 if bpy
.context
.scene
.get('surfrestrictor') is not None:
558 surfrestrictorenabled
= True
559 if bpy
.context
.scene
.get('surfrestrictor') is not None:
560 del bpy
.context
.scene
['surfrestrictor']
561 surf
= 'OUTLINER_OB_SURFACE'
562 for ob
in bpy
.context
.scene
.objects
:
563 if ob
.type == 'SURFACE':
564 if ob
.get('ignore_restrictors') is None:
565 ob
.hide_select
= False
567 surfrestrictorenabled
= False
568 bpy
.context
.scene
['surfrestrictor'] = 1
569 surf
= 'SURFACE_DATA'
570 for ob
in bpy
.context
.scene
.objects
:
571 if ob
.type == 'SURFACE':
572 if ob
.get('ignore_restrictors') is None:
573 ob
.hide_select
= True
579 # Restrictor for Speakers
581 class RestrictorSound(Operator
):
582 bl_idname
= "restrictor.speak"
583 bl_label
= "Restrictor Speakers"
584 bl_description
= "Sounds selection restrictor"
585 bl_option
= {'REGISTER', 'UNDO'}
587 def execute(self
, context
):
589 global speakrestrictorenabled
591 if bpy
.context
.scene
.get('speakrestrictor') is not None:
592 speakrestrictorenabled
= True
593 if bpy
.context
.scene
.get('speakrestrictor') is not None:
594 del bpy
.context
.scene
['speakrestrictor']
595 speak
= 'OUTLINER_OB_SPEAKER'
596 for ob
in bpy
.context
.scene
.objects
:
597 if ob
.type == 'SPEAKER':
598 if ob
.get('ignore_restrictors') is None:
599 ob
.hide_select
= False
602 speakrestrictorenabled
= False
603 bpy
.context
.scene
['speakrestrictor'] = 1
605 for ob
in bpy
.context
.scene
.objects
:
606 if ob
.type == 'SPEAKER':
607 if ob
.get('ignore_restrictors') is None:
608 ob
.hide_select
= True
614 # refresh restrictors for newly created objects
616 class RefreshRestrictors(Operator
):
617 bl_idname
= "refresh.restrictors"
618 bl_label
= "Refresh Selection Restrictors"
619 bl_option
= {'REGISTER', 'UNDO'}
620 bl_description
= "Refresh restrictors"
622 def execute(self
, context
):
636 'meshrestrictor': ("OBJECT_DATA", "MESH_CUBE", "MESH"),
637 'curverestrictor': ("OUTLINER_OB_CURVE", "CURVE_DATA", "CURVE"),
638 'armrestrictor': ("OUTLINER_OB_ARMATURE", "ARMATURE_DATA", "ARMATURE"),
639 'emptyrestrictor': ("OUTLINER_OB_EMPTY", "EMPTY_DATA", "EMPTY"),
640 'camrestrictor': ("OUTLINER_OB_CAMERA", "CAMERA_DATA", "CAMERA"),
641 'lamprestrictor': ("OUTLINER_OB_LIGHT", "LIGHT_DATA", "LIGHT"),
642 'latrestrictor': ("OUTLINER_OB_LATTICE", "LATTICE", "LATTICE"),
643 'fontrestrictor': ("OUTLINER_OB_FONT", "FONT", "FONT"),
644 'metarestrictor': ("OUTLINER_OB_META", "META_DATA", "META"),
645 'surfrestrictor': ("SURFACE", "SURFACE_DATA", "SURFACE"),
646 'speakrestrictor': ("OUTLINER_OB_SPEAKER", "SPEAKER", "SPEAKER"),
649 for prop
, values
in datas
.items():
650 icon_i
, icon_a
, types
= values
651 get_props
= bpy
.context
.scene
.get(prop
)
653 gl_icon
= icon_a
if get_props
else icon_i
655 for ob
in bpy
.context
.scene
.objects
:
657 if ob
.get('ignore_restrictors') is None:
658 ob
.hide_select
= False if get_props
is None else True
659 if get_props
is None:
662 mesh
= gl_icon
if types
== "MESH" else mesh
663 curve
= gl_icon
if types
== "CURVE" else curve
664 arm
= gl_icon
if types
== "ARMATURE" else arm
665 empty
= gl_icon
if types
== "EMPTY" else empty
666 cam
= gl_icon
if types
== "CAMERA" else cam
667 lamp
= gl_icon
if types
== "LIGHT" else lamp
668 lat
= gl_icon
if types
== "LATTICE" else lat
669 font
= gl_icon
if types
== "FONT" else font
670 meta
= gl_icon
if types
== "META" else meta
671 surf
= gl_icon
if types
== "SURFACE" else surf
672 speak
= gl_icon
if types
== "SPEAKER" else speak
677 class RestrictorSelection(Menu
):
678 """Restrict Selection"""
679 bl_label
= "Selection"
680 bl_idname
= "RestrictorSelection"
682 def draw(self
, context
):
699 layout
.operator("restrictor.mesh", icon
=mesh
, text
="Mesh")
700 layout
.operator("restrictor.curve", icon
=curve
, text
="Curve")
701 layout
.operator("restrictor.arm", icon
=arm
, text
="Armature")
702 layout
.operator("restrictor.empty", icon
=empty
, text
="Empty")
703 layout
.operator("restrictor.cam", icon
=cam
, text
="Camera")
704 layout
.operator("restrictor.light", icon
=lamp
, text
="Lamp")
705 layout
.operator("restrictor.lat", icon
=lat
, text
="Lattice")
706 layout
.operator("restrictor.font", icon
=font
, text
="Font")
707 layout
.operator("restrictor.meta", icon
=meta
, text
="MetaBall")
708 layout
.operator("restrictor.surf", icon
=surf
, text
="Surface")
709 layout
.operator("restrictor.speak", icon
=speak
, text
="Speaker")
711 layout
.operator("ignore.restrictors", icon
='GHOST_ENABLED', text
="Enable").ignore
= True
712 layout
.operator("ignore.restrictors", icon
='GHOST_DISABLED', text
="Disable").ignore
= False
713 layout
.operator("refresh.restrictors", icon
='FILE_REFRESH', text
="Refresh")
716 def view3d_select_menu(self
, context
):
717 self
.layout
.menu(RestrictorSelection
.bl_idname
)
721 bpy
.types
.VIEW3D_HT_header
.append(view3d_select_menu
)
725 bpy
.types
.VIEW3D_HT_header
.remove(view3d_select_menu
)
727 bpy
.utils
.unregister_class(RefreshRestrictors
)
730 if __name__
== "__main__":
733 # update icons when opening file and updating scene data
734 # I don't know what does "updating scene data" mean
735 # But I've added it here to refresh icons while switching scenes
736 bpy
.app
.handlers
.load_post
.append(check_restrictors
)
737 bpy
.app
.handlers
.scene_update_post
.append(check_restrictors
)