Render Layers and Collections (merge from render-layers)
authorDalai Felinto <dfelinto@gmail.com>
Tue, 7 Feb 2017 09:18:38 +0000 (10:18 +0100)
committerDalai Felinto <dfelinto@gmail.com>
Tue, 7 Feb 2017 10:11:00 +0000 (11:11 +0100)
Design Documents
----------------

* https://wiki.blender.org/index.php/Dev:2.8/Source/Layers

* https://wiki.blender.org/index.php/Dev:2.8/Source/DataDesignRevised

User Commit Log
---------------

* New Layer and Collection system to replace render layers and viewport layers.

* A layer is a set of collections of objects (and their drawing options) required for specific tasks.

* A collection is a set of objects, equivalent of the old layers in Blender. A collection can be shared across multiple layers.

* All Scenes have a master collection that all other collections are children of.

* New collection "context" tab (in Properties Editor)

* New temporary viewport "collections" panel to control per-collection
visibility

Missing User Features
---------------------

* Collection "Filter"
  Option to add objects based on their names

* Collection Manager operators
  The existing buttons  are placeholders

* Collection Manager drawing
  The editor main region is empty

* Collection Override

* Per-Collection engine settings
  This will come as a separate commit, as part of the clay-engine branch

Dev Commit Log
--------------

* New DNA file (DNA_layer_types.h) with the new structs
  We are replacing Base by a new extended Base while keeping it backward
  compatible with some legacy settings (i.e., lay, flag_legacy).

  Renamed all Base to BaseLegacy to make it clear the areas of code that
  still need to be converted

  Note: manual changes were required on - deg_builder_nodes.h, rna_object.c, KX_Light.cpp

* Unittesting for main syncronization requirements
  - read, write, add/copy/remove objects, copy scene, collection
  link/unlinking, context)

* New Editor: Collection Manager
  Based on patch by Julian Eisel
  This is extracted from the layer-manager branch. With the following changes:

    - Renamed references of layer manager to collections manager

    - I doesn't include the editors/space_collections/ draw and util files

    - The drawing code itself will be implemented separately by Julian

* Base / Object:
  A little note about them. Original Blender code would try to keep them
  in sync through the code, juggling flags back and forth. This will now
  be handled by Depsgraph, keeping Object and Bases more separated
  throughout the non-rendering code.

  Scene.base is being cleared in doversion, and the old viewport drawing
  code was poorly converted to use the new bases while the new viewport
  code doesn't get merged and replace the old one.

Python API Changes
------------------

```
- scene.layers
+ # no longer exists

- scene.objects
+ scene.scene_layers.active.objects

- scene.objects.active
+ scene.render_layers.active.objects.active

- bpy.context.scene.objects.link()
+ bpy.context.scene_collection.objects.link()

- bpy_extras.object_utils.object_data_add(context, obdata, operator=None, use_active_layer=True, name=None)
+ bpy_extras.object_utils.object_data_add(context, obdata, operator=None, name=None)

- bpy.context.object.select
+ bpy.context.object.select = True
+ bpy.context.object.select = False
+ bpy.context.object.select_get()
+ bpy.context.object.select_set(action='SELECT')
+ bpy.context.object.select_set(action='DESELECT')

-AddObjectHelper.layers
+ # no longer exists
```

186 files changed:
build_files/cmake/macros.cmake
release/scripts/modules/bpy_extras/object_utils.py
release/scripts/presets/keyconfig/3dsmax.py
release/scripts/presets/keyconfig/maya.py
release/scripts/startup/bl_operators/clip.py
release/scripts/startup/bl_operators/freestyle.py
release/scripts/startup/bl_operators/object.py
release/scripts/startup/bl_operators/rigidbody.py
release/scripts/startup/bl_ui/__init__.py
release/scripts/startup/bl_ui/properties_collection.py [new file with mode: 0644]
release/scripts/startup/bl_ui/properties_render_layer.py
release/scripts/startup/bl_ui/space_collections.py [new file with mode: 0644]
release/scripts/startup/bl_ui/space_view3d.py
release/scripts/templates_py/batch_export.py
release/scripts/templates_py/operator_modal_view3d_raycast.py
source/blender/alembic/intern/abc_exporter.cc
source/blender/blenkernel/BKE_collection.h [new file with mode: 0644]
source/blender/blenkernel/BKE_context.h
source/blender/blenkernel/BKE_group.h
source/blender/blenkernel/BKE_layer.h [new file with mode: 0644]
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/BKE_scene.h
source/blender/blenkernel/CMakeLists.txt
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/cachefile.c
source/blender/blenkernel/intern/camera.c
source/blender/blenkernel/intern/collection.c [new file with mode: 0644]
source/blender/blenkernel/intern/collision.c
source/blender/blenkernel/intern/context.c
source/blender/blenkernel/intern/dynamicpaint.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/group.c
source/blender/blenkernel/intern/layer.c [new file with mode: 0644]
source/blender/blenkernel/intern/library_query.c
source/blender/blenkernel/intern/library_remap.c
source/blender/blenkernel/intern/mball.c
source/blender/blenkernel/intern/mball_tessellate.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/object_dupli.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/pointcache.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/smoke.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenkernel/intern/sound.c
source/blender/blenlib/BLI_ghash.h
source/blender/blenlib/BLI_iterator.h [new file with mode: 0644]
source/blender/blenlib/CMakeLists.txt
source/blender/blenloader/CMakeLists.txt
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/readfile.h
source/blender/blenloader/intern/versioning_250.c
source/blender/blenloader/intern/versioning_280.c [new file with mode: 0644]
source/blender/blenloader/intern/writefile.c
source/blender/collada/DocumentImporter.cpp
source/blender/collada/EffectExporter.cpp
source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
source/blender/depsgraph/intern/builder/deg_builder_nodes.h
source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.h
source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
source/blender/editors/CMakeLists.txt
source/blender/editors/animation/anim_channels_defines.c
source/blender/editors/animation/anim_channels_edit.c
source/blender/editors/animation/anim_filter.c
source/blender/editors/animation/anim_markers.c
source/blender/editors/animation/keyframes_draw.c
source/blender/editors/animation/keyframes_edit.c
source/blender/editors/armature/armature_intern.h
source/blender/editors/armature/armature_relations.c
source/blender/editors/armature/armature_select.c
source/blender/editors/armature/editarmature_sketch.c
source/blender/editors/armature/pose_select.c
source/blender/editors/curve/editcurve.c
source/blender/editors/curve/editfont.c
source/blender/editors/gpencil/gpencil_convert.c
source/blender/editors/gpencil/gpencil_utils.c
source/blender/editors/include/BIF_glutil.h
source/blender/editors/include/ED_armature.h
source/blender/editors/include/ED_object.h
source/blender/editors/include/ED_screen.h
source/blender/editors/include/ED_space_api.h
source/blender/editors/include/ED_transform.h
source/blender/editors/include/ED_view3d.h
source/blender/editors/include/UI_interface.h
source/blender/editors/include/UI_interface_icons.h
source/blender/editors/interface/interface_eyedropper.c
source/blender/editors/interface/interface_icons.c
source/blender/editors/interface/interface_widgets.c
source/blender/editors/interface/resources.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/mesh/mesh_data.c
source/blender/editors/mesh/mesh_navmesh.c
source/blender/editors/mesh/meshtools.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_constraint.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_group.c
source/blender/editors/object/object_hook.c
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_modifier.c
source/blender/editors/object/object_ops.c
source/blender/editors/object/object_relations.c
source/blender/editors/object/object_select.c
source/blender/editors/object/object_vgroup.c
source/blender/editors/physics/physics_fluid.c
source/blender/editors/physics/physics_pointcache.c
source/blender/editors/physics/rigidbody_constraint.c
source/blender/editors/physics/rigidbody_object.c
source/blender/editors/render/render_internal.c
source/blender/editors/render/render_preview.c
source/blender/editors/render/render_shading.c
source/blender/editors/screen/glutil.c
source/blender/editors/screen/screen_context.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/space_api/spacetypes.c
source/blender/editors/space_buttons/buttons_context.c
source/blender/editors/space_buttons/space_buttons.c
source/blender/editors/space_clip/tracking_ops_orient.c
source/blender/editors/space_collections/CMakeLists.txt [new file with mode: 0644]
source/blender/editors/space_collections/collections_intern.h [new file with mode: 0644]
source/blender/editors/space_collections/collections_ops.c [new file with mode: 0644]
source/blender/editors/space_collections/space_collections.c [new file with mode: 0644]
source/blender/editors/space_info/info_stats.c
source/blender/editors/space_logic/logic_window.c
source/blender/editors/space_nla/nla_channels.c
source/blender/editors/space_outliner/outliner_draw.c
source/blender/editors/space_outliner/outliner_edit.c
source/blender/editors/space_outliner/outliner_intern.h
source/blender/editors/space_outliner/outliner_ops.c
source/blender/editors/space_outliner/outliner_select.c
source/blender/editors/space_outliner/outliner_tools.c
source/blender/editors/space_outliner/outliner_tree.c
source/blender/editors/space_time/space_time.c
source/blender/editors/space_view3d/drawarmature.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_draw_legacy.c
source/blender/editors/space_view3d/view3d_edit.c
source/blender/editors/space_view3d/view3d_header.c
source/blender/editors/space_view3d/view3d_intern.h
source/blender/editors/space_view3d/view3d_project.c
source/blender/editors/space_view3d/view3d_select.c
source/blender/editors/space_view3d/view3d_view.c
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_generics.c
source/blender/editors/transform/transform_manipulator.c
source/blender/editors/transform/transform_orientations.c
source/blender/editors/transform/transform_snap.c
source/blender/editors/transform/transform_snap_object.c
source/blender/editors/uvedit/uvedit_draw.c
source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
source/blender/gpu/intern/gpu_draw.c
source/blender/gpu/intern/gpu_material.c
source/blender/makesdna/DNA_layer_types.h [new file with mode: 0644]
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesdna/intern/makesdna.c
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_context.c
source/blender/makesrna/intern/rna_group.c
source/blender/makesrna/intern/rna_internal.h
source/blender/makesrna/intern/rna_object.c
source/blender/makesrna/intern/rna_object_api.c
source/blender/makesrna/intern/rna_object_force.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_space.c
source/blender/makesrna/intern/rna_userdef.c
source/blender/modifiers/intern/MOD_fluidsim.c
source/blender/python/intern/bpy_rna_callback.c
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/envmap.c
source/blender/render/intern/source/pipeline.c
source/blender/windowmanager/WM_types.h
source/blender/windowmanager/intern/wm_keymap.c
source/blenderplayer/bad_level_call_stubs/stubs.c
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Ketsji/KX_Light.cpp
source/gameengine/Ketsji/KX_Light.h
tests/python/CMakeLists.txt
tests/python/bl_render_layer.py [new file with mode: 0644]

index 09428953a468b8afffb9f61012adb2c1083e8da9..83ae56636b036ef89cdfbe49df6e92c39f1d86c0 100644 (file)
@@ -566,6 +566,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
                bf_editor_space_userpref
                bf_editor_space_view3d
                bf_editor_space_clip
+               bf_editor_space_collections
 
                bf_editor_transform
                bf_editor_util
index c48f03c133d69ec3381741f50bda8e31214830d0..d740137b0c3ae9e71267706c7632261f06075abc 100644 (file)
@@ -103,9 +103,9 @@ def add_object_align_init(context, operator):
     return location * rotation
 
 
-def object_data_add(context, obdata, operator=None, use_active_layer=True, name=None):
+def object_data_add(context, obdata, operator=None, name=None):
     """
-    Add an object using the view context and preference to to initialize the
+    Add an object using the view context and preference to initialize the
     location, rotation and layer.
 
     :arg context: The context to use.
@@ -117,52 +117,24 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
     :arg name: Optional name
     :type name: string
     :return: the newly created object in the scene.
-    :rtype: :class:`bpy.types.ObjectBase`
+    :rtype: :class:`bpy.types.Object`
     """
     scene = context.scene
+    layer = context.render_layer
+    scene_collection = context.scene_collection
 
-    # ugh, could be made nicer
-    for ob in scene.objects:
-        ob.select = False
+    bpy.ops.object.select_all(action='DESELECT')
 
     if name is None:
         name = "Object" if obdata is None else obdata.name
 
     obj_new = bpy.data.objects.new(name, obdata)
-
-    base = scene.objects.link(obj_new)
-    base.select = True
-
-    v3d = None
-    if context.space_data and context.space_data.type == 'VIEW_3D':
-        v3d = context.space_data
-
-    if v3d and v3d.local_view:
-        base.layers_from_view(context.space_data)
-
-    if operator is not None and any(operator.layers):
-        base.layers = operator.layers
-    else:
-        if use_active_layer:
-            if v3d and v3d.local_view:
-                base.layers[scene.active_layer] = True
-            else:
-                if v3d and not v3d.lock_camera_and_layers:
-                    base.layers = [True if i == v3d.active_layer
-                                   else False for i in range(len(v3d.layers))]
-                else:
-                    base.layers = [True if i == scene.active_layer
-                                   else False for i in range(len(scene.layers))]
-        else:
-            if v3d:
-                base.layers_from_view(context.space_data)
-
-        if operator is not None:
-            operator.layers = base.layers
+    scene_collection.objects.link(obj_new)
+    obj_new.select_set(action='SELECT')
 
     obj_new.matrix_world = add_object_align_init(context, operator)
 
-    obj_act = scene.objects.active
+    obj_act = layer.objects.active
 
     # XXX
     # caused because entering edit-mode does not add a empty undo slot!
@@ -174,8 +146,8 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
             _obdata = bpy.data.meshes.new(name)
             obj_act = bpy.data.objects.new(_obdata.name, _obdata)
             obj_act.matrix_world = obj_new.matrix_world
-            scene.objects.link(obj_act)
-            scene.objects.active = obj_act
+            scene_collection.objects.link(obj_act)
+            layer.objects.active = obj_act
             bpy.ops.object.mode_set(mode='EDIT')
             # need empty undo step
             bpy.ops.ed.undo_push(message="Enter Editmode")
@@ -185,7 +157,7 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
         bpy.ops.mesh.select_all(action='DESELECT')
         bpy.ops.object.mode_set(mode='OBJECT')
 
-        obj_act.select = True
+        obj_act.select_set(action='SELECT')
         scene.update()  # apply location
         # scene.objects.active = obj_new
 
@@ -200,16 +172,14 @@ def object_data_add(context, obdata, operator=None, use_active_layer=True, name=
         bpy.ops.object.join()  # join into the active.
         if obdata:
             bpy.data.meshes.remove(obdata)
-        # base is freed, set to active object
-        base = scene.object_bases.active
 
         bpy.ops.object.mode_set(mode='EDIT')
     else:
-        scene.objects.active = obj_new
+        layer.objects.active = obj_new
         if context.user_preferences.edit.use_enter_edit_mode:
             bpy.ops.object.mode_set(mode='EDIT')
 
-    return base
+    return obj_new
 
 
 class AddObjectHelper:
@@ -230,12 +200,6 @@ class AddObjectHelper:
             name="Rotation",
             subtype='EULER',
             )
-    layers = BoolVectorProperty(
-            name="Layers",
-            size=20,
-            subtype='LAYER',
-            options={'HIDDEN', 'SKIP_SAVE'},
-            )
 
     @classmethod
     def poll(self, context):
index 7694e338d68462448280bc2aa99d12aab1bdc270..b6b0a0c926f495ce6a1d8f295aa568625012fb32 100644 (file)
@@ -330,7 +330,6 @@ kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', shift=True)
 kmi.properties.unselected = True
 kmi = km.keymap_items.new('object.hide_render_clear', 'H', 'PRESS', ctrl=True, alt=True)
 kmi = km.keymap_items.new('object.hide_render_set', 'H', 'PRESS', ctrl=True)
-kmi = km.keymap_items.new('object.move_to_layer', 'M', 'PRESS')
 kmi = km.keymap_items.new('object.delete', 'X', 'PRESS')
 kmi.properties.use_global = False
 kmi = km.keymap_items.new('object.delete', 'X', 'PRESS', shift=True)
index 67fd1fddcac76a49b07556747a904700fd84c531..f542ecf810b7752571acb5a87bd9cffd36764e27 100644 (file)
@@ -384,7 +384,6 @@ kmi = km.keymap_items.new('object.hide_view_clear', 'H', 'PRESS', shift=True, ct
 kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', ctrl=True)
 kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', alt=True)
 kmi.properties.unselected = True
-kmi = km.keymap_items.new('object.move_to_layer', 'M', 'PRESS')
 kmi = km.keymap_items.new('object.delete', 'BACK_SPACE', 'PRESS')
 kmi = km.keymap_items.new('object.delete', 'DEL', 'PRESS')
 kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True)
index 0c77ea2ab7e3d41dcede76a5389f1bbb62402e99..d60703236d65d57ae8c804ae9f57c9b3bc18ac7d 100644 (file)
@@ -232,7 +232,7 @@ class CLIP_OT_track_to_empty(Operator):
         ob = None
 
         ob = bpy.data.objects.new(name=track.name, object_data=None)
-        ob.select = True
+        ob.select_set(action='SELECT')
         context.scene.objects.link(ob)
         context.scene.objects.active = ob
 
@@ -506,7 +506,7 @@ object's movement caused by this constraint"""
         # XXX, should probably use context.selected_editable_objects
         # since selected objects can be from a lib or in hidden layer!
         for ob in scene.objects:
-            if ob.select:
+            if ob.select_set(action='SELECT'):
                 self._bake_object(scene, ob)
 
         return {'FINISHED'}
index fe3b00d54cd17f92e3648b5ff75b7d526012716f..43cd3110bebe3a29369043f217cebb61087c8095 100644 (file)
@@ -102,7 +102,7 @@ class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator):
             m.range_max = max_dist
             return {'FINISHED'}
         # Find selected mesh objects
-        selection = [ob for ob in scene.objects if ob.select and ob.type == 'MESH' and ob.name != ref.name]
+        selection = [ob for ob in scene.objects if ob.select_get() and ob.type == 'MESH' and ob.name != source.name]
         if selection:
             # Compute the min/max distance from the reference to mesh vertices
             min_dist = sys.float_info.max
index 6356da216b1cc8d7f0f88c08c7caa4bed47559ab..be680a6df0c939f684bf9bdc791ebcdabe5c07da 100644 (file)
@@ -81,16 +81,18 @@ class SelectPattern(Operator):
         # Can be pose bones or objects
         for item in items:
             if pattern_match(item.name, self.pattern):
-                item.select = True
 
                 # hrmf, perhaps there should be a utility function for this.
                 if is_ebone:
+                    item.select = True
                     item.select_head = True
                     item.select_tail = True
                     if item.use_connect:
                         item_parent = item.parent
                         if item_parent is not None:
                             item_parent.select_tail = True
+                else:
+                    item.select_set(action='SELECT')
 
         return {'FINISHED'}
 
@@ -136,7 +138,7 @@ class SelectCamera(Operator):
                 bpy.ops.object.select_all(action='DESELECT')
             scene.objects.active = camera
             camera.hide = False
-            camera.select = True
+            camera.select_set(action='SELECT')
             return {'FINISHED'}
 
         return {'CANCELLED'}
@@ -202,7 +204,7 @@ class SelectHierarchy(Operator):
                 bpy.ops.object.select_all(action='DESELECT')
 
             for obj in select_new:
-                obj.select = True
+                obj.select_set(action='SELECT')
 
             scene.objects.active = act_new
             return {'FINISHED'}
@@ -644,8 +646,8 @@ class MakeDupliFace(Operator):
             ob_new.use_dupli_faces_scale = True
             ob_new.dupli_faces_scale = 1.0 / SCALE_FAC
 
-            ob_inst.select = True
-            ob_new.select = True
+            ob_inst.select_set(action='SELECT')
+            ob_new.select_set(action='SELECT')
 
     def execute(self, context):
         self._main(context)
@@ -664,7 +666,7 @@ class IsolateTypeRender(Operator):
 
         for obj in context.visible_objects:
 
-            if obj.select:
+            if obj.select_get():
                 obj.hide_render = False
             else:
                 if obj.type == act_type:
@@ -1029,8 +1031,8 @@ class LodGenerate(Operator):
             for level in ob.lod_levels[1:]:
                 level.object.hide = level.object.hide_render = True
 
-        lod.select = False
-        ob.select = True
+        lod.select_set(action='DESELECT')
+        ob.select_set(action='SELECT')
         scene.objects.active = ob
 
         return {'FINISHED'}
index 750a5b0bf0f8cbbbd5d390ca2f6ea9e10246be2a..cba49c629be01e2aa193073e7758d5be23f1569f 100644 (file)
@@ -63,7 +63,7 @@ class CopyRigidbodySettings(Operator):
         # deselect all but mesh objects
         for o in context.selected_objects:
             if o.type != 'MESH':
-                o.select = False
+                o.select_set(action='DESELECT')
             elif o.rigid_body is None:
                 # Add rigidbody to object!
                 scene.objects.active = o
@@ -125,7 +125,7 @@ class BakeToKeyframes(Operator):
         # filter objects selection
         for obj in context.selected_objects:
             if not obj.rigid_body or obj.rigid_body.type != 'ACTIVE':
-                obj.select = False
+                obj.select_set(action='DESELECT')
 
         objects = context.selected_objects
 
@@ -258,7 +258,7 @@ class ConnectRigidBodies(Operator):
         ob.location = loc
         context.scene.objects.link(ob)
         context.scene.objects.active = ob
-        ob.select = True
+        ob.select_set(action='SELECT')
 
         bpy.ops.rigidbody.constraint_add()
         con_obj = context.active_object
@@ -303,7 +303,7 @@ class ConnectRigidBodies(Operator):
             # restore selection
             bpy.ops.object.select_all(action='DESELECT')
             for obj in objects:
-                obj.select = True
+                obj.select_set(action='SELECT')
             scene.objects.active = obj_act
             return {'FINISHED'}
         else:
