Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2014-08-08 14:50:43 +0400
committerBastien Montagne <montagne29@wanadoo.fr>2014-08-08 14:50:43 +0400
commit026c9fe1c95adc95f45015db166d5d769d10906b (patch)
tree4e670f92b9ceae335409839d7dbca5bd07ece3cb /ui_layer_manager.py
parentb7a39588c05946aaa64b59a9991579f1bf1dbdbd (diff)
Move named layer manager addon from contrib to community addons (see T41317).
Diffstat (limited to 'ui_layer_manager.py')
-rw-r--r--ui_layer_manager.py557
1 files changed, 557 insertions, 0 deletions
diff --git a/ui_layer_manager.py b/ui_layer_manager.py
new file mode 100644
index 00000000..5a94c2cf
--- /dev/null
+++ b/ui_layer_manager.py
@@ -0,0 +1,557 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+#
+bl_info = {
+ "name": "Layer Management",
+ "author": "Alfonso Annarumma",
+ "version": (1, 5, 1),
+ "blender": (2, 70, 0),
+ "location": "View3D > Properties panel > Layer Management",
+ "warning": "",
+ "description": "Display and Edit Layer Name",
+ "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/3D_interaction/layer_manager",
+ "category": "3D View",
+}
+
+import bpy
+from bpy.types import Menu, Panel, UIList, PropertyGroup
+from bpy.props import StringProperty, BoolProperty, IntProperty, CollectionProperty, BoolVectorProperty, PointerProperty
+from bpy.app.handlers import persistent
+
+EDIT_MODES = {'EDIT_MESH', 'EDIT_CURVE', 'EDIT_SURFACE', 'EDIT_METABALL', 'EDIT_TEXT', 'EDIT_ARMATURE'}
+
+
+class NamedLayer(PropertyGroup):
+ name = StringProperty(name="Layer Name")
+ use_lock = BoolProperty(name="Lock Layer", default=False)
+ use_object_select = BoolProperty(name="Object Select", default=True)
+ use_wire = BoolProperty(name="Wire Layer", default=False)
+
+
+class NamedLayers(PropertyGroup):
+ layers = CollectionProperty(type=NamedLayer)
+ use_hide_empty_layers = BoolProperty(name="Hide Empty Layer", default=False)
+ use_extra_options = BoolProperty(name="Show Extra Options", default=True)
+ use_layer_indices = BoolProperty(name="Show Layer Indices", default=False)
+ use_classic = BoolProperty(name="Classic", default=False, description="Use a classic layer selection visibility")
+
+ use_init = BoolProperty(default=True, options={'HIDDEN'})
+
+
+# Stupid, but only solution currently is to use a handler to init that layers collection...
+@persistent
+def check_init_data(scene):
+ namedlayers = scene.namedlayers
+ if namedlayers.use_init:
+ while namedlayers.layers:
+ namedlayers.layers.remove(0)
+ for i in range(20):
+ layer = namedlayers.layers.add()
+ layer.name = "Layer%.2d" % i
+ namedlayers.use_init = False
+
+
+class LayerGroup(PropertyGroup):
+ use_toggle = BoolProperty(name="", default=False)
+ use_wire = BoolProperty(name="", default=False)
+ use_lock = BoolProperty(name="", default=False)
+
+ layers = BoolVectorProperty(name="Layers", default=([False] * 20), size=20, subtype='LAYER')
+
+
+class SCENE_OT_namedlayer_group_add(bpy.types.Operator):
+ """Add and select a new layer group"""
+ bl_idname = "scene.namedlayer_group_add"
+ bl_label = "Add Layer Group"
+
+ layers = BoolVectorProperty(name="Layers", default=([False] * 20), size=20)
+
+ @classmethod
+ def poll(cls, context):
+ return bool(context.scene)
+
+ def execute(self, context):
+ scene = context.scene
+ layergroups = scene.layergroups
+ layers = self.layers
+
+ group_idx = len(layergroups)
+ layer_group = layergroups.add()
+ layer_group.name = "LayerGroup.%.3d" % group_idx
+ layer_group.layers = layers
+ scene.layergroups_index = group_idx
+
+ return {'FINISHED'}
+
+
+class SCENE_OT_namedlayer_group_remove(bpy.types.Operator):
+ """Remove selected layer group"""
+ bl_idname = "scene.namedlayer_group_remove"
+ bl_label = "Remove Layer Group"
+
+ group_idx = bpy.props.IntProperty()
+
+ @classmethod
+ def poll(cls, context):
+ return bool(context.scene)
+
+ def execute(self, context):
+ scene = context.scene
+ group_idx = self.group_idx
+
+ scene.layergroups.remove(group_idx)
+ if scene.layergroups_index > len(scene.layergroups) - 1:
+ scene.layergroups_index = len(scene.layergroups) - 1
+
+ return {'FINISHED'}
+
+
+class SCENE_OT_namedlayer_toggle_visibility(bpy.types.Operator):
+ """Show or hide given layer (shift to extend)"""
+ bl_idname = "scene.namedlayer_toggle_visibility"
+ bl_label = "Show/Hide Layer"
+
+ layer_idx = IntProperty()
+ group_idx = IntProperty()
+ use_spacecheck = BoolProperty()
+ extend = BoolProperty(options={'SKIP_SAVE'})
+
+ @classmethod
+ def poll(cls, context):
+ return context.scene and (context.area.spaces.active.type == 'VIEW_3D')
+
+ def execute(self, context):
+ scene = context.scene
+ layer_cont = context.area.spaces.active if self.use_spacecheck else context.scene
+ layer_idx = self.layer_idx
+
+ if layer_idx == -1:
+ group_idx = self.group_idx
+ layergroups = scene.layergroups[group_idx]
+ group_layers = layergroups.layers
+ layers = layer_cont.layers
+
+ if layergroups.use_toggle:
+ layer_cont.layers = [not group_layer and layer for group_layer, layer in zip(group_layers, layers)]
+ layergroups.use_toggle = False
+ else:
+ layer_cont.layers = [group_layer or layer for group_layer, layer in zip(group_layers, layers)]
+ layergroups.use_toggle = True
+ else:
+ if self.extend:
+ layer_cont.layers[layer_idx] = not layer_cont.layers[layer_idx]
+ else:
+ layers = [False] * 20
+ layers[layer_idx] = True
+ layer_cont.layers = layers
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ self.extend = event.shift
+ return self.execute(context)
+
+
+class SCENE_OT_namedlayer_move_to_layer(bpy.types.Operator):
+ """Move selected objects to this Layer (shift to extend)"""
+ bl_idname = "scene.namedlayer_move_to_layer"
+ bl_label = "Move Objects To Layer"
+
+ layer_idx = IntProperty()
+ extend = BoolProperty(options={'SKIP_SAVE'})
+
+ @classmethod
+ def poll(cls, context):
+ return context.scene
+
+ def execute(self, context):
+ layer_idx = self.layer_idx
+ scene = context.scene
+
+ # Cycle all objects in the layer
+ for obj in scene.objects:
+ if obj.select:
+ # If object is in at least one of the scene's visible layers...
+ if True in {ob_layer and sce_layer for ob_layer, sce_layer in zip(obj.layers, scene.layers)}:
+ if self.extend:
+ obj.layers[layer_idx] = not obj.layers[layer_idx]
+ else:
+ layer = [False] * 20
+ layer[layer_idx] = True
+ obj.layers = layer
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ self.extend = event.shift
+ return self.execute(context)
+
+
+class SCENE_OT_namedlayer_toggle_wire(bpy.types.Operator):
+ """Toggle all objects on this layer draw as wire"""
+ bl_idname = "scene.namedlayer_toggle_wire"
+ bl_label = "Toggle Objects Draw Wire"
+
+ layer_idx = IntProperty()
+ use_wire = BoolProperty()
+ group_idx = IntProperty()
+
+ @classmethod
+ def poll(cls, context):
+ return context.scene and (context.area.spaces.active.type == 'VIEW_3D')
+
+ def execute(self, context):
+ scene = context.scene
+ layer_idx = self.layer_idx
+ use_wire = self.use_wire
+
+ view_3d = context.area.spaces.active
+
+ # Check if layer have some thing
+ if view_3d.layers_used[layer_idx] or layer_idx == -1:
+ display = 'WIRE' if use_wire else 'TEXTURED'
+ # Cycle all objects in the layer.
+ for obj in context.scene.objects:
+ if layer_idx == -1:
+ group_idx = self.group_idx
+ group_layers = scene.layergroups[group_idx].layers
+ layers = obj.layers
+ if True in {layer and group_layer for layer, group_layer in zip(layers, group_layers)}:
+ obj.draw_type = display
+ scene.layergroups[group_idx].use_wire = use_wire
+ else:
+ if obj.layers[layer_idx]:
+ obj.draw_type = display
+ scene.namedlayers.layers[layer_idx].use_wire = use_wire
+
+ return {'FINISHED'}
+
+
+class SCENE_OT_namedlayer_lock_selected(bpy.types.Operator):
+ """Lock all selected objects on this layer"""
+ bl_idname = "scene.namedlayer_lock_selected"
+ bl_label = "Lock Objects"
+
+ layer_idx = IntProperty()
+ use_lock = BoolProperty()
+ group_idx = IntProperty()
+
+ @classmethod
+ def poll(cls, context):
+ return context.scene and (context.area.spaces.active.type == 'VIEW_3D')
+
+ def execute(self, context):
+ scene = context.scene
+ view_3d = context.area.spaces.active
+ layer_idx = self.layer_idx
+ group_idx = self.group_idx
+ group_layers = scene.layergroups[group_idx].layers
+ use_lock = self.use_lock
+
+ # check if layer have some thing
+ if layer_idx == -1 or view_3d.layers_used[layer_idx]:
+ # Cycle all objects in the layer.
+ for obj in context.scene.objects:
+ if layer_idx == -1:
+ layers = obj.layers
+ if True in {layer and group_layer for layer, group_layer in zip(layers, group_layers)}:
+ obj.hide_select = not use_lock
+ obj.select = False
+ scene.layergroups[group_idx].use_lock = not use_lock
+ else:
+ if obj.layers[layer_idx]:
+ obj.hide_select = not use_lock
+ obj.select = False
+ scene.namedlayers.layers[layer_idx].use_lock = not use_lock
+
+ return {'FINISHED'}
+
+
+class SCENE_OT_namedlayer_select_objects_by_layer(bpy.types.Operator):
+ """Select all the objects on this Layer (shift for multi selection, ctrl to make active the last selected object)"""
+ bl_idname = "scene.namedlayer_select_objects_by_layer"
+ bl_label = "Select Objects In Layer"
+
+ select_obj = BoolProperty()
+ layer_idx = IntProperty()
+
+ extend = BoolProperty(options={'SKIP_SAVE'})
+ active = BoolProperty(options={'SKIP_SAVE'})
+
+ @classmethod
+ def poll(cls, context):
+ return context.scene and (context.area.spaces.active.type == 'VIEW_3D')
+
+ def execute(self, context):
+ scene = context.scene
+ view_3d = context.area.spaces.active
+ select_obj = self.select_obj
+ layer_idx = self.layer_idx
+
+ not_all_selected = 0
+ # check if layer have some thing
+ if view_3d.layers_used[layer_idx]:
+ objects = []
+ for obj in context.scene.objects:
+ if obj.layers[layer_idx]:
+ objects.append(obj)
+ not_all_selected -= 1
+ if self.active:
+ context.scene.objects.active = obj
+ if obj.select:
+ not_all_selected += 1
+ if not not_all_selected:
+ for obj in objects:
+ obj.select = False
+ else:
+ bpy.ops.object.select_by_layer(extend=self.extend, layers=layer_idx + 1)
+
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ self.extend = event.shift
+ self.active = event.ctrl
+ return self.execute(context)
+
+
+class SCENE_OT_namedlayer_show_all(bpy.types.Operator):
+ """Show or hide all layers in the scene"""
+ bl_idname = "scene.namedlayer_show_all"
+ bl_label = "Select All Layers"
+
+ show = BoolProperty()
+
+ @classmethod
+ def poll(cls, context):
+ return context.scene and (context.area.spaces.active.type == 'VIEW_3D')
+
+ def execute(self, context):
+ scene = context.scene
+ view_3d = context.area.spaces.active
+ show = self.show
+ active_layer = scene.active_layer
+
+ # check for lock camera and layer is active
+ layer_cont = scene if view_3d.lock_camera_and_layers else view_3d
+
+ if show:
+ layer_cont.layers[:] = [True] * 20
+ # Restore active layer (stupid, but Scene.active_layer is readonly).
+ layer_cont.layers[active_layer] = False
+ layer_cont.layers[active_layer] = True
+ else:
+ layers = [False] * 20
+ # Keep selection of active layer
+ layers[active_layer] = True
+ layer_cont.layers[:] = layers
+
+ return {'FINISHED'}
+
+
+class SCENE_PT_namedlayer_layers(bpy.types.Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'TOOLS'
+ bl_label = "Layer Management"
+ bl_options = {'DEFAULT_CLOSED'}
+ bl_category = "Layer"
+
+ @classmethod
+ def poll(self, context):
+ return ((getattr(context, "mode", 'EDIT_MESH') not in EDIT_MODES) and
+ (context.area.spaces.active.type == 'VIEW_3D'))
+
+ def draw(self, context):
+ scene = context.scene
+ view_3d = context.area.spaces.active
+ actob = context.object
+ namedlayers = scene.namedlayers
+ use_extra = namedlayers.use_extra_options
+ use_hide = namedlayers.use_hide_empty_layers
+ use_indices = namedlayers.use_layer_indices
+ use_classic = namedlayers.use_classic
+
+ # Check for lock camera and layer is active
+ if view_3d.lock_camera_and_layers:
+ layer_cont = scene
+ use_spacecheck = False
+ else:
+ layer_cont = view_3d
+ use_spacecheck = True
+
+ layout = self.layout
+ row = layout.row()
+ col = row.column()
+ col.prop(view_3d, "lock_camera_and_layers", text="")
+ # Check if there is a layer off
+ show = (False in {layer for layer in layer_cont.layers})
+ icon = 'RESTRICT_VIEW_ON' if show else 'RESTRICT_VIEW_OFF'
+ col.operator("scene.namedlayer_show_all", emboss=False, icon=icon, text="").show = show
+
+ col = row.column()
+ col.prop(namedlayers, "use_classic")
+ col.prop(namedlayers, "use_extra_options", text="Options")
+
+ col = row.column()
+ col.prop(namedlayers, "use_layer_indices", text="Indices")
+ col.prop(namedlayers, "use_hide_empty_layers", text="Hide Empty")
+
+ col = layout.column()
+ for layer_idx in range(20):
+ namedlayer = namedlayers.layers[layer_idx]
+ is_layer_used = view_3d.layers_used[layer_idx]
+
+ if (use_hide and not is_layer_used):
+ # Hide unused layers and this one is unused, skip.
+ continue
+
+ row = col.row(align=True)
+
+ # layer index
+ if use_indices:
+ row.label(text="%.2d." % (layer_idx + 1))
+
+ # visualization
+ icon = 'RESTRICT_VIEW_OFF' if layer_cont.layers[layer_idx] else 'RESTRICT_VIEW_ON'
+ if use_classic:
+ op = row.operator("scene.namedlayer_toggle_visibility", text="", icon=icon, emboss=True)
+ op.layer_idx = layer_idx
+ op.use_spacecheck = use_spacecheck
+ else:
+ row.prop(layer_cont, "layers", index=layer_idx, emboss=True, icon=icon, toggle=True, text="")
+
+ # Name (use special icon for active layer).
+ icon = 'FILE_TICK' if (getattr(layer_cont, "active_layer", -1) == layer_idx) else 'NONE'
+ row.prop(namedlayer, "name", text="", icon=icon)
+
+ if use_extra:
+ use_lock = namedlayer.use_lock
+
+ # Select by type operator
+ sub = row.column(align=True)
+ sub.enabled = not use_lock
+ sub.operator("scene.namedlayer_select_objects_by_layer", icon='RESTRICT_SELECT_OFF',
+ text="", emboss=True).layer_idx = layer_idx
+
+ # Lock operator
+ icon = 'LOCKED' if use_lock else 'UNLOCKED'
+ op = row.operator("scene.namedlayer_lock_selected", text="", emboss=True, icon=icon)
+ op.layer_idx = layer_idx
+ op.use_lock = use_lock
+
+ # Merge layer
+ # check if layer has something
+ has_active = (actob and actob.layers[layer_idx])
+ icon = ('LAYER_ACTIVE' if has_active else 'LAYER_USED') if is_layer_used else 'RADIOBUT_OFF'
+ row.operator("scene.namedlayer_move_to_layer", text="", emboss=True, icon=icon).layer_idx = layer_idx
+
+ # Wire view
+ use_wire = namedlayer.use_wire
+ icon = 'WIRE' if use_wire else 'POTATO'
+ op = row.operator("scene.namedlayer_toggle_wire", text="", emboss=True, icon=icon)
+ op.layer_idx = layer_idx
+ op.use_wire = not use_wire
+
+ if len(scene.objects) == 0:
+ layout.label(text="No objects in scene")
+
+
+class SCENE_UL_namedlayer_groups(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ layer_group = item
+
+ # check for lock camera and layer is active
+ view_3d = context.area.spaces.active # Ensured it is a 'VIEW_3D' in panel's poll(), weak... :/
+ use_spacecheck = False if view_3d.lock_camera_and_layers else True
+
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.prop(layer_group, "name", text="", emboss=False)
+ # lock operator
+ use_lock = layer_group.use_lock
+ icon = 'LOCKED' if use_lock else 'UNLOCKED'
+ op = layout.operator("scene.namedlayer_lock_selected", text="", emboss=False, icon=icon)
+ op.use_lock = use_lock
+ op.group_idx = index
+ op.layer_idx = -1
+
+ # view operator
+ icon = 'RESTRICT_VIEW_OFF' if layer_group.use_toggle else 'RESTRICT_VIEW_ON'
+ op = layout.operator("scene.namedlayer_toggle_visibility", text="", emboss=False, icon=icon)
+ op.use_spacecheck = use_spacecheck
+ op.group_idx = index
+ op.layer_idx = -1
+
+ # wire operator
+ use_wire = layer_group.use_wire
+ icon = 'WIRE' if use_wire else 'POTATO'
+ op = layout.operator("scene.namedlayer_toggle_wire", text="", emboss=False, icon=icon)
+ op.use_wire = not use_wire
+ op.group_idx = index
+ op.layer_idx = -1
+
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+
+
+class SCENE_PT_namedlayer_groups(bpy.types.Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'TOOLS'
+ bl_category = "Layer"
+ bl_label = "Layer Groups"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(self, context):
+ return ((getattr(context, "mode", 'EDIT_MESH') not in EDIT_MODES) and
+ (context.area.spaces.active.type == 'VIEW_3D'))
+
+ def draw(self, context):
+ scene = context.scene
+ group_idx = scene.layergroups_index
+
+ layout = self.layout
+ row = layout.row()
+ row.template_list("SCENE_UL_namedlayer_groups", "", scene, "layergroups", scene, "layergroups_index")
+
+ col = row.column(align=True)
+ col.operator("scene.namedlayer_group_add", icon='ZOOMIN', text="").layers = scene.layers
+ col.operator("scene.namedlayer_group_remove", icon='ZOOMOUT', text="").group_idx = group_idx
+
+ if bool(scene.layergroups):
+ layout.prop(scene.layergroups[group_idx], "layers", text="", toggle=True)
+ layout.prop(scene.layergroups[group_idx], "name", text="Name:")
+
+
+def register():
+ bpy.utils.register_module(__name__)
+ bpy.types.Scene.layergroups = CollectionProperty(type=LayerGroup)
+ # Unused, but this is needed for the TemplateList to work...
+ bpy.types.Scene.layergroups_index = IntProperty(default=-1)
+ bpy.types.Scene.namedlayers = PointerProperty(type=NamedLayers)
+ bpy.app.handlers.scene_update_post.append(check_init_data)
+
+
+def unregister():
+ bpy.app.handlers.scene_update_post.remove(check_init_data)
+ del bpy.types.Scene.layergroups
+ del bpy.types.Scene.layergroups_index
+ del bpy.types.Scene.namedlayers
+ bpy.utils.unregister_module(__name__)
+
+
+if __name__ == "__main__":
+ register()