Use separate root objects to gather the sample visualization and the
[blender-addons-contrib.git] / mesh_border_deselect_outer.py
1 import bpy
2 import bmesh
3
4 bl_info = {
5     "name": "Border Deselect Outer",
6     "author": "CoDEmanX",
7     "version": (1, 2),
8     "blender": (2, 66, 0),
9     "location": "View3D > EditMode > Select",
10     "description": "Make a selection, then run this operator " \
11         "to border-select the desired selection intersection",
12     "warning": "",
13     "wiki_url": "http://wiki.blender.org/index.php" \
14         "?title=Extensions:2.6/Py/Scripts/Modeling/Border_Deselect_Outer",
15     "tracker_url": "http://blenderartists.org/forum/showthread.php" \
16         "?290617-Mesh-Border-Deselect-Outer-(selection-intersection-by-using-a-border-select)",
17     "category": "Mesh"}
18
19
20 def store_sel():
21     bm = MESH_OT_border_deselect_outer.bm
22
23     if 'select_old' in bm.loops.layers.int.keys():
24         sel = bm.loops.layers.int['select_old']
25     else:
26         sel = bm.loops.layers.int.new("select_old")
27
28     for v in bm.verts:
29         v.link_loops[0][sel] = v.select
30
31 def restore_sel(me):
32     bm = MESH_OT_border_deselect_outer.bm
33
34     sel = bm.loops.layers.int['select_old']
35
36     for v in bm.verts:
37         if not (v.select and v.link_loops[0][sel]):
38             v.select_set(False)
39
40     bm.loops.layers.int.remove(sel)
41
42     #bm.select_mode = {'VERT'}
43     #bm.select_flush_mode()
44     bm.select_flush(False)
45     me.update()
46
47
48 def changed_sel():
49     bm = MESH_OT_border_deselect_outer.bm
50
51     sel = bm.loops.layers.int['select_old']
52
53     for v in bm.verts:
54         if v.select != v.link_loops[0][sel]:
55             return True
56     return False
57
58
59 class MESH_OT_border_deselect_outer(bpy.types.Operator):
60     """Border select an existing selection and make only the intersection selected"""
61     bl_idname = "mesh.border_deselect_outer"
62     bl_label = "Border Deselect Outer"
63     bl_options = {'REGISTER'}
64
65     init = True
66     bm = None
67     mode_change = False
68
69     def modal(self, context, event):
70
71         if changed_sel() or not self.init:
72             restore_sel(context.object.data)
73             return {'FINISHED'}
74
75         elif event.type in ('RIGHTMOUSE', 'ESC'):
76             return {'CANCELLED'}
77
78         if self.init:
79             bpy.ops.view3d.select_border('INVOKE_DEFAULT', extend=False)
80             self.init = False
81
82         return {'RUNNING_MODAL'}
83         #return {'PASS_THROUGH'} # Makes no difference
84
85     @staticmethod
86     def modecheck(context):
87         return (context.area.type == 'VIEW_3D' and
88                 context.object and
89                 context.object.type == 'MESH' and
90                 context.object.mode == 'EDIT')
91
92     @classmethod
93     def poll(cls, context):
94         return cls.modecheck(context)
95
96     def invoke(self, context, event):
97         if self.__class__.modecheck(context):
98
99             MESH_OT_border_deselect_outer.bm = bmesh.from_edit_mesh(context.object.data)
100             store_sel()
101             context.window_manager.modal_handler_add(self)
102             return {'RUNNING_MODAL'}
103         else:
104             self.report({'WARNING'}, "No active editmesh!")
105             return {'CANCELLED'}
106
107 def menu_func(self, context):
108     self.layout.operator("mesh.border_deselect_outer")
109
110
111 def register():
112     bpy.utils.register_class(MESH_OT_border_deselect_outer)
113     bpy.types.VIEW3D_MT_select_edit_mesh.prepend(menu_func)
114
115 def unregister():
116     bpy.utils.unregister_class(MESH_OT_border_deselect_outer)
117     bpy.types.VIEW3D_MT_select_edit_mesh.remove(menu_func)
118
119 if __name__ == "__main__":
120     register()