index 2389be6787d2dfc5cd7f213918e357b754a147f5..0f26ff75715e5092f433b0a1ccc2e00de20bee8e 100644 (file)
@@ -29,6 +29,7 @@ if "bpy" in locals():
 
 _modules = [
     "properties_animviz",
+    "properties_collection",
     "properties_constraint",
     "properties_data_armature",
     "properties_data_bone",
@@ -69,6 +70,7 @@ _modules = [
     "space_graph",
     "space_image",
     "space_info",
+    "space_collections",
     "space_logic",
     "space_nla",
     "space_node",
diff --git a/release/scripts/startup/bl_ui/properties_collection.py b/release/scripts/startup/bl_ui/properties_collection.py
new file mode 100644 (file)
index 0000000..d67d694
--- /dev/null
@@ -0,0 +1,79 @@
+# ##### 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>
+import bpy
+from bpy.types import Panel, UIList
+
+
+class CollectionButtonsPanel:
+    bl_space_type = 'PROPERTIES'
+    bl_region_type = 'WINDOW'
+    bl_context = "collection"
+
+
+class COLLECTION_PT_context_collection(CollectionButtonsPanel, Panel):
+    bl_label = ""
+    bl_options = {'HIDE_HEADER'}
+
+    def draw(self, context):
+        layout = self.layout
+        space = context.space_data
+
+        collection = context.layer_collection
+        name = collection.name
+        if name == 'Master Collection':
+            layout.label(text=name, icon='COLLAPSEMENU')
+        else:
+            layout.prop(collection, "name", text="", icon='COLLAPSEMENU')
+
+
+class COLLECTION_UL_objects(UIList):
+    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+        # assert(isinstance(item, bpy.types.Object)
+        ob = item
+        if self.layout_type in {'DEFAULT', 'COMPACT'}:
+            layout.label(ob.name, icon_value=icon)
+
+        elif self.layout_type == 'GRID':
+            layout.alignment = 'CENTER'
+            layout.label("", icon_value=icon)
+
+
+class COLLECTION_PT_objects(CollectionButtonsPanel, Panel):
+    bl_label = "Objects"
+
+    def draw(self, context):
+        layout = self.layout
+        scene = context.scene
+        collection = context.scene_collection
+
+        row = layout.row()
+        row.template_list("COLLECTION_UL_objects", "name", collection, "objects", collection.objects, "active_index", rows=2)
+
+        col = row.column(align=True)
+        col.operator("collections.objects_add", icon='ZOOMIN', text="")
+        col.operator("collections.objects_remove", icon='ZOOMOUT', text="")
+
+        row = layout.row(align=True)
+        row.operator("collections.objects_select", text="Select")
+        row.operator("collections.objects_deselect", text="Deselect")
+
+
+if __name__ == "__main__":  # only for live edit.
+    bpy.utils.register_module(__name__)
index 9b8bc237db96dfdc65434bb46db96fcc78c43ced..45c93dd9335d38af3ec1bf37fe269453a595e4bf 100644 (file)
@@ -35,7 +35,7 @@ class RenderLayerButtonsPanel:
 
 class RENDERLAYER_UL_renderlayers(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
-        # assert(isinstance(item, bpy.types.SceneRenderLayer)
+        # assert(isinstance(item, bpy.types.SceneLayer)
         layer = item
         if self.layout_type in {'DEFAULT', 'COMPACT'}:
             layout.prop(layer, "name", text="", icon_value=icon, emboss=False)
@@ -62,7 +62,7 @@ class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
 
         row = layout.row()
         col = row.column()
-        col.template_list("RENDERLAYER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
+        col.template_list("RENDERLAYER_UL_renderlayers", "", scene, "render_layers", scene.render_layers, "active_index", rows=2)
 
         col = row.column()
         sub = col.column(align=True)
@@ -71,103 +71,6 @@ class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
         col.prop(rd, "use_single_layer", icon_only=True)
 
 
-class RENDERLAYER_PT_layer_options(RenderLayerButtonsPanel, Panel):
-    bl_label = "Layer"
-    COMPAT_ENGINES = {'BLENDER_RENDER'}
-
-    def draw(self, context):
-        layout = self.layout
-
-        scene = context.scene
-        rd = scene.render
-        rl = rd.layers.active
-
-        split = layout.split()
-
-        col = split.column()
-        col.prop(scene, "layers", text="Scene")
-        col.label(text="")
-        col.prop(rl, "light_override", text="Lights")
-        col.prop(rl, "material_override", text="Material")
-
-        col = split.column()
-        col.prop(rl, "layers", text="Layer")
-        col.prop(rl, "layers_zmask", text="Mask Layer")
-
-        layout.separator()
-        layout.label(text="Include:")
-
-        split = layout.split()
-
-        col = split.column()
-        col.prop(rl, "use_zmask")
-        row = col.row()
-        row.prop(rl, "invert_zmask", text="Negate")
-        row.active = rl.use_zmask
-        col.prop(rl, "use_all_z")
-
-        col = split.column()
-        col.prop(rl, "use_solid")
-        col.prop(rl, "use_halo")
-        col.prop(rl, "use_ztransp")
-
-        col = split.column()
-        col.prop(rl, "use_sky")
-        col.prop(rl, "use_edge_enhance")
-        col.prop(rl, "use_strand")
-        if bpy.app.build_options.freestyle:
-            row = col.row()
-            row.prop(rl, "use_freestyle")
-            row.active = rd.use_freestyle
-
-
-class RENDERLAYER_PT_layer_passes(RenderLayerButtonsPanel, Panel):
-    bl_label = "Passes"
-    bl_options = {'DEFAULT_CLOSED'}
-    COMPAT_ENGINES = {'BLENDER_RENDER'}
-
-    @staticmethod
-    def draw_pass_type_buttons(box, rl, pass_type):
-        # property names
-        use_pass_type = "use_pass_" + pass_type
-        exclude_pass_type = "exclude_" + pass_type
-        # draw pass type buttons
-        row = box.row()
-        row.prop(rl, use_pass_type)
-        row.prop(rl, exclude_pass_type, text="")
-
-    def draw(self, context):
-        layout = self.layout
-
-        scene = context.scene
-        rd = scene.render
-        rl = rd.layers.active
-
-        split = layout.split()
-
-        col = split.column()
-        col.prop(rl, "use_pass_combined")
-        col.prop(rl, "use_pass_z")
-        col.prop(rl, "use_pass_vector")
-        col.prop(rl, "use_pass_normal")
-        col.prop(rl, "use_pass_uv")
-        col.prop(rl, "use_pass_mist")
-        col.prop(rl, "use_pass_object_index")
-        col.prop(rl, "use_pass_material_index")
-        col.prop(rl, "use_pass_color")
-
-        col = split.column()
-        col.prop(rl, "use_pass_diffuse")
-        self.draw_pass_type_buttons(col, rl, "specular")
-        self.draw_pass_type_buttons(col, rl, "shadow")
-        self.draw_pass_type_buttons(col, rl, "emit")
-        self.draw_pass_type_buttons(col, rl, "ambient_occlusion")
-        self.draw_pass_type_buttons(col, rl, "environment")
-        self.draw_pass_type_buttons(col, rl, "indirect")
-        self.draw_pass_type_buttons(col, rl, "reflection")
-        self.draw_pass_type_buttons(col, rl, "refraction")
-
-
 class RENDERLAYER_UL_renderviews(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
         # assert(isinstance(item, bpy.types.SceneRenderView)
diff --git a/release/scripts/startup/bl_ui/space_collections.py b/release/scripts/startup/bl_ui/space_collections.py
new file mode 100644 (file)
index 0000000..9b612ce
--- /dev/null
@@ -0,0 +1,41 @@
+# ##### 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>
+import bpy
+from bpy.types import Header, Menu
+
+
+class COLLECTIONS_HT_header(Header):
+    bl_space_type = 'COLLECTION_MANAGER'
+
+    def draw(self, context):
+        layout = self.layout
+
+        layout.template_header()
+
+        row = layout.row(align=True)
+        row.operator("collections.collection_new", text="", icon='NEW')
+        row.operator("collections.override_new", text="", icon='LINK_AREA')
+        row.operator("collections.collection_link", text="", icon='LINKED')
+        row.operator("collections.collection_unlink", text="", icon='UNLINKED')
+        row.operator("collections.delete", text="", icon='X')
+
+
+if __name__ == "__main__":  # only for live edit.
+    bpy.utils.register_module(__name__)
index f8e4d1338f9402746378f543417b924af2af4319..e397a85aa58ac856b552c1be02ebf1355dfcdfd2 100644 (file)
@@ -634,7 +634,6 @@ class VIEW3D_MT_select_object(Menu):
         layout.operator("object.select_all", text="Inverse").action = 'INVERT'
         layout.operator("object.select_random", text="Random")
         layout.operator("object.select_mirror", text="Mirror")
-        layout.operator("object.select_by_layer", text="Select All by Layer")
         layout.operator_menu_enum("object.select_by_type", "type", text="Select All by Type...")
         layout.operator("object.select_camera", text="Select Camera")
 
@@ -1311,15 +1310,6 @@ class VIEW3D_MT_object(Menu):
 
         layout.separator()
 
-        if is_local_view:
-            layout.operator_context = 'EXEC_REGION_WIN'
-            layout.operator("object.move_to_layer", text="Move out of Local View")
-            layout.operator_context = 'INVOKE_REGION_WIN'
-        else:
-            layout.operator("object.move_to_layer", text="Move to Layer...")
-
-        layout.menu("VIEW3D_MT_object_showhide")
-
         layout.operator_menu_enum("object.convert", "target")
 
 
@@ -1597,17 +1587,6 @@ class VIEW3D_MT_object_quick_effects(Menu):
         layout.operator("object.quick_fluid")
 
 
-class VIEW3D_MT_object_showhide(Menu):
-    bl_label = "Show/Hide"
-
-    def draw(self, context):
-        layout = self.layout
-
-        layout.operator("object.hide_view_clear", text="Show Hidden")
-        layout.operator("object.hide_view_set", text="Hide Selected").unselected = False
-        layout.operator("object.hide_view_set", text="Hide Unselected").unselected = True
-
-
 class VIEW3D_MT_make_single_user(Menu):
     bl_label = "Make Single User"
 
@@ -3167,6 +3146,74 @@ class VIEW3D_PT_viewport_debug(Panel):
         col.row(align=True).prop(view, "debug_background", expand=True)
 
 
+class VIEW3D_PT_collections_editor(Panel):
+    bl_space_type = 'VIEW_3D'
+    bl_region_type = 'UI'
+    bl_label = "Collections"
+    bl_options = {'DEFAULT_CLOSED'}
+
+    @classmethod
+    def poll(cls, context):
+        return context.space_data
+
+    def draw(self, context):
+        layout = self.layout
+        layer = context.render_layer
+        active_collection = context.layer_collection
+
+        col = layout.column()
+        box = col.box()
+
+        index = -1
+        for collection in layer.collections:
+            index = self._draw_layer_collection(box, index, active_collection, collection, True, True)
+
+        row = layout.row(align=True)
+        row.operator("collections.collection_new", text="", icon='NEW')
+        row.operator("collections.override_new", text="", icon='LINK_AREA')
+        row.operator("collections.collection_link", text="", icon='LINKED')
+        row.operator("collections.collection_unlink", text="", icon='UNLINKED')
+        row.operator("collections.delete", text="", icon='X')
+
+    def _draw_layer_collection(self, box, index, active_collection, collection, is_active, is_draw, depth=0):
+        index += 1
+        nested_collections = collection.collections
+
+        if is_draw:
+            row = box.row()
+            row.active = is_active
+            is_collection_selected = (collection == active_collection)
+
+            if is_collection_selected:
+                sub_box = row.box()
+                row = sub_box.row()
+
+            row.label(text="{0}{1}{2}".format(
+                "  " * depth,
+                u'\u21b3 ' if depth else "",
+                collection.name))
+
+            row.prop(collection, "hide", text="", emboss=False)
+            row.prop(collection, "hide_select", text="", emboss=False)
+
+            row.operator("collections.select", text="", icon='BLANK1' if is_collection_selected else 'HAND', emboss=False).collection_index=index
+
+            if nested_collections:
+                row.prop(collection, "is_unfolded", text="", emboss=False)
+            else:
+                row.label(icon='BLANK1')
+
+            if not collection.is_unfolded:
+                is_draw = False
+
+            is_active &= not collection.hide
+
+        for nested_collection in nested_collections:
+            index = self._draw_layer_collection(box, index, active_collection, nested_collection, is_active, is_draw, depth + 1)
+
+        return index
+
+
 class VIEW3D_PT_grease_pencil(GreasePencilDataPanel, Panel):
     bl_space_type = 'VIEW_3D'
     bl_region_type = 'UI'
index 6c77c5d6a1ab599522f2dd7e4a7fb40a7b2e8342..8de7a5e290397f8e829e6dd127ed5562f6dab19f 100644 (file)
@@ -18,7 +18,7 @@ bpy.ops.object.select_all(action='DESELECT')
 
 for obj in selection:
 
-    obj.select = True
+    obj.select_set(action='SELECT')
 
     # some exporters only use the active object
     scene.objects.active = obj
@@ -31,7 +31,7 @@ for obj in selection:
     ## Can be used for multiple formats
     # bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True)
 
-    obj.select = False
+    obj.select_set(action='DESELECT')
 
     print("written:", fn)
 
@@ -39,4 +39,4 @@ for obj in selection:
 scene.objects.active = obj_active
 
 for obj in selection:
-    obj.select = True
+    obj.select_set(action='SELECT')
index c4d661b4c1f819a63d29cf45626957c267107d72..e3b63813fc4a749a4032e670c0fd0a4e27ad1573 100644 (file)
@@ -67,7 +67,7 @@ def main(context, event):
     # now we have the object under the mouse cursor,
     # we could do lots of stuff but for the example just select.
     if best_obj is not None:
-        best_obj.select = True
+        best_obj.select_set(action='SELECT')
         context.scene.objects.active = best_obj
 
 
index ff8b0442ab682c38a0d7e92b4145fdb27efe128f..cc61d5ad49f5615297ba2c26e359ee90e739aef7 100644 (file)
@@ -341,7 +341,7 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled)
 
 void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx)
 {
-       Base *base = static_cast<Base *>(m_scene->base.first);
+       BaseLegacy *base = static_cast<BaseLegacy *>(m_scene->base.first);
 
        while (base) {
                Object *ob = base->object;
@@ -366,7 +366,7 @@ void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx)
 
 void AbcExporter::createTransformWritersFlat()
 {
-       Base *base = static_cast<Base *>(m_scene->base.first);
+       BaseLegacy *base = static_cast<BaseLegacy *>(m_scene->base.first);
 
        while (base) {
                Object *ob = base->object;
@@ -445,7 +445,7 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl
 
 void AbcExporter::createShapeWriters(EvaluationContext *eval_ctx)
 {
-       Base *base = static_cast<Base *>(m_scene->base.first);
+       BaseLegacy *base = static_cast<BaseLegacy *>(m_scene->base.first);
 
        while (base) {
                Object *ob = base->object;
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
new file mode 100644 (file)
index 0000000..c3f461d
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * ***** 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.
+ *
+ * Contributor(s): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_COLLECTION_H__
+#define __BKE_COLLECTION_H__
+
+/** \file blender/blenkernel/BKE_collection.h
+ *  \ingroup bke
+ */
+
+#include "BLI_ghash.h"
+#include "BLI_iterator.h"
+#include "DNA_listBase.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Iterator;
+struct SceneCollection;
+struct Object;
+struct Base;
+struct Main;
+struct Scene;
+
+struct SceneCollection *BKE_collection_add(struct Scene *scene, struct SceneCollection *sc_parent, const char *name);
+bool BKE_collection_remove(struct Scene *scene, struct SceneCollection *sc);
+struct SceneCollection *BKE_collection_master(struct Scene *scene);
+void BKE_collection_master_free(struct Scene *scene);
+void BKE_collection_object_add(struct Scene *scene, struct SceneCollection *sc, struct Object *object);
+void BKE_collection_object_add_from(struct Scene *scene, struct Object *ob_src, struct Object *ob_dst);
+void BKE_collection_object_remove(struct Main *bmain, struct Scene *scene, struct SceneCollection *sc, struct Object *object, const bool free_us);
+void BKE_collections_object_remove(struct Main *bmain, struct Scene *scene, struct Object *object, const bool free_us);
+
+typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data);
+typedef void (*BKE_scene_collections_Cb)(struct SceneCollection *ob, void *data);
+
+void BKE_scene_collections_callback(struct Scene *scene, BKE_scene_collections_Cb callback, void *data);
+void BKE_scene_objects_callback(struct Scene *scene, BKE_scene_objects_Cb callback, void *data);
+
+/* iterators */
+void BKE_scene_collections_Iterator_begin(struct Iterator *iter, void *data_in);
+void BKE_scene_collections_Iterator_next(struct Iterator *iter);
+void BKE_scene_collections_Iterator_end(struct Iterator *iter);
+
+void BKE_scene_objects_Iterator_begin(struct Iterator *iter, void *data_in);
+void BKE_scene_objects_Iterator_next(struct Iterator *iter);
+void BKE_scene_objects_Iterator_end(struct Iterator *iter);
+
+#define FOREACH_SCENE_COLLECTION(scene, _sc)                                  \
+       ITER_BEGIN(BKE_scene_collections_Iterator_begin,                          \
+                  BKE_scene_collections_Iterator_next,                           \
+                  BKE_scene_collections_Iterator_end,                            \
+                  scene, _sc)
+
+#define FOREACH_SCENE_COLLECTION_END                                          \
+       ITER_END
+
+#define FOREACH_SCENE_OBJECT(scene, _ob)                                      \
+       ITER_BEGIN(BKE_scene_objects_Iterator_begin,                              \
+                  BKE_scene_objects_Iterator_next,                               \
+                  BKE_scene_objects_Iterator_end,                                \
+                  scene, _ob)
+
+#define FOREACH_SCENE_OBJECT_END                                              \
+       ITER_END
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_COLLECTION_H__ */
index 4da6a61cbfacb8eaa933c9f7e272f8c3c1bd3d28..23f9ff28f8b8ac99409b7bb61991c79efeb97f19 100644 (file)
@@ -40,12 +40,16 @@ extern "C" {
 struct ARegion;
 struct bScreen;
 struct CacheFile;
+struct LayerCollection;
 struct ListBase;
 struct Main;
 struct Object;
+struct Base;
 struct PointerRNA;
 struct ReportList;
 struct Scene;
+struct SceneCollection;
+struct SceneLayer;
 struct ScrArea;
 struct SpaceLink;
 struct View3D;
@@ -166,6 +170,7 @@ struct SpaceAction *CTX_wm_space_action(const bContext *C);
 struct SpaceInfo *CTX_wm_space_info(const bContext *C);
 struct SpaceUserPref *CTX_wm_space_userpref(const bContext *C);
 struct SpaceClip *CTX_wm_space_clip(const bContext *C);
+struct SpaceCollections *CTX_wm_space_collections(const bContext *C);
 
 void CTX_wm_manager_set(bContext *C, struct wmWindowManager *wm);
 void CTX_wm_window_set(bContext *C, struct wmWindow *win);
@@ -239,6 +244,9 @@ int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBas
 
 struct Main *CTX_data_main(const bContext *C);
 struct Scene *CTX_data_scene(const bContext *C);
+struct LayerCollection *CTX_data_layer_collection(const bContext *C);
+struct SceneCollection *CTX_data_scene_collection(const bContext *C);
+struct SceneLayer *CTX_data_scene_layer(const bContext *C);
 struct ToolSettings *CTX_data_tool_settings(const bContext *C);
 
 const char *CTX_data_mode_string(const bContext *C);
index 09a069ee36fafb36365d399b0bff86f4e5d69041..f718e9c85558835378df76ed3018d3c2fa7ff75e 100644 (file)
@@ -33,6 +33,7 @@
  *  \author nzc
  */
 
+struct BaseLegacy;
 struct Base;
 struct EvaluationContext;
 struct Group;
@@ -44,8 +45,8 @@ void          BKE_group_free(struct Group *group);
 struct Group *BKE_group_add(struct Main *bmain, const char *name);
 struct Group *BKE_group_copy(struct Main *bmain, struct Group *group);
 void          BKE_group_make_local(struct Main *bmain, struct Group *group, const bool lib_local);
-bool          BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
-bool          BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
+bool          BKE_group_object_add(struct Group *group, struct Object *ob);
+bool          BKE_group_object_unlink(struct Group *group, struct Object *ob);
 struct Group *BKE_group_object_find(struct Group *group, struct Object *ob);
 bool          BKE_group_object_exists(struct Group *group, struct Object *ob);
 bool          BKE_group_object_cyclic_check(struct Main *bmain, struct Object *object, struct Group *group);
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
new file mode 100644 (file)
index 0000000..850c63f
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * ***** 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.
+ *
+ * Contributor(s): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_LAYER_H__
+#define __BKE_LAYER_H__
+
+/** \file blender/blenkernel/BKE_layer.h
+ *  \ingroup bke
+ */
+
+#include "BKE_collection.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TODO_LAYER_SYNC /* syncing of SceneCollection and LayerCollection trees*/
+#define TODO_LAYER_SYNC_FILTER /* syncing of filter_objects across all trees */
+#define TODO_LAYER_OVERRIDE /* CollectionOverride */
+#define TODO_LAYER_CONTEXT /* get/set current (context) SceneLayer */
+#define TODO_LAYER_BASE /* BaseLegacy to Base related TODO */
+#define TODO_LAYER_OPERATORS /* collection mamanger and property panel operators */
+#define TODO_LAYER /* generic todo */
+
+struct Base;
+struct ID;
+struct LayerCollection;
+struct Main;
+struct Object;
+struct Scene;
+struct SceneCollection;
+struct SceneLayer;
+
+struct SceneLayer *BKE_scene_layer_add(struct Scene *scene, const char *name);
+
+bool BKE_scene_layer_remove(struct Main *bmain, struct Scene *scene, struct SceneLayer *sl);
+
+void BKE_scene_layer_free(struct SceneLayer *sl);
+
+void BKE_scene_layer_engine_set(struct SceneLayer *sl, const char *engine);
+
+void BKE_scene_layer_selected_objects_tag(struct SceneLayer *sl, const int tag);
+
+struct SceneLayer *BKE_scene_layer_find_from_collection(struct Scene *scene, struct LayerCollection *lc);
+struct Base *BKE_scene_layer_base_find(struct SceneLayer *sl, struct Object *ob);
+void BKE_scene_layer_base_deselect_all(struct SceneLayer *sl);
+void BKE_scene_layer_base_select(struct SceneLayer *sl, struct Base *selbase);
+void BKE_scene_layer_base_flag_recalculate(struct SceneLayer *sl);
+
+void BKE_layer_collection_free(struct SceneLayer *sl, struct LayerCollection *lc);
+
+struct LayerCollection *BKE_layer_collection_active(struct SceneLayer *sl);
+
+int BKE_layer_collection_count(struct SceneLayer *sl);
+
+int BKE_layer_collection_findindex(struct SceneLayer *sl, struct LayerCollection *lc);
+
+struct LayerCollection *BKE_collection_link(struct SceneLayer *sl, struct SceneCollection *sc);
+
+void BKE_collection_unlink(struct SceneLayer *sl, struct LayerCollection *lc);
+
+bool BKE_scene_layer_has_collection(struct SceneLayer *sl, struct SceneCollection *sc);
+bool BKE_scene_has_object(struct Scene *scene, struct Object *ob);
+
+/* syncing */
+
+void BKE_layer_sync_new_scene_collection(struct Scene *scene, const struct SceneCollection *sc_parent, struct SceneCollection *sc);
+void BKE_layer_sync_object_link(struct Scene *scene, struct SceneCollection *sc, struct Object *ob);
+void BKE_layer_sync_object_unlink(struct Scene *scene, struct SceneCollection *sc, struct Object *ob);
+
+/* override */
+
+void BKE_collection_override_datablock_add(struct LayerCollection *lc, const char *data_path, struct ID *id);
+
+/* iterators */
+
+void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in);
+void BKE_selected_objects_Iterator_next(Iterator *iter);
+void BKE_selected_objects_Iterator_end(Iterator *iter);
+
+void BKE_visible_objects_Iterator_begin(Iterator *iter, void *data_in);
+void BKE_visible_objects_Iterator_next(Iterator *iter);
+void BKE_visible_objects_Iterator_end(Iterator *iter);
+
+void BKE_visible_bases_Iterator_begin(Iterator *iter, void *data_in);
+void BKE_visible_bases_Iterator_next(Iterator *iter);
+void BKE_visible_bases_Iterator_end(Iterator *iter);
+
+#define FOREACH_SELECTED_OBJECT(sl, _ob)                                      \
+       ITER_BEGIN(BKE_selected_objects_Iterator_begin,                           \
+                  BKE_selected_objects_Iterator_next,                            \
+                  BKE_selected_objects_Iterator_end,                             \
+                  sl, _ob)
+
+#define FOREACH_SELECTED_OBJECT_END                                           \
+       ITER_END
+
+#define FOREACH_VISIBLE_OBJECT(sl, _ob)                                       \
+       ITER_BEGIN(BKE_visible_objects_Iterator_begin,                            \
+                  BKE_visible_objects_Iterator_next,                             \
+                  BKE_visible_objects_Iterator_end,                              \
+                  sl, _ob)
+
+#define FOREACH_VISIBLE_OBJECT_END                                            \
+       ITER_END
+
+
+#define FOREACH_VISIBLE_BASE(sl, _object_base)                                \
+       ITER_BEGIN(BKE_visible_bases_Iterator_begin,                              \
+                  BKE_visible_bases_Iterator_next,                               \
+                  BKE_visible_bases_Iterator_end,                                \
+                  sl, _object_base)
+
+#define FOREACH_VISIBLE_BASE_END                                              \
+       ITER_END
+
+
+#define FOREACH_OBJECT(sl, _ob)                                               \
+{                                                                             \
+       Base *base;                                                               \
+       for (base = sl->object_bases.first; base; base = base->next) {            \
+           _ob = base->object;
+
+#define FOREACH_OBJECT_END                                                    \
+    }                                                                         \
+}
+
+#define FOREACH_OBJECT_FLAG(scene, sl, flag, _ob)                             \
+{                                                                             \
+       IteratorBeginCb func_begin;                                               \
+       IteratorCb func_next, func_end;                                           \
+       void *data_in;                                                            \
+                                                                                 \
+       if (flag == SELECT) {                                                     \
+           func_begin = &BKE_selected_objects_Iterator_begin;                    \
+           func_next = &BKE_selected_objects_Iterator_next;                      \
+           func_end = &BKE_selected_objects_Iterator_end;                        \
+           data_in = sl;                                                         \
+    }                                                                         \
+       else {                                                                    \
+           func_begin = BKE_scene_objects_Iterator_begin;                        \
+           func_next = BKE_scene_objects_Iterator_next;                          \
+           func_end = BKE_scene_objects_Iterator_end;                            \
+           data_in = scene;                                                      \
+    }                                                                         \
+       ITER_BEGIN(func_begin, func_next, func_end, data_in, _ob)
+
+
+#define FOREACH_OBJECT_FLAG_END                                               \
+       ITER_END                                                                  \
+}
+
+/* temporary hacky solution waiting for final depsgraph evaluation */
+#define DEG_OBJECT_ITER(sl_, ob_)                                             \
+{                                                                             \
+       /* flush all the data to objects*/                                        \
+       Base *base_;                                                              \
+       for (base_ = sl->object_bases.first; base_; base_ = base_->next) {        \
+           ob_ = base_->object;                                                              \
+           ob_->base_flag = base_->flag;
+
+#define DEG_OBJECT_ITER_END                                                   \
+    }                                                                         \
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_LAYER_H__ */
index 546f0d97c2b26d9db592440805532fa2fa83cd0b..67f7fa5e029861c943c841e48c6af6ab804f651c 100644 (file)
@@ -687,6 +687,13 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
 }
 /** \} */
 
+
+/* -------------------------------------------------------------------- */
+/** \name Node Tree
+ */
+
+void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, const int layer_index);
+
 /* -------------------------------------------------------------------- */
 /** \name Shader Nodes
  */
index b1e218d3e5f806232bb9019e663114e82a96e7a2..c1655d3e9c62fbe7028865f1b2c8a32350b6000b 100644 (file)
@@ -35,12 +35,13 @@ extern "C" {
 
 #include "BLI_compiler_attrs.h"
 
-struct Base;
+struct BaseLegacy;
 struct EvaluationContext;
 struct Scene;
 struct Object;
 struct BoundBox;
 struct View3D;
+struct SceneLayer;
 struct SoftBody;
 struct BulletSoftBody;
 struct MovieClip;
@@ -89,9 +90,9 @@ struct Object *BKE_object_add_only_object(
         int type, const char *name)
         ATTR_NONNULL(1) ATTR_RETURNS_NONNULL;
 struct Object *BKE_object_add(
-        struct Main *bmain, struct Scene *scene,
+        struct Main *bmain, struct Scene *scene, struct SceneLayer *sl,
         int type, const char *name)
-        ATTR_NONNULL(1, 2) ATTR_RETURNS_NONNULL;
+        ATTR_NONNULL(1, 2, 3) ATTR_RETURNS_NONNULL;
 void *BKE_object_obdata_add_from_type(
         struct Main *bmain,
         int type, const char *name)
@@ -255,7 +256,7 @@ typedef enum eObjectSet {
 
 struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter);
 struct LinkNode *BKE_object_groups(struct Object *ob);
-void             BKE_object_groups_clear(struct Scene *scene, struct Base *base, struct Object *object);
+void             BKE_object_groups_clear(struct Object *object);
 
 struct KDTree *BKE_object_as_kdtree(struct Object *ob, int *r_tot);
 
index d2152950bff48a82bc883f1cf7dd194a22ce8cc1..53bb69aedb6f6d8bbf89d2d87064747d81a0db4b 100644 (file)
@@ -38,10 +38,11 @@ extern "C" {
 #endif
 
 struct AviCodecData;
-struct Base;
+struct BaseLegacy;
 struct EvaluationContext;
 struct Main;
 struct Object;
+struct Base;
 struct QuicktimeCodecData;
 struct RenderData;
 struct SceneRenderLayer;
@@ -61,7 +62,7 @@ struct Main;
        _base;                                                                    \
        _base = _setlooper_base_step(&_sce_iter, _base)
 
-struct Base *_setlooper_base_step(struct Scene **sce_iter, struct Base *base);
+struct BaseLegacy *_setlooper_base_step(struct Scene **sce_iter, struct BaseLegacy *base);
 
 void free_avicodecdata(struct AviCodecData *acd);
 void free_qtcodecdata(struct QuicktimeCodecData *acd);
@@ -70,13 +71,15 @@ void BKE_scene_free(struct Scene *sce);
 void BKE_scene_init(struct Scene *sce);
 struct Scene *BKE_scene_add(struct Main *bmain, const char *name);
 
+void BKE_scene_remove_rigidbody_object(struct Scene *scene, struct Object *ob);
+
 /* base functions */
-struct Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name);
-struct Base *BKE_scene_base_find(struct Scene *scene, struct Object *ob);
-struct Base *BKE_scene_base_add(struct Scene *sce, struct Object *ob);
-void         BKE_scene_base_unlink(struct Scene *sce, struct Base *base);
+struct BaseLegacy *BKE_scene_base_find_by_name(struct Scene *scene, const char *name);
+struct BaseLegacy *BKE_scene_base_find(struct Scene *scene, struct Object *ob);
+struct BaseLegacy *BKE_scene_base_add(struct Scene *sce, struct Object *ob);
+void         BKE_scene_base_unlink(struct Scene *sce, struct BaseLegacy *base);
 void         BKE_scene_base_deselect_all(struct Scene *sce);
-void         BKE_scene_base_select(struct Scene *sce, struct Base *selbase);
+void         BKE_scene_base_select(struct Scene *sce, struct BaseLegacy *selbase);
 
 /* Scene base iteration function.
  * Define struct here, so no need to bother with alloc/free it.
@@ -90,10 +93,14 @@ typedef struct SceneBaseIter {
 } SceneBaseIter;
 
 int BKE_scene_base_iter_next(struct EvaluationContext *eval_ctx, struct SceneBaseIter *iter,
-                             struct Scene **scene, int val, struct Base **base, struct Object **ob);
+                             struct Scene **scene, int val, struct BaseLegacy **base, struct Object **ob);
 
 void BKE_scene_base_flag_to_objects(struct Scene *scene);
 void BKE_scene_base_flag_from_objects(struct Scene *scene);
+void BKE_scene_base_flag_sync_from_base(struct BaseLegacy *base);
+void BKE_scene_base_flag_sync_from_object(struct BaseLegacy *base);
+void BKE_scene_object_base_flag_sync_from_base(struct Base *base);
+void BKE_scene_object_base_flag_sync_from_object(struct Base *base);
 
 void BKE_scene_set_background(struct Main *bmain, struct Scene *sce);
 struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name);
index f3bab55b47daf88c82f398038a26b192f804b168..6202c84f320c87a3c6dc1cfd8086b9aa75df95f1 100644 (file)
@@ -85,6 +85,7 @@ set(SRC
        intern/camera.c
        intern/cdderivedmesh.c
        intern/cloth.c
+       intern/collection.c
        intern/collision.c
        intern/colortools.c
        intern/constraint.c
@@ -157,6 +158,7 @@ set(SRC
        intern/pbvh_bmesh.c
        intern/pointcache.c
        intern/property.c
+       intern/layer.c
        intern/report.c
        intern/rigidbody.c
        intern/sca.c
@@ -214,6 +216,7 @@ set(SRC
        BKE_ccg.h
        BKE_cdderivedmesh.h
        BKE_cloth.h
+       BKE_collection.h
        BKE_collision.h
        BKE_colortools.h
        BKE_constraint.h
@@ -274,6 +277,7 @@ set(SRC
        BKE_pbvh.h
        BKE_pointcache.h
        BKE_property.h
+       BKE_layer.h
        BKE_report.h
        BKE_rigidbody.h
        BKE_sca.h
index 2f65e71c6d29f863431452432aa47ec3f9b9b6ef..237e4e8017279fd62329b8e3e1b33d359f000ef5 100644 (file)
@@ -283,7 +283,7 @@ void animviz_get_object_motionpaths(Object *ob, ListBase *targets)
 /* tweak the object ordering to trick depsgraph into making MotionPath calculations run faster */
 static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets)
 {
-       Base *base, *baseNext;
+       BaseLegacy *base, *baseNext;
        MPathTarget *mpt;
        
        /* make sure our temp-tag isn't already in use */
@@ -321,7 +321,7 @@ static void motionpaths_calc_update_scene(Scene *scene)
                BKE_scene_update_for_newframe(G.main->eval_ctx, G.main, scene, scene->lay);
        }
        else { /* otherwise we can optimize by restricting updates */
-               Base *base, *last = NULL;
+               BaseLegacy *base, *last = NULL;
                
                /* only stuff that moves or needs display still */
                DAG_scene_update_flags(G.main, scene, scene->lay, true, false);
index 3dce08eb756be7a839a2a42a1be27c2dd7fd8017..8630e8562b07bdf20e05b8ea9356eb49aa8f4e0f 100644 (file)
@@ -205,7 +205,7 @@ float BKE_cachefile_time_offset(CacheFile *cache_file, const float time, const f
 /* TODO(kevin): replace this with some depsgraph mechanism, or something similar. */
 void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file)
 {
-       for (Base *base = scene->base.first; base; base = base->next) {
+       for (BaseLegacy *base = scene->base.first; base; base = base->next) {
                Object *ob = base->object;
 
                ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
index 9cb553aa27b59f79b5688138073247d5831280b9..978204f1cf5028b6612ecac82e0c6b1fbf8dd36a 100644 (file)
@@ -853,7 +853,7 @@ static Object *camera_multiview_advanced(Scene *scene, Object *camera, const cha
        }
 
        if (name[0] != '\0') {
-               Base *base = BKE_scene_base_find_by_name(scene, name);
+               BaseLegacy *base = BKE_scene_base_find_by_name(scene, name);
                if (base) {
                        return base->object;
                }
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
new file mode 100644 (file)
index 0000000..f374ebd
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ * ***** 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.
+ *
+ * Contributor(s): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/collection.c
+ *  \ingroup bke
+ */
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_iterator.h"
+#include "BLI_listbase.h"
+#include "BLT_translation.h"
+#include "BLI_string_utils.h"
+
+#include "BKE_collection.h"
+#include "BKE_layer.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+#include "DNA_ID.h"
+#include "DNA_layer_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+/**
+ * Add a collection to a collection ListBase and syncronize all render layers
+ * The ListBase is NULL when the collection is to be added to the master collection
+ */
+SceneCollection *BKE_collection_add(Scene *scene, SceneCollection *sc_parent, const char *name)
+{
+       SceneCollection *sc_master = BKE_collection_master(scene);
+       SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New Collection");
+
+       if (!name) {
+               name = DATA_("New Collection");
+       }
+
+       if (!sc_parent) {
+               sc_parent = sc_master;
+       }
+
+       BLI_strncpy(sc->name, name, sizeof(sc->name));
+       BLI_uniquename(&sc_master->scene_collections, sc, DATA_("Collection"), '.', offsetof(SceneCollection, name), sizeof(sc->name));
+
+       BLI_addtail(&sc_parent->scene_collections, sc);
+
+       BKE_layer_sync_new_scene_collection(scene, sc_parent, sc);
+       return sc;
+}
+
+/**
+ * Free the collection items recursively
+ */
+static void collection_free(SceneCollection *sc)
+{
+       for (LinkData *link = sc->objects.first; link; link = link->next) {
+               id_us_min(link->data);
+       }
+       BLI_freelistN(&sc->objects);
+
+       for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
+               id_us_min(link->data);
+       }
+       BLI_freelistN(&sc->filter_objects);
+
+       for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+               collection_free(nsc);
+       }
+       BLI_freelistN(&sc->scene_collections);
+}
+
+/**
+ * Unlink the collection recursively
+ * return true if unlinked
+ */
+static bool collection_remlink(SceneCollection *sc_parent, SceneCollection *sc_gone)
+{
+       for (SceneCollection *sc = sc_parent->scene_collections.first; sc; sc = sc->next)
+       {
+               if (sc == sc_gone) {
+                       BLI_remlink(&sc_parent->scene_collections, sc_gone);
+                       return true;
+               }
+
+               if (collection_remlink(sc, sc_gone)) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+/**
+ * Recursively remove any instance of this SceneCollection
+ */
+static void layer_collection_remove(SceneLayer *sl, ListBase *lb, const SceneCollection *sc)
+{
+       LayerCollection *lc = lb->first;
+       while(lc) {
+               if (lc->scene_collection == sc) {
+                       BKE_layer_collection_free(sl, lc);
+                       BLI_remlink(lb, lc);
+
+                       LayerCollection *lc_next = lc->next;
+                       MEM_freeN(lc);
+                       lc = lc_next;
+
+                       /* only the "top-level" layer collections may have the
+                        * same SceneCollection in a sibling tree.
+                        */
+                       if (lb != &sl->layer_collections) {
+                               return;
+                       }
+               }
+
+               else {
+                       layer_collection_remove(sl, &lc->layer_collections, sc);
+                       lc = lc->next;
+               }
+       }
+}
+
+/**
+ * Remove a collection from the scene, and syncronize all render layers
+ */
+bool BKE_collection_remove(Scene *scene, SceneCollection *sc)
+{
+       SceneCollection *sc_master = BKE_collection_master(scene);
+
+       /* the master collection cannot be removed */
+       if (sc == sc_master) {
+               return false;
+       }
+
+       /* unlink from the respective collection tree */
+       if (!collection_remlink(sc_master, sc)) {
+               BLI_assert(false);
+       }
+
+       /* clear the collection items */
+       collection_free(sc);
+
+       /* check all layers that use this collection and clear them */
+       for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+               layer_collection_remove(sl, &sl->layer_collections, sc);
+               BKE_scene_layer_base_flag_recalculate(sl);
+               sl->active_collection = 0;
+       }
+
+       MEM_freeN(sc);
+       return true;
+}
+
+/**
+ * Returns the master collection
+ */
+SceneCollection *BKE_collection_master(Scene *scene)
+{
+       return scene->collection;
+}
+
+/**
+ * Free (or release) any data used by the master collection (does not free the master collection itself).
+ * Used only to clear the entire scene data since it's not doing re-syncing of the LayerCollection tree
+ */
+void BKE_collection_master_free(Scene *scene){
+       collection_free(BKE_collection_master(scene));
+}
+
+static void collection_object_add(Scene *scene, SceneCollection *sc, Object *ob)
+{
+       BLI_addtail(&sc->objects, BLI_genericNodeN(ob));
+       id_us_plus((ID *)ob);
+       BKE_layer_sync_object_link(scene, sc, ob);
+}
+
+/**
+ * Add object to collection
+ */
+void BKE_collection_object_add(Scene *scene, SceneCollection *sc, Object *ob)
+{
+       if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) {
+               /* don't add the same object twice */
+               return;
+       }
+       collection_object_add(scene, sc, ob);
+}
+
+/**
+ * Add object to all collections that reference objects is in
+ * (used to copy objects)
+ */
+void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst)
+{
+       SceneCollection *sc;
+       FOREACH_SCENE_COLLECTION(scene, sc)
+       {
+               if (BLI_findptr(&sc->objects, ob_src, offsetof(LinkData, data))) {
+                       collection_object_add(scene, sc, ob_dst);
+               }
+       }
+       FOREACH_SCENE_COLLECTION_END
+}
+
+/**
+ * Remove object from collection
+ */
+void BKE_collection_object_remove(Main *bmain, Scene *scene, SceneCollection *sc, Object *ob, const bool free_us)
+{
+
+       LinkData *link = BLI_findptr(&sc->objects, ob, offsetof(LinkData, data));
+
+       if (link == NULL) {
+               return;
+       }
+
+       BLI_remlink(&sc->objects, link);
+       MEM_freeN(link);
+
+       TODO_LAYER_SYNC_FILTER; /* need to remove all instances of ob in scene collections -> filter_objects */
+       BKE_layer_sync_object_unlink(scene, sc, ob);
+
+       if (free_us) {
+               BKE_libblock_free_us(bmain, ob);
+       }
+       else {
+               id_us_min(&ob->id);
+       }
+}
+
+/**
+ * Remove object from all collections of scene
+ */
+void BKE_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us)
+{
+       BKE_scene_remove_rigidbody_object(scene, ob);
+
+       SceneCollection *sc;
+       FOREACH_SCENE_COLLECTION(scene, sc)
+       {
+               BKE_collection_object_remove(bmain, scene, sc, ob, free_us);
+       }
+       FOREACH_SCENE_COLLECTION_END
+}
+
+/* ---------------------------------------------------------------------- */
+/* Iteractors */
+/* scene collection iteractor */
+
+typedef struct SceneCollectionsIteratorData {
+       Scene *scene;
+       void **array;
+       int tot, cur;
+ } SceneCollectionsIteratorData;
+
+static void scene_collection_callback(SceneCollection *sc, BKE_scene_collections_Cb callback, void *data)
+{
+       callback(sc, data);
+
+       for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+               scene_collection_callback(nsc, callback, data);
+       }
+}
+
+static void scene_collections_count(SceneCollection *UNUSED(sc), void *data)
+{
+       int *tot = data;
+       (*tot)++;
+}
+
+static void scene_collections_build_array(SceneCollection *sc, void *data)
+{
+       SceneCollection ***array = data;
+       **array = sc;
+       (*array)++;
+}
+
+static void scene_collections_array(Scene *scene, SceneCollection ***collections_array, int *tot)
+{
+       SceneCollection *sc = BKE_collection_master(scene);
+       SceneCollection **array;
+
+       *collections_array = NULL;
+       *tot = 0;
+
+       if (scene == NULL)
+               return;
+
+       scene_collection_callback(sc, scene_collections_count, tot);
+
+       if (*tot == 0)
+               return;
+
+       *collections_array = array = MEM_mallocN(sizeof(SceneCollection *) * (*tot), "SceneCollectionArray");
+       scene_collection_callback(sc, scene_collections_build_array, &array);
+}
+
+/**
+ * Only use this in non-performance critical situations
+ * (it iterates over all scene collections twice)
+ */
+void BKE_scene_collections_Iterator_begin(Iterator *iter, void *data_in)
+{
+       Scene *scene = data_in;
+       SceneCollectionsIteratorData *data = MEM_callocN(sizeof(SceneCollectionsIteratorData), __FUNCTION__);
+
+       data->scene = scene;
+       iter->data = data;
+
+       scene_collections_array(scene, (SceneCollection ***)&data->array, &data->tot);
+       BLI_assert(data->tot != 0);
+
+       data->cur = 0;
+       iter->current = data->array[data->cur];
+       iter->valid = true;
+}
+
+void BKE_scene_collections_Iterator_next(struct Iterator *iter)
+{
+       SceneCollectionsIteratorData *data = iter->data;
+
+       if (++data->cur < data->tot) {
+               iter->current = data->array[data->cur];
+       }
+       else {
+               iter->valid = false;
+       }
+}
+
+void BKE_scene_collections_Iterator_end(struct Iterator *iter)
+{
+       SceneCollectionsIteratorData *data = iter->data;
+
+       if (data) {
+               if (data->array) {
+                       MEM_freeN(data->array);
+               }
+               MEM_freeN(data);
+       }
+       iter->valid = false;
+}
+
+
+/* scene objects iteractor */
+
+typedef struct SceneObjectsIteratorData {
+       GSet *visited;
+       LinkData *link;
+       Iterator scene_collection_iter;
+} SceneObjectsIteratorData;
+
+void BKE_scene_objects_Iterator_begin(Iterator *iter, void *data_in)
+{
+       Scene *scene = data_in;
+       SceneObjectsIteratorData *data = MEM_callocN(sizeof(SceneObjectsIteratorData), __FUNCTION__);
+       iter->data = data;
+
+       /* lookup list ot make sure each object is object called once */
+       data->visited = BLI_gset_ptr_new(__func__);
+
+       /* we wrap the scenecollection iterator here to go over the scene collections */
+       BKE_scene_collections_Iterator_begin(&data->scene_collection_iter, scene);
+
+       SceneCollection *sc = data->scene_collection_iter.current;
+       iter->current = sc->objects.first;
+
+       if (iter->current == NULL) {
+               BKE_scene_objects_Iterator_next(iter);
+       }
+}
+
+/**
+ * Gets the next unique object
+ */
+static LinkData *object_base_next(GSet *gs, LinkData *link)
+{
+       if (link == NULL) {
+               return NULL;
+       }
+
+       LinkData *link_next = link->next;
+       if (link_next) {
+               Object *ob = link_next->data;
+               if (!BLI_gset_haskey(gs, ob)) {
+                       BLI_gset_add(gs, ob);
+                       return link_next;
+               }
+               else {
+                       return object_base_next(gs, link_next);
+               }
+       }
+       return NULL;
+}
+
+void BKE_scene_objects_Iterator_next(Iterator *iter)
+{
+       SceneObjectsIteratorData *data = iter->data;
+       LinkData *link = object_base_next(data->visited, data->link);
+
+       if (link) {
+               data->link = link;
+               iter->current = link->data;
+       }
+       else {
+               /* if this is the last object of this ListBase look at the next SceneCollection */
+               SceneCollection *sc;
+               BKE_scene_collections_Iterator_next(&data->scene_collection_iter);
+               do {
+                       sc = data->scene_collection_iter.current;
+                       /* get the first unique object of this collection */
+                       LinkData *new_link = object_base_next(data->visited, sc->objects.first);
+                       if (new_link) {
+                               data->link = new_link;
+                               iter->current = data->link->data;
+                               return;
+                       }
+                       BKE_scene_collections_Iterator_next(&data->scene_collection_iter);
+               } while (data->scene_collection_iter.valid);
+
+               if (!data->scene_collection_iter.valid) {
+                       iter->valid = false;
+               }
+       }
+}
+
+void BKE_scene_objects_Iterator_end(Iterator *iter)
+{
+       SceneObjectsIteratorData *data = iter->data;
+       if (data) {
+               BKE_scene_collections_Iterator_end(&data->scene_collection_iter);
+               BLI_gset_free(data->visited, NULL);
+               MEM_freeN(data);
+       }
+}
index ee25be368555533097de01492c034b3a5dbb916b..b5f76240c0b672b9450e095e30c0b8da16de4f85 100644 (file)
@@ -514,7 +514,7 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned
 // collision object will exclude self 
 Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli)
 {
-       Base *base;
+       BaseLegacy *base;
        Object **objs;
        GroupObject *go;
        unsigned int numobj= 0, maxobj= 100;
@@ -596,7 +596,7 @@ ListBase *get_collider_cache(Scene *scene, Object *self, Group *group)
        }
        else {
                Scene *sce_iter;
-               Base *base;
+               BaseLegacy *base;
 
                /* add objects in same layer in scene */
                for (SETLOOPER(scene, sce_iter, base)) {
index 4c01bfd35f21cefac047c8c5f0e50a4348610ef9..1cbf8cf01c80f5c665f34b8dd0e120abb1f721e7 100644 (file)
@@ -47,6 +47,7 @@
 #include "BLT_translation.h"
 
 #include "BKE_context.h"
+#include "BKE_layer.h"
 #include "BKE_main.h"
 #include "BKE_screen.h"
 #include "BKE_sound.h"
@@ -814,6 +815,14 @@ struct SpaceClip *CTX_wm_space_clip(const bContext *C)
        return NULL;
 }
 
+struct SpaceCollections *CTX_wm_space_collections(const bContext *C)
+{
+       ScrArea *sa = CTX_wm_area(C);
+       if (sa && sa->spacetype == SPACE_COLLECTIONS)
+               return sa->spacedata.first;
+       return NULL;
+}
+
 void CTX_wm_manager_set(bContext *C, wmWindowManager *wm)
 {
        C->wm.manager = wm;
@@ -836,8 +845,9 @@ void CTX_wm_window_set(bContext *C, wmWindow *win)
 void CTX_wm_screen_set(bContext *C, bScreen *screen)
 {
        C->wm.screen = screen;
-       if (C->wm.screen)
-               C->data.scene = C->wm.screen->scene;
+       if (C->wm.screen) {
+               CTX_data_scene_set(C, C->wm.screen->scene);
+       }
        C->wm.area = NULL;
        C->wm.region = NULL;
 }
@@ -896,6 +906,62 @@ Scene *CTX_data_scene(const bContext *C)
                return C->data.scene;
 }
 
+SceneLayer *CTX_data_scene_layer(const bContext *C)
+{
+       SceneLayer *sl;
+
+       if (ctx_data_pointer_verify(C, "render_layer", (void *)&sl)) {
+               return sl;
+       }
+       else {
+               Scene *scene = CTX_data_scene(C);
+               sl = BLI_findlink(&scene->render_layers, scene->active_layer);
+               BLI_assert(sl);
+               return sl;
+       }
+}
+
+/**
+ * This is tricky. Sometimes the user overrides the render_layer
+ * but not the scene_collection. In this case what to do?
+ *
+ * If the scene_collection is linked to the SceneLayer we use it.
+ * Otherwise we fallback to the active one of the SceneLayer.
+ */
+LayerCollection *CTX_data_layer_collection(const bContext *C)
+{
+       SceneLayer *sl = CTX_data_scene_layer(C);
+       LayerCollection *lc;
+
+       if (ctx_data_pointer_verify(C, "layer_collection", (void *)&lc)) {
+               if (BKE_scene_layer_has_collection(sl, lc->scene_collection)) {
+                       return lc;
+               }
+       }
+
+       /* fallback */
+       return BKE_layer_collection_active(sl);
+}
+
+SceneCollection *CTX_data_scene_collection(const bContext *C)
+{
+       SceneCollection *sc;
+       if (ctx_data_pointer_verify(C, "scene_collection", (void *)&sc)) {
+               if (BKE_scene_layer_has_collection(CTX_data_scene_layer(C), sc)) {
+                       return sc;
+               }
+       }
+
+       LayerCollection *lc = CTX_data_layer_collection(C);
+       if (lc) {
+               return lc->scene_collection;
+       }
+
+       /* fallback */
+       Scene *scene = CTX_data_scene(C);
+       return BKE_collection_master(scene);
+}
+
 int CTX_data_mode_enum(const bContext *C)
 {
        Object *obedit = CTX_data_edit_object(C);
index bc9871aee54abffb8d7a538f223571fac119d7eb..39d06a13e6ea8a9e8a14d073899be332b897d562 100644 (file)
@@ -488,7 +488,7 @@ static void scene_setSubframe(Scene *scene, float subframe)
 
 static int surface_getBrushFlags(DynamicPaintSurface *surface, const Scene *scene)
 {
-       Base *base = NULL;
+       BaseLegacy *base = NULL;
        GroupObject *go = NULL;
        Object *brushObj = NULL;
        ModifierData *md = NULL;
@@ -5780,7 +5780,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
         * Loop through surface's target paint objects and do painting
         */
        {
-               Base *base = NULL;
+               BaseLegacy *base = NULL;
                GroupObject *go = NULL;
                Object *brushObj = NULL;
                ModifierData *md = NULL;
index fe8f5ebdca6b96e7269f4d250ae19252ddd1c619..668d4d6c9e236c34e32ba1ce7f864cbf3114f185 100644 (file)
@@ -209,7 +209,7 @@ static void add_particles_to_effectors(ListBase **effectors, Scene *scene, Effec
 ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src,
                           EffectorWeights *weights, bool for_simulation)
 {
-       Base *base;
+       BaseLegacy *base;
        unsigned int layer= ob_src->lay;
        ListBase *effectors = NULL;
        
index 9b011dbb003c537c380e9c74ecf19b596367eb14..9c81a8b49bee7d7b910164132870fbe122058545 100644 (file)
@@ -130,18 +130,11 @@ static bool group_object_add_internal(Group *group, Object *ob)
        return true;
 }
 
-bool BKE_group_object_add(Group *group, Object *object, Scene *scene, Base *base)
+bool BKE_group_object_add(Group *group, Object *object)
 {
        if (group_object_add_internal(group, object)) {
                if ((object->flag & OB_FROMGROUP) == 0) {
-
-                       if (scene && base == NULL)
-                               base = BKE_scene_base_find(scene, object);
-
                        object->flag |= OB_FROMGROUP;
-
-                       if (base)
-                               base->flag |= OB_FROMGROUP;
                }
                return true;
        }
@@ -208,18 +201,12 @@ bool BKE_group_object_cyclic_check(Main *bmain, Object *object, Group *group)
        return group_object_cyclic_check_internal(object, group);
 }
 
-bool BKE_group_object_unlink(Group *group, Object *object, Scene *scene, Base *base)
+bool BKE_group_object_unlink(Group *group, Object *object)
 {
        if (group_object_unlink_internal(group, object)) {
                /* object can be NULL */
                if (object && BKE_group_object_find(NULL, object) == NULL) {
-                       if (scene && base == NULL)
-                               base = BKE_scene_base_find(scene, object);
-
                        object->flag &= ~OB_FROMGROUP;
-
-                       if (base)
-                               base->flag &= ~OB_FROMGROUP;
                }
                return true;
        }
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
new file mode 100644 (file)
index 0000000..cec1d70
--- /dev/null
@@ -0,0 +1,684 @@
+/*
+ * ***** 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.
+ *
+ * Contributor(s): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/layer.c
+ *  \ingroup bke
+ */
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_string_utf8.h"
+#include "BLI_string_utils.h"
+#include "BLT_translation.h"
+
+#include "BKE_layer.h"
+#include "BKE_collection.h"
+#include "BKE_layer.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+
+#include "DNA_ID.h"
+#include "DNA_layer_types.h"
+#include "DNA_object_types.h"
+#include "DNA_node_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+/* prototype */
+static void layer_collection_free(SceneLayer *sl, LayerCollection *lc);
+static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc);
+static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc);
+static void object_bases_Iterator_next(Iterator *iter, const int flag);
+
+/* RenderLayer */
+
+/**
+ * Add a new renderlayer
+ * by default, a renderlayer has the master collection
+ */
+SceneLayer *BKE_scene_layer_add(Scene *scene, const char *name)
+{
+       if (!name) {
+               name = DATA_("Render Layer");
+       }
+
+       SceneLayer *sl = MEM_callocN(sizeof(SceneLayer), "Scene Layer");
+       sl->flag |= SCENE_LAYER_RENDER;
+
+       BLI_addtail(&scene->render_layers, sl);
+
+       /* unique name */
+       BLI_strncpy_utf8(sl->name, name, sizeof(sl->name));
+       BLI_uniquename(&scene->render_layers, sl, DATA_("SceneLayer"), '.', offsetof(SceneLayer, name), sizeof(sl->name));
+
+       SceneCollection *sc = BKE_collection_master(scene);
+       layer_collection_add(sl, &sl->layer_collections, sc);
+
+       return sl;
+}
+
+bool BKE_scene_layer_remove(Main *bmain, Scene *scene, SceneLayer *sl)
+{
+       const int act = BLI_findindex(&scene->render_layers, sl);
+
+       if (act == -1) {
+               return false;
+       }
+       else if ( (scene->render_layers.first == scene->render_layers.last) &&
+                 (scene->render_layers.first == sl))
+       {
+               /* ensure 1 layer is kept */
+               return false;
+       }
+
+       BLI_remlink(&scene->render_layers, sl);
+
+       BKE_scene_layer_free(sl);
+       MEM_freeN(sl);
+
+       scene->active_layer = 0;
+       /* TODO WORKSPACE: set active_layer to 0 */
+
+       for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
+               if (sce->nodetree) {
+                       BKE_nodetree_remove_layer_n(sce->nodetree, scene, act);
+               }
+       }
+
+       return true;
+}
+
+/**
+ * Free (or release) any data used by this SceneLayer (does not free the SceneLayer itself).
+ */
+void BKE_scene_layer_free(SceneLayer *sl)
+{
+       sl->basact = NULL;
+       BLI_freelistN(&sl->object_bases);
+
+       for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+               layer_collection_free(NULL, lc);
+       }
+       BLI_freelistN(&sl->layer_collections);
+}
+
+/**
+ * Set the render engine of a renderlayer
+ */
+void BKE_scene_layer_engine_set(SceneLayer *sl, const char *engine)
+{
+       BLI_strncpy_utf8(sl->engine, engine, sizeof(sl->engine));
+}
+
+/**
+ * Tag all the selected objects of a renderlayer
+ */
+void BKE_scene_layer_selected_objects_tag(SceneLayer *sl, const int tag)
+{
+       for (Base *base = sl->object_bases.first; base; base = base->next) {
+               if ((base->flag & BASE_SELECTED) != 0) {
+                       base->object->flag |= tag;
+               }
+               else {
+                       base->object->flag &= ~tag;
+               }
+       }
+}
+
+static bool find_scene_collection_in_scene_collections(ListBase *lb, const LayerCollection *lc)
+{
+       for (LayerCollection *lcn = lb->first; lcn; lcn = lcn->next) {
+               if (lcn == lc) {
+                       return true;
+               }
+               if (find_scene_collection_in_scene_collections(&lcn->layer_collections, lc)) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+/**
+ * Find the SceneLayer a LayerCollection belongs to
+ */
+SceneLayer *BKE_scene_layer_find_from_collection(Scene *scene, LayerCollection *lc)
+{
+       for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+               if (find_scene_collection_in_scene_collections(&sl->layer_collections, lc)) {
+                       return sl;
+               }
+       }
+       return NULL;
+}
+
+/* Base */
+
+Base *BKE_scene_layer_base_find(SceneLayer *sl, Object *ob)
+{
+       return BLI_findptr(&sl->object_bases, ob, offsetof(Base, object));
+}
+
+void BKE_scene_layer_base_deselect_all(SceneLayer *sl)
+{
+       Base *base;
+
+       for (base = sl->object_bases.first; base; base = base->next) {
+               base->flag &= ~BASE_SELECTED;
+       }
+}
+
+void BKE_scene_layer_base_select(struct SceneLayer *sl, Base *selbase)
+{
+       sl->basact = selbase;
+       if ((selbase->flag & BASE_SELECTABLED) != 0) {
+               selbase->flag |= BASE_SELECTED;
+       }
+}
+
+static void scene_layer_object_base_unref(SceneLayer* sl, Base *base)
+{
+       base->refcount--;
+
+       /* It only exists in the RenderLayer */
+       if (base->refcount == 0) {
+               if (sl->basact == base) {
+                       sl->basact = NULL;
+               }
+
+               BLI_remlink(&sl->object_bases, base);
+               MEM_freeN(base);
+       }
+}
+
+static void layer_collection_base_flag_recalculate(LayerCollection *lc, const bool tree_is_visible, const bool tree_is_selectable)
+{
+       bool is_visible = tree_is_visible && ((lc->flag & COLLECTION_VISIBLE) != 0);
+       /* an object can only be selected if it's visible */
+       bool is_selectable = tree_is_selectable && is_visible && ((lc->flag & COLLECTION_SELECTABLE) != 0);
+
+       for (LinkData *link = lc->object_bases.first; link; link = link->next) {
+               Base *base = link->data;
+
+               if (is_visible) {
+                       base->flag |= BASE_VISIBLED;
+               }
+               else {
+                       base->flag &= ~BASE_VISIBLED;
+               }
+
+               if (is_selectable) {
+                       base->flag |= BASE_SELECTABLED;
+               }
+               else {
+                       base->flag &= ~BASE_SELECTABLED;
+               }
+       }
+
+       for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
+               layer_collection_base_flag_recalculate(lcn, is_visible, is_selectable);
+       }
+}
+
+/**
+ * Re-evaluate the ObjectBase flags for SceneLayer
+ */
+void BKE_scene_layer_base_flag_recalculate(SceneLayer *sl)
+{
+       for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+               layer_collection_base_flag_recalculate(lc, true, true);
+       }
+
+       /* if base is not selectabled, clear select */
+       for (Base *base = sl->object_bases.first; base; base = base->next) {
+               if ((base->flag & BASE_SELECTABLED) == 0) {
+                       base->flag &= ~BASE_SELECTED;
+               }
+       }
+}
+
+/**
+ * Return the base if existent, or create it if necessary
+ * Always bump the refcount
+ */
+static Base *object_base_add(SceneLayer *sl, Object *ob)
+{
+       Base *base;
+       base = BKE_scene_layer_base_find(sl, ob);
+
+       if (base == NULL) {
+               base = MEM_callocN(sizeof(Base), "Object Base");
+
+               /* do not bump user count, leave it for SceneCollections */
+               base->object = ob;
+               BLI_addtail(&sl->object_bases, base);
+       }
+       base->refcount++;
+       return base;
+}
+
+/* LayerCollection */
+
+/**
+ * When freeing the entire SceneLayer at once we don't bother with unref
+ * otherwise SceneLayer is passed to keep the syncing of the LayerCollection tree
+ */
+static void layer_collection_free(SceneLayer *sl, LayerCollection *lc)
+{
+       if (sl) {
+               for (LinkData *link = lc->object_bases.first; link; link = link->next) {
+                       scene_layer_object_base_unref(sl, link->data);
+               }
+       }
+
+       BLI_freelistN(&lc->object_bases);
+       BLI_freelistN(&lc->overrides);
+
+       for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+               layer_collection_free(sl, nlc);
+       }
+       BLI_freelistN(&lc->layer_collections);
+}
+
+/**
+ * Free (or release) LayerCollection from SceneLayer
+ * (does not free the LayerCollection itself).
+ */
+void BKE_layer_collection_free(SceneLayer *sl, LayerCollection *lc)
+{
+       layer_collection_free(sl, lc);
+}
+
+/* LayerCollection */
+
+/**
+ * Recursively get the collection for a given index
+ */
+static LayerCollection *collection_from_index(ListBase *lb, const int number, int *i)
+{
+       for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+               if (*i == number) {
+                       return lc;
+               }
+
+               (*i)++;
+
+               LayerCollection *lc_nested = collection_from_index(&lc->layer_collections, number, i);
+               if (lc_nested) {
+                       return lc_nested;
+               }
+       }
+       return NULL;
+}
+
+/**
+ * Get the active collection
+ */
+LayerCollection *BKE_layer_collection_active(SceneLayer *sl)
+{
+       int i = 0;
+       return collection_from_index(&sl->layer_collections, sl->active_collection, &i);
+}
+
+/**
+ * Recursively get the count of collections
+ */
+static int collection_count(ListBase *lb)
+{
+       int i = 0;
+       for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+               i += collection_count(&lc->layer_collections) + 1;
+       }
+       return i;
+}
+
+/**
+ * Get the total number of collections
+ * (including all the nested collections)
+ */
+int BKE_layer_collection_count(SceneLayer *sl)
+{
+       return collection_count(&sl->layer_collections);
+}
+
+/**
+ * Recursively get the index for a given collection
+ */
+static int index_from_collection(ListBase *lb, LayerCollection *lc, int *i)
+{
+       for (LayerCollection *lcol = lb->first; lcol; lcol = lcol->next) {
+               if (lcol == lc) {
+                       return *i;
+               }
+
+               (*i)++;
+
+               int i_nested = index_from_collection(&lcol->layer_collections, lc, i);
+               if (i_nested != -1) {
+                       return i_nested;
+               }
+       }
+       return -1;
+}
+
+/**
+ * Return -1 if not found
+ */
+int BKE_layer_collection_findindex(SceneLayer *sl, LayerCollection *lc)
+{
+       int i = 0;
+       return index_from_collection(&sl->layer_collections, lc, &i);
+}
+
+/**
+ * Link a collection to a renderlayer
+ * The collection needs to be created separately
+ */
+LayerCollection *BKE_collection_link(SceneLayer *sl, SceneCollection *sc)
+{
+       LayerCollection *lc = layer_collection_add(sl, &sl->layer_collections, sc);
+       sl->active_collection = BKE_layer_collection_findindex(sl, lc);
+       return lc;
+}
+
+/**
+ * Unlink a collection base from a renderlayer
+ * The corresponding collection is not removed from the master collection
+ */
+void BKE_collection_unlink(SceneLayer *sl, LayerCollection *lc)
+{
+       BKE_layer_collection_free(sl, lc);
+       BKE_scene_layer_base_flag_recalculate(sl);
+
+       BLI_remlink(&sl->layer_collections, lc);
+       MEM_freeN(lc);
+       sl->active_collection = 0;
+}
+
+static void layer_collection_object_add(SceneLayer *sl, LayerCollection *lc, Object *ob)
+{
+       Base *base = object_base_add(sl, ob);
+
+       /* only add an object once - prevent SceneCollection->objects and
+        * SceneCollection->filter_objects to add the same object */
+
+       if (BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data))) {
+               return;
+       }
+
+       BLI_addtail(&lc->object_bases, BLI_genericNodeN(base));
+
+       BKE_scene_layer_base_flag_recalculate(sl);
+}
+
+static void layer_collection_object_remove(SceneLayer *sl, LayerCollection *lc, Object *ob)
+{
+       Base *base;
+       base = BKE_scene_layer_base_find(sl, ob);
+
+       LinkData *link = BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data));
+       BLI_remlink(&lc->object_bases, link);
+       MEM_freeN(link);
+
+       scene_layer_object_base_unref(sl, base);
+}
+
+static void layer_collection_objects_populate(SceneLayer *sl, LayerCollection *lc, ListBase *objects)
+{
+       for (LinkData *link = objects->first; link; link = link->next) {
+               layer_collection_object_add(sl, lc, link->data);
+       }
+}
+
+static void layer_collection_populate(SceneLayer *sl, LayerCollection *lc, SceneCollection *sc)
+{
+       layer_collection_objects_populate(sl, lc, &sc->objects);
+       layer_collection_objects_populate(sl, lc, &sc->filter_objects);
+
+       for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+               layer_collection_add(sl, &lc->layer_collections, nsc);
+       }
+}
+
+static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc)
+{
+       LayerCollection *lc = MEM_callocN(sizeof(LayerCollection), "Collection Base");
+       BLI_addtail(lb, lc);
+
+       lc->scene_collection = sc;
+       lc->flag = COLLECTION_VISIBLE + COLLECTION_SELECTABLE + COLLECTION_FOLDED;
+
+       layer_collection_populate(sl, lc, sc);
+       return lc;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+/**
+ * See if render layer has the scene collection linked directly, or indirectly (nested)
+ */
+bool BKE_scene_layer_has_collection(struct SceneLayer *sl, struct SceneCollection *sc)
+{
+       for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+               if (find_layer_collection_by_scene_collection(lc, sc) != NULL) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+/**
+ * See if the object is in any of the scene layers of the scene
+ */
+bool BKE_scene_has_object(Scene *scene, Object *ob)
+{
+       for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+               Base *base = BKE_scene_layer_base_find(sl, ob);
+               if (base) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* Syncing */
+
+static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc)
+{
+       if (lc->scene_collection == sc) {
+               return lc;
+       }
+
+       for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+               LayerCollection *found = find_layer_collection_by_scene_collection(nlc, sc);
+               if (found) {
+                       return found;
+               }
+       }
+       return NULL;
+}
+
+/**
+ * Add a new LayerCollection for all the SceneLayers that have sc_parent
+ */
+void BKE_layer_sync_new_scene_collection(Scene *scene, const SceneCollection *sc_parent, SceneCollection *sc)
+{
+       for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+               for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+                       LayerCollection *lc_parent = find_layer_collection_by_scene_collection(lc, sc_parent);
+                       if (lc_parent) {
+                               layer_collection_add(sl, &lc_parent->layer_collections, sc);
+                       }
+               }
+       }
+}
+
+/**
+ * Add a corresponding ObjectBase to all the equivalent LayerCollection
+ */
+void BKE_layer_sync_object_link(Scene *scene, SceneCollection *sc, Object *ob)
+{
+       for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+               for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+                       LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc);
+                       if (found) {
+                               layer_collection_object_add(sl, found, ob);
+                       }
+               }
+       }
+}
+
+/**
+ * Remove the equivalent object base to all layers that have this collection
+ * also remove all reference to ob in the filter_objects
+ */
+void BKE_layer_sync_object_unlink(Scene *scene, SceneCollection *sc, Object *ob)
+{
+       for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+               for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+                       LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc);
+                       if (found) {
+                               layer_collection_object_remove(sl, found, ob);
+                       }
+               }
+               BKE_scene_layer_base_flag_recalculate(sl);
+       }
+}
+
+/* ---------------------------------------------------------------------- */
+/* Override */
+
+/**
+ * Add a new datablock override
+ */
+void BKE_collection_override_datablock_add(LayerCollection *UNUSED(lc), const char *UNUSED(data_path), ID *UNUSED(id))
+{
+       TODO_LAYER_OVERRIDE;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Iterators */
+
+static void object_bases_Iterator_begin(Iterator *iter, void *data_in, const int flag)
+{
+       SceneLayer *sl = data_in;
+       Base *base = sl->object_bases.first;
+
+       /* when there are no objects */
+       if (base ==  NULL) {
+               iter->valid = false;
+               return;
+       }
+
+       iter->valid = true;
+       iter->data = base;
+
+       if ((base->flag & flag) == 0) {
+               object_bases_Iterator_next(iter, flag);
+       }
+       else {
+               iter->current = base;
+       }
+}
+
+static void object_bases_Iterator_next(Iterator *iter, const int flag)
+{
+       Base *base = ((Base *)iter->data)->next;
+
+       while (base) {
+               if ((base->flag & flag) != 0) {
+                       iter->current = base;
+                       iter->data = base;
+                       return;
+               }
+               base = base->next;
+       }
+
+       iter->current = NULL;
+       iter->valid = false;
+}
+
+static void objects_Iterator_begin(Iterator *iter, void *data_in, const int flag)
+{
+       object_bases_Iterator_begin(iter, data_in, flag);
+
+       if (iter->valid) {
+               iter->current = ((Base *)iter->current)->object;
+       }
+}
+
+static void objects_Iterator_next(Iterator *iter, const int flag)
+{
+       object_bases_Iterator_next(iter, flag);
+
+       if (iter->valid) {
+               iter->current = ((Base *)iter->current)->object;
+       }
+}
+
+void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in)
+{
+       objects_Iterator_begin(iter, data_in, BASE_SELECTED);
+}
+
+void BKE_selected_objects_Iterator_next(Iterator *iter)
+{
+       objects_Iterator_next(iter, BASE_SELECTED);
+}
+
+void BKE_selected_objects_Iterator_end(Iterator *UNUSED(iter))
+{
+       /* do nothing */
+}
+
+void BKE_visible_objects_Iterator_begin(Iterator *iter, void *data_in)
+{
+       objects_Iterator_begin(iter, data_in, BASE_VISIBLED);
+}
+
+void BKE_visible_objects_Iterator_next(Iterator *iter)
+{
+       objects_Iterator_next(iter, BASE_VISIBLED);
+}
+
+void BKE_visible_objects_Iterator_end(Iterator *UNUSED(iter))
+{
+       /* do nothing */
+}
+
+void BKE_visible_bases_Iterator_begin(Iterator *iter, void *data_in)
+{
+       object_bases_Iterator_begin(iter, data_in, BASE_VISIBLED);
+}
+
+void BKE_visible_bases_Iterator_next(Iterator *iter)
+{
+       object_bases_Iterator_next(iter, BASE_VISIBLED);
+}
+
+void BKE_visible_bases_Iterator_end(Iterator *UNUSED(iter))
+{
+       /* do nothing */
+}
index 9685f1f5af6b04dcda279cade6d18a1d7fbd7662..a071b3202be1a37069afbd8c4da5e3e191a14b8b 100644 (file)
@@ -68,6 +68,7 @@
 #include "BLI_linklist_stack.h"
 
 #include "BKE_animsys.h"
+#include "BKE_collection.h"
 #include "BKE_constraint.h"
 #include "BKE_fcurve.h"
 #include "BKE_library.h"
@@ -354,7 +355,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
                                Scene *scene = (Scene *) id;
                                ToolSettings *toolsett = scene->toolsettings;
                                SceneRenderLayer *srl;
-                               Base *base;
+                               BaseLegacy *legacy_base;
 
                                CALLBACK_INVOKE(scene->camera, IDWALK_CB_NOP);
                                CALLBACK_INVOKE(scene->world, IDWALK_CB_USER);
@@ -411,8 +412,28 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
 
                                CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER);
 
-                               for (base = scene->base.first; base; base = base->next) {
-                                       CALLBACK_INVOKE(base->object, IDWALK_CB_USER);
+                               for (legacy_base = scene->base.first; legacy_base; legacy_base = legacy_base->next) {
+                                       CALLBACK_INVOKE(legacy_base->object, IDWALK_CB_USER);
+                               }
+
+                               SceneCollection *sc;
+                               FOREACH_SCENE_COLLECTION(scene, sc)
+                               {
+                                       for (LinkData *link = sc->objects.first; link; link = link->next) {
+                                               CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER);
+                                       }
+
+                                       for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
+                                               CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER);
+                                       }
+                               }
+                               FOREACH_SCENE_COLLECTION_END
+
+                               SceneLayer *sl;
+                               for (sl = scene->render_layers.first; sl; sl = sl->next) {
+                                       for (Base *base = sl->object_bases.first; base; base = base->next) {
+                                               CALLBACK_INVOKE(base->object, IDWALK_NOP);
+                                       }
                                }
 
                                for (TimeMarker *marker = scene->markers.first; marker; marker = marker->next) {
index a408b498f184cafb61b8132e71249c552b226172..9946d1cc81f130807631fcff8d18a5e190583e2f 100644 (file)
@@ -71,6 +71,7 @@
 #include "BKE_brush.h"
 #include "BKE_camera.h"
 #include "BKE_cachefile.h"
+#include "BKE_collection.h"
 #include "BKE_curve.h"
 #include "BKE_depsgraph.h"
 #include "BKE_fcurve.h"
@@ -242,7 +243,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
 
 /* Some reamapping unfortunately require extra and/or specific handling, tackle those here. */
 static void libblock_remap_data_preprocess_scene_base_unlink(
-        IDRemap *r_id_remap_data, Scene *sce, Base *base, const bool skip_indirect, const bool is_indirect)
+        IDRemap *r_id_remap_data, Scene *sce, BaseLegacy *base, const bool skip_indirect, const bool is_indirect)
 {
        if (skip_indirect && is_indirect) {
                r_id_remap_data->skipped_indirect++;
@@ -258,6 +259,22 @@ static void libblock_remap_data_preprocess_scene_base_unlink(
        }
 }
 
+/* Some remapping unfortunately require extra and/or specific handling, tackle those here. */
+static void libblock_remap_data_preprocess_scene_object_unlink(
+        IDRemap *r_id_remap_data, Scene *sce, Object *ob, const bool skip_indirect, const bool is_indirect)
+{
+       if (skip_indirect && is_indirect) {
+               r_id_remap_data->skipped_indirect++;
+               r_id_remap_data->skipped_refcounted++;
+       }
+       else {
+               BKE_collections_object_remove(r_id_remap_data->bmain, sce, ob, false);
+               if (!is_indirect) {
+                       r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
+               }
+       }
+}
+
 static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
 {
        switch (GS(r_id_remap_data->id->name)) {
@@ -272,7 +289,16 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
                                /* In case we are unlinking... */
                                if (!r_id_remap_data->old_id) {
                                        /* ... everything from scene. */
-                                       Base *base, *base_next;
+                                       Object *ob_iter;
+                                       FOREACH_SCENE_OBJECT(sce, ob_iter)
+                                       {
+                                               libblock_remap_data_preprocess_scene_object_unlink(
+                                                           r_id_remap_data, sce, ob_iter, skip_indirect, is_indirect);
+                                       }
+                                       FOREACH_SCENE_OBJECT_END
+
+
+                                       BaseLegacy *base, *base_next;
                                        for (base = sce->base.first; base; base = base_next) {
                                                base_next = base->next;
                                                libblock_remap_data_preprocess_scene_base_unlink(
@@ -282,8 +308,11 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
                                else if (GS(r_id_remap_data->old_id->name) == ID_OB) {
                                        /* ... a specific object from scene. */
                                        Object *old_ob = (Object *)r_id_remap_data->old_id;
-                                       Base *base = BKE_scene_base_find(sce, old_ob);
 
+                                       libblock_remap_data_preprocess_scene_object_unlink(
+                                                   r_id_remap_data, sce, old_ob, skip_indirect, is_indirect);
+
+                                       BaseLegacy *base = BKE_scene_base_find(sce, old_ob);
                                        if (base) {
                                                libblock_remap_data_preprocess_scene_base_unlink(
                                                            r_id_remap_data, sce, base, skip_indirect, is_indirect);
@@ -329,7 +358,7 @@ static void libblock_remap_data_postprocess_object_fromgroup_update(Main *bmain,
                }
                if (new_ob == NULL) {  /* We need to remove NULL-ified groupobjects... */
                        for (Group *group = bmain->group.first; group; group = group->id.next) {
-                               BKE_group_object_unlink(group, NULL, NULL, NULL);
+                               BKE_group_object_unlink(group, NULL);
                        }
                }
                else {
@@ -342,23 +371,17 @@ static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmai
 {
        /* Note that here we assume no object has no base (i.e. all objects are assumed instanced
         * in one scene...). */
-       for (Base *base = sce->base.first; base; base = base->next) {
-               if (base->flag & OB_FROMGROUP) {
-                       Object *ob = base->object;
-
-                       if (ob->flag & OB_FROMGROUP) {
-                               Group *grp = BKE_group_object_find(NULL, ob);
-
-                               /* Unlinked group (old_id) is still in bmain... */
-                               if (grp && (&grp->id == old_id || grp->id.us == 0)) {
-                                       grp = BKE_group_object_find(grp, ob);
-                               }
-                               if (!grp) {
-                                       ob->flag &= ~OB_FROMGROUP;
-                               }
+       for (BaseLegacy *base = sce->base.first; base; base = base->next) {
+               Object *ob = base->object;
+               if (ob->flag & OB_FROMGROUP) {
+                       Group *grp = BKE_group_object_find(NULL, ob);
+
+                       /* Unlinked group (old_id) is still in bmain... */
+                       if (grp && (&grp->id == old_id || grp->id.us == 0)) {
+                               grp = BKE_group_object_find(grp, ob);
                        }
-                       if (!(ob->flag & OB_FROMGROUP)) {
-                               base->flag &= ~OB_FROMGROUP;
+                       if (!grp) {
+                               ob->flag &= ~OB_FROMGROUP;
                        }
                }
        }
index 97033a9555d4610ae4e0e8f6cd7f1ece55dcde47..2632acea58bb63039b0527a5e4b0c088fd1d9fce 100644 (file)
@@ -316,7 +316,7 @@ bool BKE_mball_is_basis_for(Object *ob1, Object *ob2)
 void BKE_mball_properties_copy(Scene *scene, Object *active_object)
 {
        Scene *sce_iter = scene;
-       Base *base;
+       BaseLegacy *base;
        Object *ob;
        MetaBall *active_mball = (MetaBall *)active_object->data;
        int basisnr, obnr;
@@ -359,27 +359,25 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object)
  */
 Object *BKE_mball_basis_find(Scene *scene, Object *basis)
 {
-       Scene *sce_iter = scene;
-       Base *base;
-       Object *ob, *bob = basis;
+       Object *bob = basis;
        int basisnr, obnr;
        char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
-       SceneBaseIter iter;
-       EvaluationContext *eval_ctx = G.main->eval_ctx;
 
        BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
 
-       BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
-       while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
-               if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
-                       if (ob != bob) {
-                               BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
-
-                               /* object ob has to be in same "group" ... it means, that it has to have same base of its name */
-                               if (STREQ(obname, basisname)) {
-                                       if (obnr < basisnr) {
-                                               basis = ob;
-                                               basisnr = obnr;
+       for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+               for (Base *base = sl->object_bases.first; base; base = base->next) {
+                       Object *ob = base->object;
+                       if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
+                               if (ob != bob) {
+                                       BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
+
+                                       /* object ob has to be in same "group" ... it means, that it has to have same base of its name */
+                                       if (STREQ(obname, basisname)) {
+                                               if (obnr < basisnr) {
+                                                       basis = ob;
+                                                       basisnr = obnr;
+                                               }
                                        }
                                }
                        }
index 5c0b09f0ff0684503666907429b73dd8421c6889..144a885ffd40099db53d8bf68550a6ca796c5674 100644 (file)
@@ -1080,7 +1080,7 @@ static void polygonize(PROCESS *process)
 static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob)
 {
        Scene *sce_iter = scene;
-       Base *base;
+       BaseLegacy *base;
        Object *bob;
        MetaBall *mb;
        const MetaElem *ml;
@@ -1102,7 +1102,7 @@ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scen
                        zero_size = 0;
                        ml = NULL;
 
-                       if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) {
+                       if (bob == ob && (base->flag_legacy & OB_FROMDUPLI) == 0) {
                                mb = ob->data;
 
                                if (mb->editelems) ml = mb->editelems->first;
index 3f3b48966535d9df6d29beff6d5cac333efcb29a..05422a01dbfaad9664a97f6fdbb5419ab95d05dc 100644 (file)
@@ -3776,3 +3776,20 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
 
        return true;
 }
+
+/* -------------------------------------------------------------------- */
+/* NodeTree kernel functions */
+
+void BKE_nodetree_remove_layer_n(bNodeTree *ntree, Scene *scene, const int layer_index)
+{
+       for (bNode *node = ntree->nodes.first; node; node = node->next) {
+               if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) {
+                       if (node->custom1 == layer_index) {
+                               node->custom1 = 0;
+                       }
+                       else if (node->custom1 > layer_index) {
+                               node->custom1--;
+                       }
+               }
+       }
+}
index ff8be5892e9ef98d26061143362c1b4bd906a783..08cb9e57ab487db8d7fa9690299c4ca388be9bde 100644 (file)
@@ -91,6 +91,7 @@
 #include "BKE_icons.h"
 #include "BKE_key.h"
 #include "BKE_lamp.h"
+#include "BKE_layer.h"
 #include "BKE_lattice.h"
 #include "BKE_library.h"
 #include "BKE_library_query.h"
@@ -153,7 +154,7 @@ void BKE_object_workob_clear(Object *workob)
 
 void BKE_object_update_base_layer(struct Scene *scene, Object *ob)
 {
-       Base *base = scene->base.first;
+       BaseLegacy *base = scene->base.first;
 
        while (base) {
                if (base->object == ob) base->lay = ob->lay;
@@ -677,23 +678,25 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
 /* general add: to scene, with layer from area and default name */
 /* creates minimum required data, but without vertices etc. */
 Object *BKE_object_add(
-        Main *bmain, Scene *scene,
+        Main *bmain, Scene *scene, SceneLayer *sl,
         int type, const char *name)
 {
        Object *ob;
        Base *base;
+       LayerCollection *lc;
 
        ob = BKE_object_add_only_object(bmain, type, name);
 
        ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
 
-       ob->lay = scene->lay;
-       
-       base = BKE_scene_base_add(scene, ob);
-       BKE_scene_base_deselect_all(scene);
-       BKE_scene_base_select(scene, base);
-       DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+       lc = BKE_layer_collection_active(sl);
+       BKE_collection_object_add(scene, lc->scene_collection, ob);
+
+       base = BKE_scene_layer_base_find(sl, ob);
+       BKE_scene_layer_base_deselect_all(sl);
+       BKE_scene_layer_base_select(sl, base);
 
+       DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
        return ob;
 }
 
@@ -2542,11 +2545,11 @@ void BKE_scene_foreach_display_point(
         Scene *scene, View3D *v3d, const short flag,
         void (*func_cb)(const float[3], void *), void *user_data)
 {
-       Base *base;
+       BaseLegacy *base;
        Object *ob;
 
        for (base = FIRSTBASE; base; base = base->next) {
-               if (BASE_VISIBLE_BGMODE(v3d, scene, base) && (base->flag & flag) == flag) {
+               if (BASE_VISIBLE_BGMODE(v3d, scene, base) && (base->flag_legacy & flag) == flag) {
                        ob = base->object;
 
                        if ((ob->transflag & OB_DUPLI) == 0) {
@@ -3351,7 +3354,7 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS
 {
        LinkNode *links = NULL;
 
-       Base *base;
+       BaseLegacy *base;
 
        /* Remove markers from all objects */
        for (base = scene->base.first; base; base = base->next) {
@@ -3395,7 +3398,7 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS
 
                                /* child relationship */
                                if (includeFilter & (OB_REL_CHILDREN | OB_REL_CHILDREN_RECURSIVE)) {
-                                       Base *local_base;
+                                       BaseLegacy *local_base;
                                        for (local_base = scene->base.first; local_base; local_base = local_base->next) {
                                                if (BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, local_base)) {
 
@@ -3441,18 +3444,11 @@ struct LinkNode *BKE_object_groups(Object *ob)
        return group_linknode;
 }
 
-void BKE_object_groups_clear(Scene *scene, Base *base, Object *object)
+void BKE_object_groups_clear(Object *ob)
 {
        Group *group = NULL;
-
-       BLI_assert((base == NULL) || (base->object == object));
-
-       if (scene && base == NULL) {
-               base = BKE_scene_base_find(scene, object);
-       }
-
-       while ((group = BKE_group_object_find(group, base->object))) {
-               BKE_group_object_unlink(group, object, scene, base);
+       while ((group = BKE_group_object_find(group, ob))) {
+               BKE_group_object_unlink(group, ob);
        }
 }
 
index e3b801b319336a749ce4c53f05ab1211331c5a1d..26af1c48afbef203580440dc1ba0ba731a6358b6 100644 (file)
@@ -241,7 +241,7 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
        else {
                unsigned int lay = ctx->scene->lay;
                int baseid = 0;
-               Base *base;
+               BaseLegacy *base;
                for (base = ctx->scene->base.first; base; base = base->next, baseid++) {
                        Object *ob = base->object;
 
index 943dc7812461703ecab0703ed1b172c8f787d87f..8531c7c9df98592ad55a46a5f690ec70ecd262c7 100644 (file)
@@ -2896,7 +2896,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
        ParticleSystem *psys = sim->psys;
        ParticleSettings *part = psys->part;
        ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
-       Base *base;
+       BaseLegacy *base;
        int distr=0, alloc=0, skip=0;
 
        if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET)
index 30eb8dcb287b6c963bee61471b58d3166e8d7fa8..c3f2107c5afb4e47731477c8af8a9096bfb88869 100644 (file)
@@ -3541,7 +3541,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
        Main *bmain = baker->main;
        Scene *scene = baker->scene;
        Scene *sce_iter; /* SETLOOPER macro only */
-       Base *base;
+       BaseLegacy *base;
        ListBase pidlist;
        PTCacheID *pid = &baker->pid;
        PointCache *cache = NULL;
index a1338b4ea10cc09f56f87b07f8151b50606a420c..d47982f96eb86dcf03220cdb74a0dec8e540ec5d 100644 (file)
@@ -67,6 +67,7 @@
 #include "BKE_action.h"
 #include "BKE_armature.h"
 #include "BKE_cachefile.h"
+#include "BKE_collection.h"
 #include "BKE_colortools.h"
 #include "BKE_depsgraph.h"
 #include "BKE_editmesh.h"
@@ -78,6 +79,7 @@
 #include "BKE_icons.h"
 #include "BKE_idprop.h"
 #include "BKE_image.h"
+#include "BKE_layer.h"
 #include "BKE_library.h"
 #include "BKE_library_remap.h"
 #include "BKE_linestyle.h"
@@ -154,13 +156,66 @@ static void remove_sequencer_fcurves(Scene *sce)
        }
 }
 
+/* copy SceneCollection tree but keep pointing to the same objects */
+static void scene_collection_copy(SceneCollection *scn, SceneCollection *sc)
+{
+       BLI_duplicatelist(&scn->objects, &sc->objects);
+       for (LinkData *link = scn->objects.first; link; link = link->next) {
+               id_us_plus(link->data);
+       }
+
+       BLI_duplicatelist(&scn->filter_objects, &sc->filter_objects);
+       for (LinkData *link = scn->filter_objects.first; link; link = link->next) {
+               id_us_plus(link->data);
+       }
+
+       BLI_duplicatelist(&scn->scene_collections, &sc->scene_collections);
+       SceneCollection *nscn = scn->scene_collections.first; /* nested SceneCollection new */
+       for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+               scene_collection_copy(nscn, nsc);
+               nscn = nscn->next;
+       }
+}
+
+/* Find the equivalent SceneCollection in the new tree */
+static SceneCollection *scene_collection_from_new_tree(SceneCollection *sc_reference, SceneCollection *scn, SceneCollection *sc)
+{
+       if (sc == sc_reference) {
+               return scn;
+       }
+
+       SceneCollection *nscn = scn->scene_collections.first; /* nested master collection new */
+       for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+
+               SceneCollection *found = scene_collection_from_new_tree(sc_reference, nscn, nsc);
+               if (found) {
+                       return found;
+               }
+               nscn = nscn->next;
+       }
+       return NULL;
+}
+
+/* recreate the LayerCollection tree */
+static void layer_collections_recreate(SceneLayer *sl, ListBase *lb, SceneCollection *mcn, SceneCollection *mc)
+{
+       for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+
+               SceneCollection *sc = scene_collection_from_new_tree(lc->scene_collection, mcn, mc);
+               BLI_assert(sc);
+
+               /* instead of syncronizing both trees we simply re-create it */
+               BKE_collection_link(sl, sc);
+       }
+}
+
 Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
 {
        Scene *scen;
        SceneRenderLayer *srl, *new_srl;
        FreestyleLineSet *lineset;
        ToolSettings *ts;
-       Base *base, *obase;
+       BaseLegacy *legacy_base, *olegacy_base;
        
        if (type == SCE_COPY_EMPTY) {
                ListBase rl, rv;
@@ -214,14 +269,14 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
                        BKE_libblock_relink_ex(bmain, scen->nodetree, &sce->id, &scen->id, false);
                }
 
-               obase = sce->base.first;
-               base = scen->base.first;
-               while (base) {
-                       id_us_plus(&base->object->id);
-                       if (obase == sce->basact) scen->basact = base;
+               olegacy_base = sce->base.first;
+               legacy_base = scen->base.first;
+               while (legacy_base) {
+                       id_us_plus(&legacy_base->object->id);
+                       if (olegacy_base == sce->basact) scen->basact = legacy_base;
        
-                       obase = obase->next;
-                       base = base->next;
+                       olegacy_base = olegacy_base->next;
+                       legacy_base = legacy_base->next;
                }
 
                /* copy action and remove animation used by sequencer */
@@ -244,6 +299,36 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
                        }
                        new_srl = new_srl->next;
                }
+
+               /* layers and collections */
+               scen->collection = MEM_dupallocN(sce->collection);
+               SceneCollection *mcn = BKE_collection_master(scen);
+               SceneCollection *mc = BKE_collection_master(sce);
+
+               /* recursively creates a new SceneCollection tree */
+               scene_collection_copy(mcn, mc);
+
+               BLI_duplicatelist(&scen->render_layers, &sce->render_layers);
+               SceneLayer *new_sl = scen->render_layers.first;
+               for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
+
+                       /* we start fresh with no overrides and no visibility flags set
+                        * instead of syncing both trees we simply unlink and relink the scene collection */
+                       BLI_listbase_clear(&new_sl->layer_collections);
+                       BLI_listbase_clear(&new_sl->object_bases);
+                       layer_collections_recreate(new_sl, &sl->layer_collections, mcn, mc);
+
+                       if (sl->basact) {
+                               Object *active_ob = sl->basact->object;
+                               for (Base *base = new_sl->object_bases.first; base; base = base->next) {
+                                       if (base->object == active_ob) {
+                                               new_sl->basact = base;
+                                               break;
+                                       }
+                               }
+                       }
+                       new_sl = new_sl->next;
+               }
        }
 
        /* copy color management settings */
@@ -471,6 +556,16 @@ void BKE_scene_free(Scene *sce)
 
        BKE_previewimg_free(&sce->preview);
        curvemapping_free_data(&sce->r.mblur_shutter_curve);
+
+       for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
+               BKE_scene_layer_free(sl);
+       }
+       BLI_freelistN(&sce->render_layers);
+
+       /* Master Collection */
+       BKE_collection_master_free(sce);
+       MEM_freeN(sce->collection);
+       sce->collection = NULL;
 }
 
 void BKE_scene_init(Scene *sce)
@@ -820,6 +915,12 @@ void BKE_scene_init(Scene *sce)
        sce->toolsettings->gpencil_v2d_align = GP_PROJECT_VIEWSPACE;
        sce->toolsettings->gpencil_seq_align = GP_PROJECT_VIEWSPACE;
        sce->toolsettings->gpencil_ima_align = GP_PROJECT_VIEWSPACE;
+
+       /* Master Collection */
+       sce->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection");
+       BLI_strncpy(sce->collection->name, "Master Collection", sizeof(sce->collection->name));
+
+       BKE_scene_layer_add(sce, "Render Layer");
 }
 
 Scene *BKE_scene_add(Main *bmain, const char *name)
@@ -835,9 +936,9 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
        return sce;
 }
 
-Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name)
+BaseLegacy *BKE_scene_base_find_by_name(struct Scene *scene, const char *name)
 {
-       Base *base;
+       BaseLegacy *base;
 
        for (base = scene->base.first; base; base = base->next) {
                if (STREQ(base->object->id.name + 2, name)) {
@@ -848,9 +949,9 @@ Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name)
        return base;
 }
 
-Base *BKE_scene_base_find(Scene *scene, Object *ob)
+BaseLegacy *BKE_scene_base_find(Scene *scene, Object *ob)
 {
-       return BLI_findptr(&scene->base, ob, offsetof(Base, object));
+       return BLI_findptr(&scene->base, ob, offsetof(BaseLegacy, object));
 }
 
 /**
@@ -861,11 +962,10 @@ Base *BKE_scene_base_find(Scene *scene, Object *ob)
 void BKE_scene_set_background(Main *bmain, Scene *scene)
 {
        Scene *sce;
-       Base *base;
+       BaseLegacy *base;
        Object *ob;
        Group *group;
        GroupObject *go;
-       int flag;
        
        /* check for cyclic sets, for reading old files but also for definite security (py?) */
        BKE_scene_validate_setscene(bmain, scene);
@@ -897,13 +997,7 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
                ob->lay = base->lay;
                
                /* group patch... */
-               base->flag &= ~(OB_FROMGROUP);
-               flag = ob->flag & (OB_FROMGROUP);
-               base->flag |= flag;
-               
-               /* not too nice... for recovering objects with lost data */
-               //if (ob->pose == NULL) base->flag &= ~OB_POSEMODE;
-               ob->flag = base->flag;
+               BKE_scene_base_flag_sync_from_base(base);
        }
        /* no full animation update, this to enable render code to work (render code calls own animation updates) */
 }
@@ -924,7 +1018,7 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name)
 
 /* Used by metaballs, return *all* objects (including duplis) existing in the scene (including scene's sets) */
 int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
-                             Scene **scene, int val, Base **base, Object **ob)
+                             Scene **scene, int val, BaseLegacy **base, Object **ob)
 {
        bool run_again = true;
        
@@ -1006,7 +1100,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
                                }
                                /* handle dupli's */
                                if (iter->dupob) {
-                                       (*base)->flag |= OB_FROMDUPLI;
+                                       (*base)->flag_legacy |= OB_FROMDUPLI;
                                        *ob = iter->dupob->ob;
                                        iter->phase = F_DUPLI;
 
@@ -1025,7 +1119,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
                                }
                                else if (iter->phase == F_DUPLI) {
                                        iter->phase = F_SCENE;
-                                       (*base)->flag &= ~OB_FROMDUPLI;
+                                       (*base)->flag_legacy &= ~OB_FROMDUPLI;
                                        
                                        if (iter->dupli_refob) {
                                                /* Restore last object's real matrix. */
@@ -1052,7 +1146,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
 
 Object *BKE_scene_camera_find(Scene *sc)
 {
-       Base *base;
+       BaseLegacy *base;
        
        for (base = sc->base.first; base; base = base->next)
                if (base->object->type == OB_CAMERA)
@@ -1154,28 +1248,32 @@ char *BKE_scene_find_last_marker_name(Scene *scene, int frame)
        return best_marker ? best_marker->name : NULL;
 }
 
+void BKE_scene_remove_rigidbody_object(Scene *scene, Object *ob)
+{
+       /* remove rigid body constraint from world before removing object */
+       if (ob->rigidbody_constraint)
+               BKE_rigidbody_remove_constraint(scene, ob);
+       /* remove rigid body object from world before removing object */
+       if (ob->rigidbody_object)
+               BKE_rigidbody_remove_object(scene, ob);
+}
 
-Base *BKE_scene_base_add(Scene *sce, Object *ob)
+BaseLegacy *BKE_scene_base_add(Scene *sce, Object *ob)
 {
-       Base *b = MEM_callocN(sizeof(*b), __func__);
+       BaseLegacy *b = MEM_callocN(sizeof(*b), __func__);
        BLI_addhead(&sce->base, b);
 
        b->object = ob;
-       b->flag = ob->flag;
+       b->flag_legacy = ob->flag;
        b->lay = ob->lay;
 
        return b;
 }
 
-void BKE_scene_base_unlink(Scene *sce, Base *base)
+void BKE_scene_base_unlink(Scene *sce, BaseLegacy *base)
 {
-       /* remove rigid body constraint from world before removing object */
-       if (base->object->rigidbody_constraint)
-               BKE_rigidbody_remove_constraint(sce, base->object);
-       /* remove rigid body object from world before removing object */
-       if (base->object->rigidbody_object)
-               BKE_rigidbody_remove_object(sce, base->object);
-       
+       BKE_scene_remove_rigidbody_object(sce, base->object);
+
        BLI_remlink(&sce->base, base);
        if (sce->basact == base)
                sce->basact = NULL;
@@ -1183,18 +1281,20 @@ void BKE_scene_base_unlink(Scene *sce, Base *base)
 
 void BKE_scene_base_deselect_all(Scene *sce)
 {
-       Base *b;
+       BaseLegacy *b;
 
        for (b = sce->base.first; b; b = b->next) {
-               b->flag &= ~SELECT;
-               b->object->flag = b->flag;
+               b->flag_legacy &= ~SELECT;
+               int flag = b->object->flag & (OB_FROMGROUP);
+               b->object->flag = b->flag_legacy;
+               b->object->flag |= flag;
        }
 }
 
-void BKE_scene_base_select(Scene *sce, Base *selbase)
+void BKE_scene_base_select(Scene *sce, BaseLegacy *selbase)
 {
-       selbase->flag |= SELECT;
-       selbase->object->flag = selbase->flag;
+       selbase->flag_legacy |= SELECT;
+       selbase->object->flag = selbase->flag_legacy;
 
        sce->basact = selbase;
 }
@@ -1492,15 +1592,7 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer *
 
        for (sce = bmain->scene.first; sce; sce = sce->id.next) {
                if (sce->nodetree) {
-                       bNode *node;
-                       for (node = sce->nodetree->nodes.first; node; node = node->next) {
-                               if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) {
-                                       if (node->custom1 == act)
-                                               node->custom1 = 0;
-                                       else if (node->custom1 > act)
-                                               node->custom1--;
-                               }
-                       }
+                       BKE_nodetree_remove_layer_n(sce->nodetree, scene, act);
                }
        }
 
@@ -1588,7 +1680,7 @@ float get_render_aosss_error(const RenderData *r, float error)
 }
 
 /* helper function for the SETLOOPER macro */
-Base *_setlooper_base_step(Scene **sce_iter, Base *base)
+BaseLegacy *_setlooper_base_step(Scene **sce_iter, BaseLegacy *base)
 {
        if (base && base->next) {
                /* common case, step to the next */
@@ -1596,12 +1688,12 @@ Base *_setlooper_base_step(Scene **sce_iter, Base *base)
        }
        else if (base == NULL && (*sce_iter)->base.first) {
                /* first time looping, return the scenes first base */
-               return (Base *)(*sce_iter)->base.first;
+               return (BaseLegacy *)(*sce_iter)->base.first;
        }
        else {
                /* reached the end, get the next base in the set */
                while ((*sce_iter = (*sce_iter)->set)) {
-                       base = (Base *)(*sce_iter)->base.first;
+                       base = (BaseLegacy *)(*sce_iter)->base.first;
                        if (base) {
                                return base;
                        }
@@ -1648,24 +1740,56 @@ bool BKE_scene_uses_blender_game(const Scene *scene)
 
 void BKE_scene_base_flag_to_objects(struct Scene *scene)
 {
-       Base *base = scene->base.first;
+       BaseLegacy *base = scene->base.first;
 
        while (base) {
-               base->object->flag = base->flag;
+               BKE_scene_base_flag_sync_from_base(base);
                base = base->next;
        }
 }
 
 void BKE_scene_base_flag_from_objects(struct Scene *scene)
 {
-       Base *base = scene->base.first;
+       BaseLegacy *base = scene->base.first;
 
        while (base) {
-               base->flag = base->object->flag;
+               BKE_scene_base_flag_sync_from_object(base);
                base = base->next;
        }
 }
 
+void BKE_scene_base_flag_sync_from_base(BaseLegacy *base)
+{
+       Object *ob = base->object;
+
+       /* keep the object only flags untouched */
+       int flag = ob->flag & OB_FROMGROUP;
+
+       ob->flag = base->flag_legacy;
+       ob->flag |= flag;
+}
+
+void BKE_scene_base_flag_sync_from_object(BaseLegacy *base)
+{
+       base->flag_legacy = base->object->flag;
+}
+
+void BKE_scene_object_base_flag_sync_from_base(Base *base)
+{
+       Object *ob = base->object;
+
+       /* keep the object only flags untouched */
+       int flag = ob->flag & OB_FROMGROUP;
+
+       ob->flag = base->flag;
+       ob->flag |= flag;
+}
+
+void BKE_scene_object_base_flag_sync_from_object(Base *base)
+{
+       base->flag = base->object->flag;
+}
+
 void BKE_scene_disable_color_management(Scene *scene)
 {
        ColorManagedDisplaySettings *display_settings = &scene->display_settings;
index d0ef5cfc0928ef3939fb5b2f071a82a0b4fd7542..f1ce69d3945c9773371e3728cde6f66a263ab771 100644 (file)
@@ -698,7 +698,7 @@ static float calc_voxel_transp(float *result, float *input, int res[3], int *pix
 
 static int get_lamp(Scene *scene, float *light)
 {
-       Base *base_tmp = NULL;
+       BaseLegacy *base_tmp = NULL;
        int found_lamp = 0;
 
        // try to find a lamp, preferably local
index 660107eb2e65e2515219249db52ad34e9033d2c9..e7df1d810c99aa719007531872959edc0bfcae85 100644 (file)
@@ -530,7 +530,7 @@ static void ccd_build_deflector_hash(Scene *scene, Group *group, Object *vertexo
                }
        }
        else {
-               for (Base *base = scene->base.first; base; base = base->next) {
+               for (BaseLegacy *base = scene->base.first; base; base = base->next) {
                        /*Only proceed for mesh object in same layer */
                        if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) {
                                ob= base->object;
@@ -576,7 +576,7 @@ static void ccd_update_deflector_hash(Scene *scene, Group *group, Object *vertex
                }
        }
        else {
-               for (Base *base = scene->base.first; base; base = base->next) {
+               for (BaseLegacy *base = scene->base.first; base; base = base->next) {
                        /*Only proceed for mesh object in same layer */
                        if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) {
                                ob= base->object;
@@ -986,7 +986,7 @@ static bool are_there_deflectors(Scene *scene, Group *group, unsigned int layer)
                }
        }
        else {
-               for (Base *base = scene->base.first; base; base= base->next) {
+               for (BaseLegacy *base = scene->base.first; base; base= base->next) {
                        if ( (base->lay & layer) && base->object->pd) {
                                if (base->object->pd->deflect)
                                        return 1;
index 22288127119ec49e10dbda1cefe299651b4666e9..e10f92078969a9e9d6bcad4f5497b6c52e8ce32c 100644 (file)
@@ -782,7 +782,7 @@ void BKE_sound_read_waveform(bSound *sound, short *stop)
 void BKE_sound_update_scene(Main *bmain, struct Scene *scene)
 {
        Object *ob;
-       Base *base;
+       BaseLegacy *base;
        NlaTrack *track;
        NlaStrip *strip;
        Speaker *speaker;
index 7e3a009ede8cda9be5228f3f3386984073a9073d..068c188e3361e2f62eead0625336bcb559ee90de 100644 (file)
@@ -32,6 +32,7 @@
  *  \ingroup bli
  */
 
+#include "BLI_blenlib.h"
 #include "BLI_sys_types.h" /* for bool */
 #include "BLI_compiler_attrs.h"
 
diff --git a/source/blender/blenlib/BLI_iterator.h b/source/blender/blenlib/BLI_iterator.h
new file mode 100644 (file)
index 0000000..cfa303b
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * ***** 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.
+ *
+ * Contributor(s): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_ITERATOR_H__
+#define __BLI_ITERATOR_H__
+
+/** \file BLI_iterator.h
+ *  \ingroup bli
+ */
+
+typedef struct Iterator {
+       void *current; /* current pointer we iterate over */
+       void *data;    /* stored data required for this iterator */
+       bool valid;
+} Iterator;
+
+typedef void (*IteratorCb)(Iterator *iter);
+typedef void (*IteratorBeginCb)(Iterator *iter, void *data_in);
+
+#define ITER_BEGIN(callback_begin, callback_next, callback_end, _data_in, _data_out) \
+{                                                                                    \
+       IteratorCb callback_end_func = callback_end;                                     \
+       Iterator iter_macro;                                                             \
+       for (callback_begin(&iter_macro, _data_in);                                      \
+            iter_macro.valid;                                                           \
+            callback_next(&iter_macro))                                                 \
+    {                                                                                \
+               _data_out = iter_macro.current;
+
+#define ITER_END                                                                     \
+       }                                                                                \
+       callback_end_func(&iter_macro);                                                  \
+}
+
+#endif /* __BLI_ITERATOR_H__ */
index 3277519c66e5a19f1b80666d439ec1353648db1d..97225170f67bbcfada0af53ebd27b47f43a6704e 100644 (file)
@@ -155,6 +155,7 @@ set(SRC
        BLI_hash_md5.h
        BLI_hash_mm2a.h
        BLI_heap.h
+       BLI_iterator.h
        BLI_jitter.h
        BLI_kdopbvh.h
        BLI_kdtree.h
index 8cb9ef837b218a0ec5f83afc71873ceb2303ef11..e40692f4a889a7ee798537c5bbaec5c24fd01e68 100644 (file)
@@ -53,6 +53,7 @@ set(SRC
        intern/versioning_250.c
        intern/versioning_260.c
        intern/versioning_270.c
+       intern/versioning_280.c
        intern/versioning_defaults.c
        intern/versioning_legacy.c
        intern/writefile.c
index 060d290df326a20743d95fb1a32ee34cd3c3692b..e669bf3b4a6ba3536cec94fe59536b44681c896c 100644 (file)
@@ -72,6 +72,7 @@
 #include "DNA_ipo_types.h"
 #include "DNA_key_types.h"
 #include "DNA_lattice_types.h"
+#include "DNA_layer_types.h"
 #include "DNA_lamp_types.h"
 #include "DNA_linestyle_types.h"
 #include "DNA_meta_types.h"
 #include "DNA_movieclip_types.h"
 #include "DNA_mask_types.h"
 
+#include "RNA_access.h"
+
 #include "MEM_guardedalloc.h"
 
 #include "BLI_endian_switch.h"
@@ -5630,11 +5633,29 @@ static bool scene_validate_setscene__liblink(Scene *sce, const int totscene)
 }
 #endif
 
+static void lib_link_scene_collection(FileData *fd, Library *lib, SceneCollection *sc)
+{
+       for (LinkData *link = sc->objects.first; link; link = link->next) {
+               link->data = newlibadr_us(fd, lib, link->data);
+               BLI_assert(link->data);
+       }
+
+       for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
+               link->data = newlibadr_us(fd, lib, link->data);
+               BLI_assert(link->data);
+       }
+
+       for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+               lib_link_scene_collection(fd, lib, nsc);
+       }
+}
+
 static void lib_link_scene(FileData *fd, Main *main)
 {
        Scene *sce;
-       Base *base, *next;
+       BaseLegacy *base_legacy, *base_legacy_next;
        Sequence *seq;
+       SceneLayer *sl;
        SceneRenderLayer *srl;
        FreestyleModuleConfig *fmc;
        FreestyleLineSet *fls;
@@ -5684,17 +5705,17 @@ static void lib_link_scene(FileData *fd, Main *main)
                        
                        sce->toolsettings->particle.shape_object = newlibadr(fd, sce->id.lib, sce->toolsettings->particle.shape_object);
                        
-                       for (base = sce->base.first; base; base = next) {
-                               next = base->next;
+                       for (base_legacy = sce->base.first; base_legacy; base_legacy = base_legacy_next) {
+                               base_legacy_next = base_legacy->next;
                                
-                               base->object = newlibadr_us(fd, sce->id.lib, base->object);
+                               base_legacy->object = newlibadr_us(fd, sce->id.lib, base_legacy->object);
                                
-                               if (base->object == NULL) {
+                               if (base_legacy->object == NULL) {
                                        blo_reportf_wrap(fd->reports, RPT_WARNING, TIP_("LIB: object lost from scene: '%s'"),
                                                         sce->id.name + 2);
-                                       BLI_remlink(&sce->base, base);
-                                       if (base == sce->basact) sce->basact = NULL;
-                                       MEM_freeN(base);
+                                       BLI_remlink(&sce->base, base_legacy);
+                                       if (base_legacy == sce->basact) sce->basact = NULL;
+                                       MEM_freeN(base_legacy);
                                }
                        }
                        
@@ -5780,6 +5801,15 @@ static void lib_link_scene(FileData *fd, Main *main)
                        /* Motion Tracking */
                        sce->clip = newlibadr_us(fd, sce->id.lib, sce->clip);
 
+                       lib_link_scene_collection(fd, sce->id.lib, sce->collection);
+
+                       for (sl = sce->render_layers.first; sl; sl = sl->next) {
+                               for (Base *base = sl->object_bases.first; base; base = base->next) {
+                                       /* we only bump the use count for the collection objects */
+                                       base->object = newlibadr(fd, sce->id.lib, base->object);
+                               }
+                       }
+
 #ifdef USE_SETSCENE_CHECK
                        if (sce->set != NULL) {
                                /* link flag for scenes with set would be reset later,
@@ -5883,12 +5913,42 @@ static void direct_link_view_settings(FileData *fd, ColorManagedViewSettings *vi
                direct_link_curvemapping(fd, view_settings->curve_mapping);
 }
 
+static void direct_link_scene_collection(FileData *fd, SceneCollection *sc)
+{
+       link_list(fd, &sc->objects);
+       link_list(fd, &sc->filter_objects);
+       link_list(fd, &sc->scene_collections);
+
+       for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+               direct_link_scene_collection(fd, nsc);
+       }
+}
+
+static void direct_link_layer_collections(FileData *fd, ListBase *lb)
+{
+       link_list(fd, lb);
+       for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+               lc->scene_collection = newdataadr(fd, lc->scene_collection);
+
+               link_list(fd, &lc->object_bases);
+
+               for (LinkData *link = lc->object_bases.first; link; link = link->next) {
+                       link->data = newdataadr(fd, link->data);
+               }
+
+               link_list(fd, &lc->overrides);
+
+               direct_link_layer_collections(fd, &lc->layer_collections);
+       }
+}
+
 static void direct_link_scene(FileData *fd, Scene *sce)
 {
        Editing *ed;
        Sequence *seq;
        MetaStack *ms;
        RigidBodyWorld *rbw;
+       SceneLayer *sl;
        SceneRenderLayer *srl;
        
        sce->theDag = NULL;
@@ -6139,6 +6199,19 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        sce->preview = direct_link_preview_image(fd, sce->preview);
 
        direct_link_curvemapping(fd, &sce->r.mblur_shutter_curve);
+
+       /* this runs before the very first doversion */
+       if (sce->collection) {
+               sce->collection = newdataadr(fd, sce->collection);
+               direct_link_scene_collection(fd, sce->collection);
+       }
+
+       link_list(fd, &sce->render_layers);
+       for (sl = sce->render_layers.first; sl; sl = sl->next) {
+               link_list(fd, &sl->object_bases);
+               sl->basact = newdataadr(fd, sl->basact);
+               direct_link_layer_collections(fd, &sl->layer_collections);
+       }
 }
 
 /* ************ READ WM ***************** */
@@ -6482,6 +6555,10 @@ static void lib_link_screen(FileData *fd, Main *main)
                                                
                                                slogic->gpd = newlibadr_us(fd, sc->id.lib, slogic->gpd);
                                        }
+                                       else if (sl->spacetype == SPACE_COLLECTIONS) {
+                                               SpaceCollections *slayer = (SpaceCollections *)sl;
+                                               slayer->flag |= SC_COLLECTION_DATA_REFRESH;
+                                       }
                                }
                        }
                        sc->id.tag &= ~LIB_TAG_NEED_LINK;
@@ -6867,6 +6944,10 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
                                        
                                        slogic->gpd = restore_pointer_by_name(id_map, (ID *)slogic->gpd, USER_REAL);
                                }
+                               else if (sl->spacetype == SPACE_COLLECTIONS) {
+                                       SpaceCollections *slayer = (SpaceCollections *)sl;
+                                       slayer->flag |= SC_COLLECTION_DATA_REFRESH;
+                               }
                        }
                }
        }
@@ -7261,6 +7342,10 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
                                sclip->scopes.track_preview = NULL;
                                sclip->scopes.ok = 0;
                        }
+                       else if (sl->spacetype == SPACE_COLLECTIONS) {
+                               SpaceCollections *slayer = (SpaceCollections *)sl;
+                               slayer->flag |= SC_COLLECTION_DATA_REFRESH;
+                       }
                }
                
                BLI_listbase_clear(&sa->actionzones);
@@ -7457,7 +7542,7 @@ static void lib_link_group(FileData *fd, Main *main)
                        if (add_us) {
                                id_us_ensure_real(&group->id);
                        }
-                       BKE_group_object_unlink(group, NULL, NULL, NULL);       /* removes NULL entries */
+                       BKE_group_object_unlink(group, NULL);   /* removes NULL entries */
                }
        }
 }
@@ -8389,6 +8474,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        blo_do_versions_250(fd, lib, main);
        blo_do_versions_260(fd, lib, main);
        blo_do_versions_270(fd, lib, main);
+       blo_do_versions_280(fd, lib, main);
 
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */
@@ -8400,8 +8486,8 @@ static void do_versions_after_linking(Main *main)
 {
 //     printf("%s for %s (%s), %d.%d\n", __func__, main->curlib ? main->curlib->name : main->name,
 //            main->curlib ? "LIB" : "MAIN", main->versionfile, main->subversionfile);
-
        do_versions_after_linking_270(main);
+       do_versions_after_linking_280(main);
 }
 
 static void lib_link_all(FileData *fd, Main *main)
@@ -9484,9 +9570,24 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
        }
 }
 
+static void expand_scene_collection(FileData *fd, Main *mainvar, SceneCollection *sc)
+{
+       for (LinkData *link = sc->objects.first; link; link = link->next) {
+               expand_doit(fd, mainvar, link->data);
+       }
+
+       for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
+               expand_doit(fd, mainvar, link->data);
+       }
+
+       for (SceneCollection *nsc= sc->scene_collections.first; nsc; nsc = nsc->next) {
+               expand_scene_collection(fd, mainvar, nsc);
+       }
+}
+
 static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
 {
-       Base *base;
+       BaseLegacy *base;
        SceneRenderLayer *srl;
        FreestyleModuleConfig *module;
        FreestyleLineSet *lineset;
@@ -9553,6 +9654,8 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
        }
 
        expand_doit(fd, mainvar, sce->clip);
+
+       expand_scene_collection(fd, mainvar, sce->collection);
 }
 
 static void expand_camera(FileData *fd, Main *mainvar, Camera *ca)
@@ -9799,7 +9902,7 @@ static bool object_in_any_scene(Main *mainvar, Object *ob)
 static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Library *lib, const short flag)
 {
        Object *ob;
-       Base *base;
+       BaseLegacy *base;
        const unsigned int active_lay = (flag & FILE_ACTIVELAY) ? BKE_screen_view3d_layer_active(v3d, scene) : 0;
        const bool is_link = (flag & FILE_LINK) != 0;
 
@@ -9820,7 +9923,7 @@ static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Libra
                        }
 
                        if (do_it) {
-                               base = MEM_callocN(sizeof(Base), __func__);
+                               base = MEM_callocN(sizeof(BaseLegacy), __func__);
                                BLI_addtail(&scene->base, base);
 
                                if (active_lay) {
@@ -9835,7 +9938,7 @@ static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Libra
 
                                base->object = ob;
                                base->lay = ob->lay;
-                               base->flag = ob->flag;
+                               BKE_scene_base_flag_sync_from_object(base);
 
                                CLAMP_MIN(ob->id.us, 0);
                                id_us_plus_no_lib((ID *)ob);
@@ -9851,7 +9954,7 @@ static void give_base_to_groups(
         Main *mainvar, Scene *scene, View3D *v3d, Library *UNUSED(lib), const short UNUSED(flag))
 {
        Group *group;
-       Base *base;
+       BaseLegacy *base;
        Object *ob;
        const unsigned int active_lay = BKE_screen_view3d_layer_active(v3d, scene);
 
@@ -9868,8 +9971,8 @@ static void give_base_to_groups(
 
                        /* assign the base */
                        base = BKE_scene_base_add(scene, ob);
-                       base->flag |= SELECT;
-                       base->object->flag = base->flag;
+                       base->flag_legacy |= SELECT;
+                       BKE_scene_base_flag_sync_from_base(base);
                        DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
                        scene->basact = base;
 
@@ -9951,10 +10054,10 @@ static ID *link_named_part(
 static void link_object_postprocess(ID *id, Scene *scene, View3D *v3d, const short flag)
 {
        if (scene) {
-               Base *base;
+               BaseLegacy *base;
                Object *ob;
 
-               base = MEM_callocN(sizeof(Base), "app_nam_part");
+               base = MEM_callocN(sizeof(BaseLegacy), "app_nam_part");
                BLI_addtail(&scene->base, base);
 
                ob = (Object *)id;
@@ -9967,12 +10070,12 @@ static void link_object_postprocess(ID *id, Scene *scene, View3D *v3d, const sho
                ob->mode = OB_MODE_OBJECT;
                base->lay = ob->lay;
                base->object = ob;
-               base->flag = ob->flag;
+               base->flag_legacy = ob->flag;
                id_us_plus_no_lib((ID *)ob);
 
                if (flag & FILE_AUTOSELECT) {
-                       base->flag |= SELECT;
-                       base->object->flag = base->flag;
+                       base->flag_legacy |= SELECT;
+                       BKE_scene_base_flag_sync_from_base(base);
                        /* do NOT make base active here! screws up GUI stuff, if you want it do it on src/ level */
                }
        }
index d97bef13a787ff7243ab0ba46421af4740652a98..50cdeca16b568c48e54b67b056a2f25168a2c300 100644 (file)
@@ -34,6 +34,8 @@
 #define __READFILE_H__
 
 #include "zlib.h"
+#include "DNA_sdna_types.h"
+#include "DNA_space_types.h"
 #include "DNA_windowmanager_types.h"  /* for ReportType */
 
 struct OldNewMap;
@@ -169,8 +171,10 @@ void blo_do_versions_pre250(struct FileData *fd, struct Library *lib, struct Mai
 void blo_do_versions_250(struct FileData *fd, struct Library *lib, struct Main *main);
 void blo_do_versions_260(struct FileData *fd, struct Library *lib, struct Main *main);
 void blo_do_versions_270(struct FileData *fd, struct Library *lib, struct Main *main);
+void blo_do_versions_280(struct FileData *fd, struct Library *lib, struct Main *main);
 
 void do_versions_after_linking_270(struct Main *main);
+void do_versions_after_linking_280(struct Main *main);
 
 #endif
 
index 1956a17d57bb21d5c369accd1653a539c345ccb8..943e5479d9a5f578d1b6deeaeffe7c02135e7bb3 100644 (file)
@@ -736,7 +736,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main)
        if (main->versionfile < 250) {
                bScreen *screen;
                Scene *scene;
-               Base *base;
+               BaseLegacy *base;
                Material *ma;
                Camera *cam;
                Mesh *me;
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
new file mode 100644 (file)
index 0000000..a4e69c9
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * ***** 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.
+ *
+ * Contributor(s): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/blenloader/intern/versioning_280.c
+ *  \ingroup blenloader
+ */
+
+/* allow readfile to use deprecated functionality */
+#define DNA_DEPRECATED_ALLOW
+
+#include "DNA_object_types.h"
+#include "DNA_layer_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_genfile.h"
+
+#include "BKE_collection.h"
+#include "BKE_layer.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "BLO_readfile.h"
+#include "readfile.h"
+
+#include "MEM_guardedalloc.h"
+
+void do_versions_after_linking_280(Main *main)
+{
+       if (!MAIN_VERSION_ATLEAST(main, 280, 0)) {
+               for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+                       /* since we don't have access to FileData we check the (always valid) first render layer instead */
+                       if (scene->render_layers.first == NULL) {
+                               SceneCollection *sc_master = BKE_collection_master(scene);
+                               BLI_strncpy(sc_master->name, "Master Collection", sizeof(sc_master->name));
+
+                               SceneCollection *collections[20] = {NULL};
+                               bool is_visible[20];
+
+                               int lay_used = 0;
+                               for (int i = 0; i < 20; i++) {
+                                       char name[MAX_NAME];
+
+                                       BLI_snprintf(name, sizeof(collections[i]->name), "%d", i + 1);
+                                       collections[i] = BKE_collection_add(scene, sc_master, name);
+
+                                       is_visible[i] = (scene->lay & (1 << i));
+                               }
+
+                               for (BaseLegacy *base = scene->base.first; base; base = base->next) {
+                                       lay_used |= base->lay & ((1 << 20) - 1); /* ignore localview */
+
+                                       for (int i = 0; i < 20; i++) {
+                                               if ((base->lay & (1 << i)) != 0) {
+                                                       BKE_collection_object_add(scene, collections[i], base->object);
+                                               }
+                                       }
+                               }
+
+                               scene->active_layer = 0;
+
+                               if (!BKE_scene_uses_blender_game(scene)) {
+                                       for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) {
+
+                                               SceneLayer *sl = BKE_scene_layer_add(scene, srl->name);
+                                               BKE_scene_layer_engine_set(sl, scene->r.engine);
+
+                                               if (srl->mat_override) {
+                                                       BKE_collection_override_datablock_add((LayerCollection *)sl->layer_collections.first, "material", (ID *)srl->mat_override);
+                                               }
+
+                                               if (srl->light_override && BKE_scene_uses_blender_internal(scene)) {
+                                                       /* not sure how we handle this, pending until we design the override system */
+                                                       TODO_LAYER_OVERRIDE;
+                                               }
+
+                                               if (srl->lay != scene->lay) {
+                                                       /* unlink master collection  */
+                                                       BKE_collection_unlink(sl, sl->layer_collections.first);
+
+                                                       /* add new collection bases */
+                                                       for (int i = 0; i < 20; i++) {
+                                                               if ((srl->lay & (1 << i)) != 0) {
+                                                                       BKE_collection_link(sl, collections[i]);
+                                                               }
+                                                       }
+                                               }
+
+                                               /* TODO: passes, samples, mask_layesr, exclude, ... */
+                                       }
+
+                                       if (BLI_findlink(&scene->render_layers, scene->r.actlay)) {
+                                               scene->active_layer = scene->r.actlay;
+                                       }
+                               }
+
+                               SceneLayer *sl = BKE_scene_layer_add(scene, "Render Layer");
+
+                               /* In this particular case we can safely assume the data struct */
+                               LayerCollection *lc = ((LayerCollection *)sl->layer_collections.first)->layer_collections.first;
+                               for (int i = 0; i < 20; i++) {
+                                       if (!is_visible[i]) {
+                                               lc->flag &= ~COLLECTION_VISIBLE;
+                                       }
+                                       lc = lc->next;
+                               }
+
+                               /* but we still need to make the flags synced */
+                               BKE_scene_layer_base_flag_recalculate(sl);
+
+                               /* convert active base */
+                               if (scene->basact) {
+                                       sl->basact = BKE_scene_layer_base_find(sl, scene->basact->object);
+                               }
+
+                               /* convert selected bases */
+                               for (BaseLegacy *base = scene->base.first; base; base = base->next) {
+                                       Base *ob_base = BKE_scene_layer_base_find(sl, base->object);
+                                       if ((base->flag_legacy & SELECT) != 0) {
+                                               if ((ob_base->flag & BASE_SELECTABLED) != 0) {
+                                                       ob_base->flag |= BASE_SELECTED;
+                                               }
+                                       }
+                                       else {
+                                               ob_base->flag &= ~BASE_SELECTED;
+                                       }
+                               }
+
+                               /* TODO: copy scene render data to layer */
+
+                               /* Cleanup */
+                               for (int i = 0; i < 20; i++) {
+                                       if ((lay_used & (1 << i)) == 0) {
+                                               BKE_collection_remove(scene, collections[i]);
+                                       }
+                               }
+
+                               /* remove bases once and for all */
+                               for (BaseLegacy *base = scene->base.first; base; base = base->next) {
+                                       id_us_min(&base->object->id);
+                               }
+                               BLI_freelistN(&scene->base);
+                               scene->basact = NULL;
+                       }
+               }
+       }
+}
+
+void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
+{
+       if (!MAIN_VERSION_ATLEAST(main, 280, 0)) {
+               if (!DNA_struct_elem_find(fd->filesdna, "Scene", "ListBase", "render_layers")) {
+                       for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+                               /* Master Collection */
+                               scene->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection");
+                               BLI_strncpy(scene->collection->name, "Master Collection", sizeof(scene->collection->name));
+                       }
+               }
+       }
+}
index 5011f9836b768a3ef21702377d6b8a54d2e5eaa0..4ddf83d306bf249100b7cd6ae78a13161a0439fb 100644 (file)
 #include "DNA_key_types.h"
 #include "DNA_lattice_types.h"
 #include "DNA_lamp_types.h"
+#include "DNA_layer_types.h"
 #include "DNA_linestyle_types.h"
 #include "DNA_meta_types.h"
 #include "DNA_mesh_types.h"
@@ -2626,10 +2627,34 @@ static void write_paint(WriteData *wd, Paint *p)
        }
 }
 
+static void write_scene_collection(WriteData *wd, SceneCollection *sc)
+{
+       writestruct(wd, DATA, SceneCollection, 1, sc);
+
+       writelist(wd, DATA, LinkData, &sc->objects);
+       writelist(wd, DATA, LinkData, &sc->filter_objects);
+
+       for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+               write_scene_collection(wd, nsc);
+       }
+}
+
+static void write_layer_collections(WriteData *wd, ListBase *lb)
+{
+       for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+               writestruct(wd, DATA, LayerCollection, 1, lc);
+
+               writelist(wd, DATA, LinkData, &lc->object_bases);
+               writelist(wd, DATA, CollectionOverride, &lc->overrides);
+
+               write_layer_collections(wd, &lc->layer_collections);
+       }
+}
+
 static void write_scenes(WriteData *wd, ListBase *scebase)
 {
        Scene *sce;
-       Base *base;
+       BaseLegacy *base;
        Editing *ed;
        Sequence *seq;
        MetaStack *ms;
@@ -2641,6 +2666,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
        ToolSettings *tos;
        FreestyleModuleConfig *fmc;
        FreestyleLineSet *fls;
+       SceneLayer *sl;
 
        sce = scebase->first;
        while (sce) {
@@ -2656,7 +2682,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
                /* direct data */
                base = sce->base.first;
                while (base) {
-                       writestruct(wd, DATA, Base, 1, base);
+                       writestruct(wd, DATA, BaseLegacy, 1, base);
                        base = base->next;
                }
 
@@ -2846,6 +2872,14 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
                write_previews(wd, sce->preview);
                write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve);
 
+               write_scene_collection(wd, sce->collection);
+
+               for (sl = sce->render_layers.first; sl; sl = sl->next) {
+                       writestruct(wd, DATA, SceneLayer, 1, sl);
+                       writelist(wd, DATA, Base, &sl->object_bases);
+                       write_layer_collections(wd, &sl->layer_collections);
+               }
+
                sce = sce->id.next;
        }
 
@@ -3167,6 +3201,9 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
                                else if (sl->spacetype == SPACE_INFO) {
                                        writestruct(wd, DATA, SpaceInfo, 1, sl);
                                }
+                               else if (sl->spacetype == SPACE_COLLECTIONS) {
+                                       writestruct(wd, DATA, SpaceCollections, 1, sl);
+                               }
 
                                sl = sl->next;
                        }
index 226f319cefd7c8542beaaef1aa1a1b06dd6569fa..ef505e5ed3e39bd813c0164434004320e0c9fa79 100644 (file)
@@ -57,6 +57,7 @@ extern "C" {
 #include "BLI_fileops.h"
 
 #include "BKE_camera.h"
+#include "BKE_collection.h"
 #include "BKE_main.h"
 #include "BKE_lamp.h"
 #include "BKE_library.h"
@@ -264,7 +265,7 @@ void DocumentImporter::finish()
                for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) {
                        Object *ob = *it;
 
-                       Base *base = BKE_scene_base_find(sce, ob);
+                       BaseLegacy *base = BKE_scene_base_find(sce, ob);
                        if (base) {
                                BLI_remlink(&sce->base, base);
                                BKE_libblock_free_us(G.main, base->object);
@@ -418,7 +419,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod
 
        Object *obn = BKE_object_copy(G.main, source_ob);
        DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
-       BKE_scene_base_add(sce, obn);
+       BKE_collection_object_add_from(sce, source_ob, obn);
 
        if (instance_node) {
                anim_importer.read_node_transform(instance_node, obn);
index 76b5114850908ebbb2e27f94bfe291c8c0902b01..7d9599c8554a175f7a162a5d990e775d583d3074 100644 (file)
@@ -66,7 +66,7 @@ EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettin
 
 bool EffectsExporter::hasEffects(Scene *sce)
 {
-       Base *base = (Base *)sce->base.first;
+       BaseLegacy *base = (BaseLegacy *)sce->base.first;
        
        while (base) {
                Object *ob = base->object;
index 9fea68fc94181a3280455d9f6342e08e4c641014..373d9dc434825b7e20858315b2087cb61e05b1aa 100644 (file)
@@ -338,7 +338,7 @@ void DepsgraphNodeBuilder::begin_build(Main *bmain) {
 }
 
 void DepsgraphNodeBuilder::build_group(Scene *scene,
-                                       Base *base,
+                                       BaseLegacy *base,
                                        Group *group)
 {
        ID *group_id = &group->id;
@@ -387,7 +387,7 @@ SubgraphDepsNode *DepsgraphNodeBuilder::build_subgraph(Group *group)
        return subgraph_node;
 }
 
-void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
+void DepsgraphNodeBuilder::build_object(Scene *scene, BaseLegacy *base, Object *ob)
 {
        const bool has_object = (ob->id.tag & LIB_TAG_DOIT);
        IDDepsNode *id_node = (has_object)
index c5035f35f6ef96b2b9dee4d65a40ae0a0a81e81c..ab66fb901609bf0fcf45ca06593319e3580df82f 100644 (file)
 
 #include "intern/depsgraph_types.h"
 
-struct Base;
+/* XXX: Temporary solution to get proper Baselegacy. */
+#include "DNA_scene_types.h"
+
+struct BaseLegacy;
 struct CacheFile;
 struct bGPdata;
 struct ListBase;
@@ -126,8 +129,8 @@ struct DepsgraphNodeBuilder {
 
        void build_scene(Main *bmain, Scene *scene);
        SubgraphDepsNode *build_subgraph(Group *group);
-       void build_group(Scene *scene, Base *base, Group *group);
-       void build_object(Scene *scene, Base *base, Object *ob);
+       void build_group(Scene *scene, BaseLegacy *base, Group *group);
+       void build_object(Scene *scene, BaseLegacy *base, Object *ob);
        void build_object_transform(Scene *scene, Object *ob);
        void build_object_constraints(Scene *scene, Object *ob);
        void build_pose_constraints(Object *ob, bPoseChannel *pchan);
index 99e6169223107b6dcfd06113985c2eb2aa8c701f..507f257292718d2f1ee57d433ff3bb519921b97d 100644 (file)
@@ -79,7 +79,7 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene)
        }
 
        /* scene objects */
-       LINKLIST_FOREACH (Base *, base, &scene->base) {
+       LINKLIST_FOREACH (BaseLegacy *, base, &scene->base) {
                Object *ob = base->object;
 
                /* object itself */
index 054e4103290b37d696dc73d687be0d833994540f..2e6fa7b5801a2e3301ee58f93c171a4bafedd428 100644 (file)
@@ -45,7 +45,7 @@
 #include "intern/nodes/deg_node.h"
 #include "intern/nodes/deg_node_operation.h"
 
-struct Base;
+struct BaseLegacy;
 struct bGPdata;
 struct CacheFile;
 struct ListBase;
index 8a3476cff45e986130a24c226a8436658484b5f9..8b68516a027cd21f40b3908ca112ec2a5d428995 100644 (file)
@@ -74,7 +74,7 @@ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene)
        }
 
        /* scene objects */
-       LINKLIST_FOREACH (Base *, base, &scene->base) {
+       LINKLIST_FOREACH (BaseLegacy *, base, &scene->base) {
                Object *ob = base->object;
 
                /* object itself */
index 1559512d713f2108fe09a56e254f769610a4316f..7e804a5bbfcfa72920a475056d796900216f9ff4 100644 (file)
@@ -47,6 +47,7 @@ if(WITH_BLENDER)
        add_subdirectory(space_graph)
        add_subdirectory(space_image)
        add_subdirectory(space_info)
+       add_subdirectory(space_collections)
        add_subdirectory(space_logic)
        add_subdirectory(space_nla)
        add_subdirectory(space_node)
index 4163cbfe1135fb2f8d2d03ef4df5ee64342cf622..ef8dabc16310d5a8903fdf23ccb2995670beb0f6 100644 (file)
@@ -631,7 +631,7 @@ static bAnimChannelType ACF_SCENE =
 
 static int acf_object_icon(bAnimListElem *ale)
 {
-       Base *base = (Base *)ale->data;
+       BaseLegacy *base = (BaseLegacy *)ale->data;
        Object *ob = base->object;
        
        /* icon depends on object-type */
@@ -666,7 +666,7 @@ static int acf_object_icon(bAnimListElem *ale)
 /* name for object */
 static void acf_object_name(bAnimListElem *ale, char *name)
 {
-       Base *base = (Base *)ale->data;
+       BaseLegacy *base = (BaseLegacy *)ale->data;
        Object *ob = base->object;
        
        /* just copy the name... */
@@ -686,7 +686,7 @@ static bool acf_object_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRN
 /* check if some setting exists for this channel */
 static bool acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
 {
-       Base *base = (Base *)ale->data;
+       BaseLegacy *base = (BaseLegacy *)ale->data;
        Object *ob = base->object;
        
        switch (setting) {
@@ -743,7 +743,7 @@ static int acf_object_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin
 /* get pointer to the setting */
 static void *acf_object_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
 {
-       Base *base = (Base *)ale->data;
+       BaseLegacy *base = (BaseLegacy *)ale->data;
        Object *ob = base->object;
        
        /* clear extra return data first */
index 117b8549712d922d88719af074150bd9608155d0..22578b6a518ec5b0b597fd5a2ec4078d2f73a6fa 100644 (file)
@@ -57,6 +57,7 @@
 #include "BKE_context.h"
 #include "BKE_mask.h"
 #include "BKE_global.h"
+#include "BKE_scene.h"
 
 #include "UI_view2d.h"
 
@@ -2682,31 +2683,31 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
                {
                        bDopeSheet *ads = (bDopeSheet *)ac->data;
                        Scene *sce = (Scene *)ads->source;
-                       Base *base = (Base *)ale->data;
+                       BaseLegacy *base = (BaseLegacy *)ale->data;
                        Object *ob = base->object;
                        AnimData *adt = ob->adt;
                        
                        /* set selection status */
                        if (selectmode == SELECT_INVERT) {
                                /* swap select */
-                               base->flag ^= SELECT;
-                               ob->flag = base->flag;
+                               base->flag_legacy ^= SELECT;
+                               BKE_scene_base_flag_sync_from_base(base);
                                
                                if (adt) adt->flag ^= ADT_UI_SELECTED;
                        }
                        else {
-                               Base *b;
+                               BaseLegacy *b;
                                
                                /* deselect all */
                                /* TODO: should this deselect all other types of channels too? */
                                for (b = sce->base.first; b; b = b->next) {
-                                       b->flag &= ~SELECT;
-                                       b->object->flag = b->flag;
+                                       b->flag_legacy &= ~SELECT;
+                                       BKE_scene_base_flag_sync_from_base(b);
                                        if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
                                }
                                
                                /* select object now */
-                               base->flag |= SELECT;
+                               base->flag_legacy |= SELECT;
                                ob->flag |= SELECT;
                                if (adt) adt->flag |= ADT_UI_SELECTED;
                        }
index 2f73eb6b71c875252fa5d47bf44704f06fc6eb00..7b6d30469a4060e2de4207845718e1999953a946 100644 (file)
@@ -601,7 +601,7 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
                        }
                        case ANIMTYPE_OBJECT:
                        {
-                               Base *base = (Base *)data;
+                               BaseLegacy *base = (BaseLegacy *)data;
                                Object *ob = base->object;
                                
                                ale->flag = ob->flag;
@@ -1683,7 +1683,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi
        
        if (ads->filterflag & ADS_FILTER_GP_3DONLY) {
                Scene *scene = (Scene *)ads->source;
-               Base *base;
+               BaseLegacy *base;
                
                /* Active scene's GPencil block first - No parent item needed... */
                if (scene->gpd) {
@@ -1714,7 +1714,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi
                                }
                                
                                /* check selection and object type filters */
-                               if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == scene->basact)*/) ) {
+                               if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag_legacy & SELECT) /*|| (base == scene->basact)*/) ) {
                                        /* only selected should be shown */
                                        continue;
                                }
@@ -2573,7 +2573,7 @@ static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, b
 }
 
 /* get animation channels from object2 */
-static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, BaseLegacy *base, int filter_mode)
 {
        ListBase tmp_data = {NULL, NULL};
        Object *ob = base->object;
@@ -2629,7 +2629,7 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data
                if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
                        /* check if filtering by selection */
                        // XXX: double-check on this - most of the time, a lot of tools need to filter out these channels!
-                       if (ANIMCHANNEL_SELOK((base->flag & SELECT))) {
+                       if (ANIMCHANNEL_SELOK((base->flag_legacy & SELECT))) {
                                /* check if filtering by active status */
                                if (ANIMCHANNEL_ACTIVEOK(ob)) {
                                        ANIMCHANNEL_NEW_CHANNEL(base, ANIMTYPE_OBJECT, ob);
@@ -2853,7 +2853,7 @@ static size_t animdata_filter_dopesheet_movieclips(bAnimContext *ac, ListBase *a
 }
 
 /* Helper for animdata_filter_dopesheet() - For checking if an object should be included or not */
-static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base, int filter_mode)
+static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, BaseLegacy *base, int filter_mode)
 {
        Object *ob = base->object;
        
@@ -2906,7 +2906,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base
        }
 
        /* check selection and object type filters */
-       if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/)) {
+       if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag_legacy & SELECT) /*|| (base == sce->basact)*/)) {
                /* only selected should be shown */
                return false;
        }
@@ -2927,28 +2927,28 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base
 /* Helper for animdata_filter_ds_sorted_bases() - Comparison callback for two Base pointers... */
 static int ds_base_sorting_cmp(const void *base1_ptr, const void *base2_ptr)
 {
-       const Base *b1 = *((const Base **)base1_ptr);
-       const Base *b2 = *((const Base **)base2_ptr);
+       const BaseLegacy *b1 = *((const BaseLegacy **)base1_ptr);
+       const BaseLegacy *b2 = *((const BaseLegacy **)base2_ptr);
        
        return strcmp(b1->object->id.name + 2, b2->object->id.name + 2);
 }
 
 /* Get a sorted list of all the bases - for inclusion in dopesheet (when drawing channels) */
-static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, Scene *scene, int filter_mode, size_t *r_usable_bases)
+static BaseLegacy **animdata_filter_ds_sorted_bases(bDopeSheet *ads, Scene *scene, int filter_mode, size_t *r_usable_bases)
 {
        /* Create an array with space for all the bases, but only containing the usable ones */
        size_t tot_bases = BLI_listbase_count(&scene->base);
        size_t num_bases = 0;
        
-       Base **sorted_bases = MEM_mallocN(sizeof(Base *) * tot_bases, "Dopesheet Usable Sorted Bases");
-       for (Base *base = scene->base.first; base; base = base->next) {
+       BaseLegacy **sorted_bases = MEM_mallocN(sizeof(BaseLegacy *) * tot_bases, "Dopesheet Usable Sorted Bases");
+       for (BaseLegacy *base = scene->base.first; base; base = base->next) {
                if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) {
                        sorted_bases[num_bases++] = base;
                }
        }
        
        /* Sort this list of pointers (based on the names) */
-       qsort(sorted_bases, num_bases, sizeof(Base *), ds_base_sorting_cmp);
+       qsort(sorted_bases, num_bases, sizeof(BaseLegacy *), ds_base_sorting_cmp);
        
        /* Return list of sorted bases */
        *r_usable_bases = num_bases;
@@ -3002,7 +3002,7 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b
        {
                /* Filter list of bases (i.e. objects), sort them, then add their contents normally... */
                // TODO: Cache the old sorted order - if the set of bases hasn't changed, don't re-sort...
-               Base **sorted_bases;
+               BaseLegacy **sorted_bases;
                size_t num_bases;
                
                sorted_bases = animdata_filter_ds_sorted_bases(ads, scene, filter_mode, &num_bases);
@@ -3022,7 +3022,7 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b
                /* Filter and add contents of each base (i.e. object) without them sorting first
                 * NOTE: This saves performance in cases where order doesn't matter
                 */
-               for (Base *base = scene->base.first; base; base = base->next) {
+               for (BaseLegacy *base = scene->base.first; base; base = base->next) {
                        if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) {
                                /* since we're still here, this object should be usable */
                                items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode);
index 823cde75334c1c00caa62546ddabc9bdc7cc8797..f4a673a888bf469a100b7479141e0ab5b272cac8 100644 (file)
@@ -1124,7 +1124,7 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool
 
        if (camera) {
                Scene *scene = CTX_data_scene(C);
-               Base *base;
+               BaseLegacy *base;
                TimeMarker *marker;
                int sel = 0;
                
index 5f675e690b940c624ea5f41e4ac36ce9bc1ff7ec..c66fb27e52593439ed296e565b271127ff2898f3 100644 (file)
@@ -938,7 +938,7 @@ void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *bl
        int filter;
        
        bAnimListElem dummychan = {NULL};
-       Base dummybase = {NULL};
+       BaseLegacy dummybase = {NULL};
        
        if (ob == NULL)
                return;
index 4571df0f077c8761601c9b691ed042ffe6033d9c..f4922fec38595ff1c574fc18dbd0b2ba8d18bc1f 100644 (file)
@@ -193,7 +193,7 @@ static short ob_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Object *o
        int ret = 0;
        
        bAnimListElem dummychan = {NULL};
-       Base dummybase = {NULL};
+       BaseLegacy dummybase = {NULL};
        
        if (ob == NULL)
                return 0;
index b39b4bd81ee038c22a13b63d241eb759361fa318..d75193a46fff50f60ae04f78f402074f5bdbc2e7 100644 (file)
@@ -37,7 +37,7 @@ struct wmOperatorType;
 struct bContext;
 struct Scene;
 struct Object;
-struct Base;
+struct BaseLegacy;
 struct bAction;
 struct bPoseChannel;
 
@@ -248,7 +248,7 @@ void armature_select_mirrored(struct bArmature *arm);
 void armature_tag_unselect(struct bArmature *arm);
 
 void *get_nearest_bone(struct bContext *C, short findunsel, int x, int y);
-void *get_bone_from_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest);
+void *get_bone_from_selectbuffer(struct Scene *scene, struct BaseLegacy *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest);
 
 int bone_looper(struct Object *ob, struct Bone *bone, void *data,
                 int (*bone_func)(struct Object *, struct Bone *, void *));
index 1c342657eecdc5f293abfee1b3c11450fdbfcd29..0dc97483dfc7122adf848c4ec3b60122e48e1d09 100644 (file)
@@ -50,6 +50,7 @@
 #include "BKE_depsgraph.h"
 #include "BKE_fcurve.h"
 #include "BKE_global.h"
+#include "BKE_layer.h"
 #include "BKE_main.h"
 #include "BKE_report.h"
 
@@ -400,7 +401,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
                        }
                        
                        /* Free the old object data */
-                       ED_base_object_free_and_unlink(bmain, scene, base);
+                       ED_base_object_free_and_unlink(bmain, scene, base->object);
                }
        }
        CTX_DATA_END;
@@ -579,6 +580,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
 {
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
+       SceneLayer *sl = CTX_data_scene_layer(C);
        Object *obedit = CTX_data_edit_object(C);
        Object *oldob, *newob;
        Base *oldbase, *newbase;
@@ -602,14 +604,18 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
        /* TODO: use context iterators for this? */
        CTX_DATA_BEGIN(C, Base *, base, visible_bases)
        {
-               if (base->object == obedit) base->flag |= SELECT;
-               else base->flag &= ~SELECT;
+               if (base->object == obedit) {
+                       ED_object_base_select(base, BA_SELECT);
+               }
+               else {
+                       ED_object_base_select(base, BA_DESELECT);
+               }
        }
        CTX_DATA_END;
        
        /* 1) store starting settings and exit editmode */
        oldob = obedit;
-       oldbase = BASACT;
+       oldbase = sl->basact;
        oldob->mode &= ~OB_MODE_POSE;
        //oldbase->flag &= ~OB_POSEMODE;
        
@@ -617,13 +623,13 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
        ED_armature_edit_free(obedit->data);
        
        /* 2) duplicate base */
-       newbase = ED_object_add_duplicate(bmain, scene, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
+       newbase = ED_object_add_duplicate(bmain, scene, sl, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
        DAG_relations_tag_update(bmain);
 
        newob = newbase->object;
-       newbase->flag &= ~SELECT;
-       
-       
+       newbase->flag &= ~BASE_SELECTED;
+
+
        /* 3) remove bones that shouldn't still be around on both armatures */
        separate_armature_bones(oldob, 1);
        separate_armature_bones(newob, 0);
index e9946abba0b7fa45162639f0895aeb3e5d75dacf..1f994a7f13e79514c8ff834be2cb7532e6158b03 100644 (file)
@@ -74,7 +74,7 @@ Bone *get_indexed_bone(Object *ob, int index)
 
 /* See if there are any selected bones in this buffer */
 /* only bones from base are checked on */
-void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest)
+void *get_bone_from_selectbuffer(Scene *scene, BaseLegacy *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest)
 {
        Object *obedit = scene->obedit; // XXX get from context
        Bone *bone;
index cc4c1809fbc6eb2feb72feb94cb18ed8d0556599..caa18b91775861375c8c94791e1b0d7a23eb7f31 100644 (file)
@@ -142,7 +142,7 @@ void BIF_makeListTemplates(const bContext *C)
        Object *obedit = CTX_data_edit_object(C);
        Scene *scene = CTX_data_scene(C);
        ToolSettings *ts = CTX_data_tool_settings(C);
-       Base *base;
+       BaseLegacy *base;
        int index = 0;
 
        if (TEMPLATES_HASH != NULL) {
index 44470c1f827bce9baf8212c61a3cdd245b404cee..903d309cb1fbc30e2a72d172d46c002e77e780df 100644 (file)
@@ -132,7 +132,7 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select)
 
 /* called from editview.c, for mode-less pose selection */
 /* assumes scene obact and basact is still on old situation */
-int ED_do_pose_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits,
+int ED_do_pose_selectbuffer(Scene *scene, BaseLegacy *base, unsigned int *buffer, short hits,
                             bool extend, bool deselect, bool toggle, bool do_nearest)
 {
        Object *ob = base->object;
index e9fd5fb5a438a29ddf8425bb0e485ad75f2c5851..6b5a5d81d3258e70c167100a1586bbacb399c3ea 100644 (file)
@@ -50,6 +50,7 @@
 #include "BKE_fcurve.h"
 #include "BKE_global.h"
 #include "BKE_key.h"
+#include "BKE_layer.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
 #include "BKE_report.h"
@@ -1270,6 +1271,7 @@ static int separate_exec(bContext *C, wmOperator *op)
 {
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
+       SceneLayer *sl = CTX_data_scene_layer(C);
        Object *oldob, *newob;
        Base *oldbase, *newbase;
        Curve *oldcu, *newcu;
@@ -1297,7 +1299,7 @@ static int separate_exec(bContext *C, wmOperator *op)
        }
 
        /* 2. duplicate the object and data */
-       newbase = ED_object_add_duplicate(bmain, scene, oldbase, 0); /* 0 = fully linked */
+       newbase = ED_object_add_duplicate(bmain, scene, sl, oldbase, 0); /* 0 = fully linked */
        DAG_relations_tag_update(bmain);
 
        newob = newbase->object;
@@ -6024,7 +6026,7 @@ int join_curve_exec(bContext *C, wmOperator *op)
                                        }
                                }
                        
-                               ED_base_object_free_and_unlink(bmain, scene, base);
+                               ED_base_object_free_and_unlink(bmain, scene, base->object);
                        }
                }
        }
index 57e731874b4e299e6b48ee70feb8802c55af0844..d86091aaa77ff9aac39dee69f9be5509dd662caa 100644 (file)
@@ -420,6 +420,7 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const
 {
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
+       SceneLayer *sl = CTX_data_scene_layer(C);
        Curve *cu;
        Object *obedit;
        Base *base;
@@ -429,8 +430,8 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const
        int a;
        float rot[3] = {0.f, 0.f, 0.f};
        
-       obedit = BKE_object_add(bmain, scene, OB_FONT, NULL);
-       base = scene->basact;
+       obedit = BKE_object_add(bmain, scene, sl, OB_FONT, NULL);
+       base = sl->basact;
 
        /* seems to assume view align ? TODO - look into this, could be an operator option */
        ED_object_base_init_transform(C, base, NULL, rot);
index d0f68c4b8f332b62ea2ffd053abd0bb48d3c052e..505114869ac584fbdb06f8f0569829534d43beb9 100644 (file)
@@ -1128,7 +1128,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
        Object *ob;
        Curve *cu;
        Nurb *nu = NULL;
-       Base *base_orig = BASACT, *base_new = NULL;
+       BaseLegacy *base_orig = BASACT, *base_new = NULL;
        float minmax_weights[2] = {1.0f, 0.0f};
        
        /* camera framing */
@@ -1217,7 +1217,8 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
        
        /* set the layer and select */
        base_new->lay  = ob->lay  = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene);
-       base_new->flag = ob->flag = base_new->flag | SELECT;
+       base_new->flag_legacy |= SELECT;
+       BKE_scene_base_flag_sync_from_base(base_new);
 }
 
 /* --- */
index 76e85f20c3604869b3bbc237bc3a61104127d75f..e3b6b7482278eeb3e77be3c73d6eba558f5e0d8b 100644 (file)
@@ -204,7 +204,7 @@ bGPdata *ED_gpencil_data_get_active(const bContext *C)
 // XXX: this should be removed... We really shouldn't duplicate logic like this!
 bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, View3D *v3d)
 {
-       Base *base = scene->basact;
+       BaseLegacy *base = scene->basact;
        bGPdata *gpd = NULL;
        /* We have to make sure active object is actually visible and selected, else we must use default scene gpd,
         * to be consistent with ED_gpencil_data_get_active's behavior.
index 35d38bf4ca12e795f97a6be598ede5b3d8af9ef9..96532f748e43facbdd73219bb20a7b4646146498 100644 (file)
@@ -49,6 +49,7 @@ struct ColorManagedDisplaySettings;
 
 void fdrawline(float x1, float y1, float x2, float y2); /* DEPRECATED */
 void fdrawbox(float x1, float y1, float x2, float y2); /* DEPRECATED */
+void fdrawbox_filled(float x1, float y1, float x2, float y2);
 void sdrawline(int x1, int y1, int x2, int y2); /* DEPRECATED */
 void sdrawbox(int x1, int y1, int x2, int y2); /* DEPRECATED */
 
index 7ad61671b1b07e243171eaba0e76ac15c25571fa..3bde01a1bdd6c9a6be10f443f5e6c6d9176cb837 100644 (file)
@@ -35,7 +35,7 @@ extern "C" {
 #endif
 
 struct bArmature;
-struct Base;
+struct BaseLegacy;
 struct bContext;
 struct Bone;
 struct bPoseChannel;
@@ -44,6 +44,7 @@ struct ListBase;
 struct MeshDeformModifierData;
 struct DerivedMesh;
 struct Object;
+struct Base;
 struct ReportList;
 struct Scene;
 struct ViewContext;
@@ -130,7 +131,7 @@ void ED_armature_ebone_listbase_temp_clear(struct ListBase *lb);
 void ED_armature_deselect_all(struct Object *obedit);
 void ED_armature_deselect_all_visible(struct Object *obedit);
 
-int ED_do_pose_selectbuffer(struct Scene *scene, struct Base *base, unsigned int *buffer,
+int ED_do_pose_selectbuffer(struct Scene *scene, struct BaseLegacy *base, unsigned int *buffer,
                             short hits, bool extend, bool deselect, bool toggle, bool do_nearest);
 bool ED_armature_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
 int join_armature_exec(struct bContext *C, struct wmOperator *op);
index 04ff5692717ae7eb9c6c2f02f4f2971272e58ee3..4d79a42e64e2afacab0c6658569ec4245fe49894 100644 (file)
 extern "C" {
 #endif
 
-struct Base;
+struct BaseLegacy;
 struct EnumPropertyItem;
 struct ID;
 struct Main;
 struct ModifierData;
 struct Object;
+struct Base;
 struct ReportList;
 struct Scene;
+struct SceneLayer;
 struct bConstraint;
 struct bContext;
 struct bPoseChannel;
@@ -53,6 +55,7 @@ struct wmOperatorType;
 struct PointerRNA;
 struct PropertyRNA;
 struct EnumPropertyItem;
+struct LayerTree;
 
 /* object_edit.c */
 struct Object *ED_object_context(struct bContext *C);               /* context.object */
@@ -89,7 +92,6 @@ bool ED_object_parent_set(struct ReportList *reports, struct Main *bmain, struct
                           struct Object *par, int partype, const bool xmirror, const bool keep_transform,
                           const int vert_par[3]);
 void ED_object_parent_clear(struct Object *ob, const int type);
-struct Base *ED_object_scene_link(struct Scene *scene, struct Object *ob);
 
 void ED_keymap_proportional_cycle(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap);
 void ED_keymap_proportional_obmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap);
@@ -98,14 +100,20 @@ void ED_keymap_proportional_editmode(struct wmKeyConfig *keyconf, struct wmKeyMa
                                      const bool do_connected);
 
 /* send your own notifier for select! */
-void ED_base_object_select(struct Base *base, short mode);
+void ED_base_object_select(struct BaseLegacy *base, short mode);
 /* includes notifier */
-void ED_base_object_activate(struct bContext *C, struct Base *base);
+void ED_base_object_activate(struct bContext *C, struct BaseLegacy *base);
+
+void ED_object_base_select(struct Base *base, short mode);
+void ED_object_base_activate(struct bContext *C, struct Base *base);
 
-void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Base *base);
+void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *ob);
+
+void ED_base_object_sync_from_base(struct BaseLegacy *base, struct Object *ob);
+void ED_base_object_sync_from_object(struct BaseLegacy *base, struct Object *ob);
 
 /* single object duplicate, if (dupflag == 0), fully linked, else it uses the flags given */
-struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct Base *base, int dupflag);
+struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct SceneLayer *sl, struct Base *base, int dupflag);
 
 void ED_object_parent(struct Object *ob, struct Object *parent, const int type, const char *substr);
 
@@ -191,7 +199,7 @@ void ED_object_modifier_clear(struct Main *bmain, struct Object *ob);
 int ED_object_modifier_move_down(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
 int ED_object_modifier_move_up(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
 int ED_object_modifier_convert(struct ReportList *reports, struct Main *bmain, struct Scene *scene,
-                               struct Object *ob, struct ModifierData *md);
+                               struct SceneLayer *sl, struct Object *ob, struct ModifierData *md);
 int ED_object_modifier_apply(struct ReportList *reports, struct Scene *scene,
                              struct Object *ob, struct ModifierData *md, int mode);
 int ED_object_modifier_copy(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
index f5f66a07aea795193bcec9f85199cdfe4ab7168d..01be63919bed13b4f036ab179c649adc05c1dac6 100644 (file)
@@ -162,6 +162,7 @@ int     ED_operator_image_active(struct bContext *C);
 int     ED_operator_nla_active(struct bContext *C);
 int     ED_operator_logic_active(struct bContext *C);
 int     ED_operator_info_active(struct bContext *C);
+int     ED_operator_collections_active(struct bContext *C);
 int     ED_operator_console_active(struct bContext *C);
 
 
index d268c578cf20ba813e1deb9fc346a9dc63739770..b754e1ba20fe53c3b4cb8b336fe8e926b5b774de 100644 (file)
@@ -58,6 +58,7 @@ void ED_spacetype_logic(void);
 void ED_spacetype_console(void);
 void ED_spacetype_userpref(void);
 void ED_spacetype_clip(void);
+void ED_spacetype_collections(void);
 
 /* calls for instancing and freeing spacetype static data 
  * called in WM_init_exit */
index ebd2a3dcb7af3e697699915cf109f6bcb40eecf0..898eecd3e42fa76cf4509ec933222f4ec787eddc 100644 (file)
@@ -109,7 +109,7 @@ enum TfmMode {
 bool calculateTransformCenter(struct bContext *C, int centerMode, float cent3d[3], float cent2d[2]);
 
 struct TransInfo;
-struct Base;
+struct BaseLegacy;
 struct Scene;
 struct Object;
 struct wmOperator;
index 53253c1274f7420ee069fe1a7764184beb278e3d..3bbc7617745558a4f5bc670428e456ad24aa4256 100644 (file)
@@ -37,7 +37,7 @@ struct BMEdge;
 struct BMFace;
 struct BMVert;
 struct BPoint;
-struct Base;
+struct BaseLegacy;
 struct BezTriple;
 struct BoundBox;
 struct EditBone;
@@ -187,7 +187,7 @@ void pose_foreachScreenBone(
 void ED_view3d_project_float_v2_m4(const struct ARegion *ar, const float co[3], float r_co[2], float mat[4][4]);
 void ED_view3d_project_float_v3_m4(const struct ARegion *ar, const float co[3], float r_co[3], float mat[4][4]);
 
-eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *base);
+eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct BaseLegacy *base);
 
 /* *** short *** */
 eV3DProjStatus ED_view3d_project_short_ex(const struct ARegion *ar, float perspmat[4][4], const bool is_local,
@@ -353,7 +353,7 @@ struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
         int alpha_mode, int samples, bool full_samples, const char *viewname,
         struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
 
-struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
+struct BaseLegacy *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
 void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip);
 void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]);
 bool ED_view3d_quat_from_axis_view(const char view, float quat[4]);
index 286ac6054e2d2f44b43e4697adf370cd6b8a8c8d..8caf772ca9a9e3d4a79e32cb1c54703fb3414f90 100644 (file)
@@ -212,6 +212,9 @@ enum {
        UI_BUT_ALIGN_STITCH_TOP  = (1 << 18),
        UI_BUT_ALIGN_STITCH_LEFT = (1 << 19),
        UI_BUT_ALIGN_ALL         = (UI_BUT_ALIGN | UI_BUT_ALIGN_STITCH_TOP | UI_BUT_ALIGN_STITCH_LEFT),
+
+       /* Another hack, in some rare cases we don't want any text margin */
+       UI_BUT_TEXT_NO_MARGIN    = (1 << 20),
 };
 
 /* scale fixed button widths by this to account for DPI */
index 945ac1b6db9e4befe3fceae32f6e062e0da8446a..f08c46af8a64e51ee840eb712a7058f86a44ec52 100644 (file)
@@ -83,5 +83,6 @@ struct PreviewImage *UI_icon_to_preview(int icon_id);
 
 int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big);
 int UI_idcode_icon_get(const int idcode);
+int UI_colorset_icon_get(const int set_idx);
 
 #endif /*  __UI_INTERFACE_ICONS_H__ */
index 0a21c89e692d7482325684f24416ecd50edc6db6..a50c0f5a4f4c7f207c9e3daa79090e39fc279203 100644 (file)
@@ -597,7 +597,7 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int
                                const int mval[2] = {
                                    mx - ar->winrct.xmin,
                                    my - ar->winrct.ymin};
-                               Base *base;
+                               BaseLegacy *base;
 
                                CTX_wm_area_set(C, sa);
                                CTX_wm_region_set(C, ar);
index 0573e8d9c94797027425c6849f975588e1027b50..70bfd30c2d809790a8f9e1ec748a0137f29f50ed 100644 (file)
@@ -1385,6 +1385,14 @@ int UI_idcode_icon_get(const int idcode)
        }
 }
 
+/**
+ * \param set_idx: A value from #rna_enum_color_sets_items.
+ */
+int UI_colorset_icon_get(const int set_idx)
+{
+       return (set_idx < 1) ? ICON_NONE : VICO_COLORSET_01_VEC - 1 + set_idx;
+}
+
 static void icon_draw_at_size(
         float x, float y, int icon_id, float aspect, float alpha,
         enum eIconSizes size, const bool nocreate)
index b580d394dd0c7e56b570e30c5ba204782e8f905b..84b022ca44017873eb47cfe92923b57017159ee0 100644 (file)
@@ -1576,7 +1576,10 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
                }
        }
 
-       if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) {
+       if (but->drawflag & UI_BUT_TEXT_NO_MARGIN) {
+               /* skip */
+       }
+       else if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) {
                rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
        }
        else if ((but->drawflag & UI_BUT_TEXT_RIGHT)) {
index 76b8f348c9c2556c04d47d573c6ab886a35c3014..8bd671873becbb8d741961064ca97493c0e39a89 100644 (file)
@@ -167,6 +167,9 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
                                case SPACE_CLIP:
                                        ts = &btheme->tclip;
                                        break;
+                               case SPACE_COLLECTIONS:
+                                       ts = &btheme->tcollections;
+                                       break;
                                default:
                                        ts = &btheme->tv3d;
                                        break;
@@ -1208,6 +1211,11 @@ void ui_theme_init_default(void)
        rgba_char_args_set(btheme->tclip.strip_select, 0xff, 0x8c, 0x00, 0xff);
        btheme->tclip.handle_vertex_size = 5;
        ui_theme_space_init_handles_color(&btheme->tclip);
+
+       /* space collection manager */
+       btheme->tcollections = btheme->tv3d;
+       rgba_char_args_set_fl(btheme->tcollections.back,    0.42, 0.42, 0.42, 1.0);
+       rgba_char_args_set(btheme->tcollections.hilite, 255, 140, 25, 255);  /* selected files */
 }
 
 void ui_style_init_default(void)
@@ -2859,7 +2867,11 @@ void init_userdef_do_versions(void)
         * (keep this block even if it becomes empty).
         */
        {
-               
+               for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
+                       btheme->tcollections = btheme->tv3d;
+                       rgba_char_args_set_fl(btheme->tcollections.back,    0.42, 0.42, 0.42, 1.0);
+                       rgba_char_args_set(btheme->tcollections.hilite, 255, 140, 25, 255);  /* selected files */
+               }
        }
 
        if (U.pixelsize == 0.0f)
index 8f004bcf72b3bf090d7eef0a21a2141ca1817f41..549bcd4c4b66da80892afd51291f6b344013da4b 100644 (file)
@@ -47,6 +47,7 @@
 #include "BLI_rand.h"
 #include "BLI_sort_utils.h"
 
+#include "BKE_layer.h"
 #include "BKE_material.h"
 #include "BKE_context.h"
 #include "BKE_deform.h"
@@ -3010,7 +3011,7 @@ enum {
        MESH_SEPARATE_LOOSE    = 2,
 };
 
-static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static Base *mesh_separate_tagged(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old)
 {
        Base *base_new;
        Object *obedit = base_old->object;
@@ -3031,11 +3032,11 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe
        CustomData_bmesh_init_pool(&bm_new->ldata, bm_mesh_allocsize_default.totloop, BM_LOOP);
        CustomData_bmesh_init_pool(&bm_new->pdata, bm_mesh_allocsize_default.totface, BM_FACE);
 
-       base_new = ED_object_add_duplicate(bmain, scene, base_old, USER_DUP_MESH);
+       base_new = ED_object_add_duplicate(bmain, scene, sl, base_old, USER_DUP_MESH);
        /* DAG_relations_tag_update(bmain); */ /* normally would call directly after but in this case delay recalc */
        assign_matarar(base_new->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */
 
-       ED_base_object_select(base_new, BA_SELECT);
+       ED_object_base_select(base_new, BA_SELECT);
 
        BMO_op_callf(bm_old, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
                     "duplicate geom=%hvef dest=%p", BM_ELEM_TAG, bm_new);
@@ -3057,7 +3058,7 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe
        return base_new;
 }
 
-static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static bool mesh_separate_selected(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old)
 {
        /* we may have tags from previous operators */
        BM_mesh_elem_hflag_disable_all(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, false);
@@ -3065,7 +3066,7 @@ static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BM
        /* sel -> tag */
        BM_mesh_elem_hflag_enable_test(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, true, false, BM_ELEM_SELECT);
 
-       return (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL);
+       return (mesh_separate_tagged(bmain, scene, sl, base_old, bm_old) != NULL);
 }
 
 /* flush a hflag to from verts to edges/faces */
@@ -3164,7 +3165,7 @@ static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const
        }
 }
 
-static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static bool mesh_separate_material(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old)
 {
        BMFace *f_cmp, *f;
        BMIter iter;
@@ -3205,7 +3206,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM
                }
 
                /* Move selection into a separate object */
-               base_new = mesh_separate_tagged(bmain, scene, base_old, bm_old);
+               base_new = mesh_separate_tagged(bmain, scene, sl, base_old, bm_old);
                if (base_new) {
                        mesh_separate_material_assign_mat_nr(bmain, base_new->object, mat_nr);
                }
@@ -3216,7 +3217,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM
        return result;
 }
 
-static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static bool mesh_separate_loose(Main *bmain, Scene *scene, SceneLayer *sl, Base *base_old, BMesh *bm_old)
 {
        int i;
        BMEdge *e;
@@ -3269,7 +3270,7 @@ static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh
                bm_mesh_hflag_flush_vert(bm_old, BM_ELEM_TAG);
 
                /* Move selection into a separate object */
-               result |= (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL);
+               result |= (mesh_separate_tagged(bmain, scene, sl, base_old, bm_old) != NULL);
        }
 
        return result;
@@ -3279,6 +3280,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
 {
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
+       SceneLayer *sl = CTX_data_scene_layer(C);
        const int type = RNA_enum_get(op->ptr, "type");
        int retval = 0;
        
@@ -3299,13 +3301,13 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
                /* editmode separate */
                switch (type) {
                        case MESH_SEPARATE_SELECTED:
-                               retval = mesh_separate_selected(bmain, scene, base, em->bm);
+                           retval = mesh_separate_selected(bmain, scene, sl, base, em->bm);
                                break;
                        case MESH_SEPARATE_MATERIAL:
-                               retval = mesh_separate_material(bmain, scene, base, em->bm);
+                           retval = mesh_separate_material(bmain, scene, sl, base, em->bm);
                                break;
                        case MESH_SEPARATE_LOOSE:
-                               retval = mesh_separate_loose(bmain, scene, base, em->bm);
+                           retval = mesh_separate_loose(bmain, scene, sl, base, em->bm);
                                break;
                        default:
                                BLI_assert(0);
@@ -3340,10 +3342,10 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
 
                                        switch (type) {
                                                case MESH_SEPARATE_MATERIAL:
-                                                       retval_iter = mesh_separate_material(bmain, scene, base_iter, bm_old);
+                                                   retval_iter = mesh_separate_material(bmain, scene, sl, base_iter, bm_old);
                                                        break;
                                                case MESH_SEPARATE_LOOSE:
-                                                       retval_iter = mesh_separate_loose(bmain, scene, base_iter, bm_old);
+                                                   retval_iter = mesh_separate_loose(bmain, scene, sl, base_iter, bm_old);
                                                        break;
                                                default:
                                                        BLI_assert(0);
index 772bb1bd3082bd611d1af288ccc1fa770f3d0db0..036d084a91cfeb0b0c1216ed5d6666c45aceb055 100644 (file)
@@ -551,7 +551,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
        View3D *v3d = CTX_wm_view3d(C);
-       Base *base;
+       BaseLegacy *base;
        Image *ima = NULL;
        Mesh *me;
        Object *obedit;
index b95921964eb256e69f27349fd5abf98a078ce4e2..443f2f0baa8f1f79654b875aa1b8e6a27895d0ce 100644 (file)
@@ -326,7 +326,7 @@ static bool buildNavMesh(const RecastData *recastParams, int nverts, float *vert
 }
 
 static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, struct recast_polyMeshDetail *dmesh,
-                                  Base *base, unsigned int lay)
+                                  BaseLegacy *base, unsigned int lay)
 {
        float co[3], rot[3];
        BMEditMesh *em;
@@ -461,14 +461,15 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
 static int navmesh_create_exec(bContext *C, wmOperator *op)
 {
        Scene *scene = CTX_data_scene(C);
+       SceneLayer *sl = CTX_data_scene_layer(C);
        LinkNode *obs = NULL;
-       Base *navmeshBase = NULL;
+       BaseLegacy *navmeshBase = NULL;
 
        CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
        {
                if (base->object->type == OB_MESH) {
                        if (base->object->body_type == OB_BODY_TYPE_NAVMESH) {
-                               if (!navmeshBase || base == scene->basact) {
+                               if (!navmeshBase || base == sl->basact) {
                                        navmeshBase = base;
                                }
                        }
index 743efb246ab37c2acb5eafd77aaaba6f1767bf28..c8b0955c70fe1f34294a31f18810bae667fcc6d1 100644 (file)
@@ -526,7 +526,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
 
                        /* free base, now that data is merged */
                        if (base->object != ob) {
-                               ED_base_object_free_and_unlink(bmain, scene, base);
+                               ED_base_object_free_and_unlink(bmain, scene, base->object);
                        }
                }
        }
index 02b2d8492b431a1fdf516509ebfe566cb8c8c3c7..e7223f6f1eeaebe820f204debb613bdd7e34f568 100644 (file)
@@ -63,6 +63,7 @@
 #include "BKE_animsys.h"
 #include "BKE_armature.h"
 #include "BKE_camera.h"
+#include "BKE_collection.h"
 #include "BKE_context.h"
 #include "BKE_curve.h"
 #include "BKE_depsgraph.h"
@@ -73,6 +74,7 @@
 #include "BKE_group.h"
 #include "BKE_lamp.h"
 #include "BKE_lattice.h"
+#include "BKE_layer.h"
 #include "BKE_library.h"
 #include "BKE_library_query.h"
 #include "BKE_library_remap.h"
@@ -405,10 +407,11 @@ Object *ED_object_add_type(
         bContext *C,
         int type, const char *name,
         const float loc[3], const float rot[3],
-        bool enter_editmode, unsigned int layer)
+        bool enter_editmode, unsigned int UNUSED(layer))
 {
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
+       SceneLayer *sl = CTX_data_scene_layer(C);
        Object *ob;
 
        /* for as long scene has editmode... */
@@ -416,13 +419,12 @@ Object *ED_object_add_type(
                ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);  /* freedata, and undo */
 
        /* deselects all, sets scene->basact */
-       ob = BKE_object_add(bmain, scene, type, name);
-       BASACT->lay = ob->lay = layer;
+       ob = BKE_object_add(bmain, scene, sl, type, name);
        /* editor level activate, notifiers */
-       ED_base_object_activate(C, BASACT);
+       ED_object_base_activate(C, sl->basact);
 
        /* more editor stuff */
-       ED_object_base_init_transform(C, BASACT, loc, rot);
+       ED_object_base_init_transform(C, sl->basact, loc, rot);
 
        /* Ignore collisions by default for non-mesh objects */
        if (type != OB_MESH) {
@@ -830,7 +832,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv
 {
        Scene *scene = CTX_data_scene(C);
 
-       Base *base = NULL;
+       BaseLegacy *base = NULL;
        Image *ima = NULL;
        Object *ob = NULL;
 
@@ -1109,21 +1111,19 @@ static void object_delete_check_glsl_update(Object *ob)
 
 /* remove base from a specific scene */
 /* note: now unlinks constraints as well */
-void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Base *base)
+void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
 {
-       if (BKE_library_ID_is_indirectly_used(bmain, base->object) &&
-           ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0)
+       if (BKE_library_ID_is_indirectly_used(bmain, ob) &&
+           ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0)
        {
                /* We cannot delete indirectly used object... */
                printf("WARNING, undeletable object '%s', should have been catched before reaching this function!",
-                      base->object->id.name + 2);
+                      ob->id.name + 2);
                return;
        }
 
-       BKE_scene_base_unlink(scene, base);
-       object_delete_check_glsl_update(base->object);
-       BKE_libblock_free_us(bmain, base->object);
-       MEM_freeN(base);
+       object_delete_check_glsl_update(ob);
+       BKE_collections_object_remove(bmain, scene, ob, true);
        DAG_id_type_tag(bmain, ID_OB);
 }
 
@@ -1139,56 +1139,46 @@ static int object_delete_exec(bContext *C, wmOperator *op)
        if (CTX_data_edit_object(C)) 
                return OPERATOR_CANCELLED;
 
-       CTX_DATA_BEGIN (C, Base *, base, selected_bases)
+       CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
        {
-               const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, base->object);
-               if (base->object->id.tag & LIB_TAG_INDIRECT) {
+               const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, ob);
+               if (ob->id.tag & LIB_TAG_INDIRECT) {
                        /* Can this case ever happen? */
-                       BKE_reportf(op->reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", base->object->id.name + 2);
+                       BKE_reportf(op->reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2);
                        continue;
                }
-               else if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) {
+               else if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
                        BKE_reportf(op->reports, RPT_WARNING,
                                "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
-                               base->object->id.name + 2, scene->id.name + 2);
+                               ob->id.name + 2, scene->id.name + 2);
                        continue;
                }
                /* remove from Grease Pencil parent */
                for (bGPdata *gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) {
                        for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
                                if (gpl->parent != NULL) {
-                                       Object *ob = gpl->parent;
-                                       Object *curob = base->object;
-                                       if (ob == curob) {
+                                       if (gpl->parent == ob) {
                                                gpl->parent = NULL;
                                        }
                                }
                        }
                }
 
-               /* deselect object -- it could be used in other scenes */
-               base->object->flag &= ~SELECT;
-
                /* remove from current scene only */
-               ED_base_object_free_and_unlink(bmain, scene, base);
+               ED_base_object_free_and_unlink(bmain, scene, ob);
                changed = true;
 
                if (use_global) {
                        Scene *scene_iter;
-                       Base *base_other;
-
                        for (scene_iter = bmain->scene.first; scene_iter; scene_iter = scene_iter->id.next) {
                                if (scene_iter != scene && !ID_IS_LINKED_DATABLOCK(scene_iter)) {
-                                       base_other = BKE_scene_base_find(scene_iter, base->object);
-                                       if (base_other) {
-                                               if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) {
-                                                       BKE_reportf(op->reports, RPT_WARNING,
-                                                                   "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
-                                                                   base->object->id.name + 2, scene_iter->id.name + 2);
-                                                       break;
-                                               }
-                                               ED_base_object_free_and_unlink(bmain, scene_iter, base_other);
+                                       if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
+                                               BKE_reportf(op->reports, RPT_WARNING,
+                                                           "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
+                                                           ob->id.name + 2, scene_iter->id.name + 2);
+                                               break;
                                        }
+                                       ED_base_object_free_and_unlink(bmain, scene_iter, ob);
                                }
                        }
                }
@@ -1329,6 +1319,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
                                        const bool use_hierarchy)
 {
        Main *bmain = CTX_data_main(C);
+       SceneLayer *sl = CTX_data_scene_layer(C);
        ListBase *lb;
        DupliObject *dob;
        GHash *dupli_gh = NULL, *parent_gh = NULL;
@@ -1360,12 +1351,10 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
                 */
                if (ob->mat == NULL)&n