Merge branch 'master' into blender2.8
[blender.git] / source / blender / blenkernel / intern / scene.c
index 5933aaccd66290a9eaa8a0ae4091a0d334f72d58..420c1a3ebabfcff2609e5cf0371ef64aa29fc95c 100644 (file)
@@ -67,8 +67,8 @@
 #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"
 #include "BKE_fcurve.h"
 #include "BKE_freestyle.h"
@@ -78,6 +78,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"
@@ -95,6 +96,8 @@
 #include "BKE_world.h"
 
 #include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
 
 #include "RE_engine.h"
 
 
 const char *RE_engine_id_BLENDER_RENDER = "BLENDER_RENDER";
 const char *RE_engine_id_BLENDER_GAME = "BLENDER_GAME";
+const char *RE_engine_id_BLENDER_CLAY = "BLENDER_CLAY";
+const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE";
 const char *RE_engine_id_CYCLES = "CYCLES";
 
 void free_avicodecdata(AviCodecData *acd)
@@ -154,13 +159,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 +272,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 */
@@ -247,6 +305,39 @@ 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;
+               }
+
+               IDPropertyTemplate val = {0};
+               scen->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
        }
 
        /* copy color management settings */
@@ -360,6 +451,12 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
 
        BKE_previewimg_id_copy(&scen->id, &sce->id);
 
+       if (type != SCE_COPY_NEW) {
+               if (sce->collection_properties) {
+                       IDP_MergeGroup(scen->collection_properties, sce->collection_properties, true);
+               }
+       }
+
        return scen;
 }
 
@@ -465,7 +562,7 @@ void BKE_scene_free(Scene *sce)
                sce->toolsettings = NULL;
        }
        
-       DAG_scene_free(sce);
+       DEG_scene_graph_free(sce);
        if (sce->depsgraph)
                DEG_graph_free(sce->depsgraph);
        
@@ -478,6 +575,23 @@ 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;
+
+       /* Runtime Engine Data */
+       if (sce->collection_properties) {
+               IDP_FreeProperty(sce->collection_properties);
+               MEM_freeN(sce->collection_properties);
+               sce->collection_properties = NULL;
+       }
 }
 
 void BKE_scene_init(Scene *sce)
@@ -827,6 +941,16 @@ 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));
+
+       IDPropertyTemplate val = {0};
+       sce->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+       BKE_layer_collection_engine_settings_create(sce->collection_properties);
+
+       BKE_scene_layer_add(sce, "Render Layer");
 }
 
 Scene *BKE_scene_add(Main *bmain, const char *name)
@@ -842,9 +966,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)) {
@@ -855,9 +979,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));
 }
 
 /**
@@ -868,11 +992,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);
@@ -896,7 +1019,7 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
 
        /* sort baselist for scene and sets */
        for (sce = scene; sce; sce = sce->set)
-               DAG_scene_relations_rebuild(bmain, sce);
+               DEG_scene_relations_rebuild(bmain, sce);
 
        /* copy layers and flags from bases to objects */
        for (base = scene->base.first; base; base = base->next) {
@@ -904,13 +1027,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) */
 }
@@ -931,7 +1048,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;
        
@@ -1013,7 +1130,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;
 
@@ -1032,7 +1149,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. */
@@ -1057,9 +1174,22 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
        return iter->phase;
 }
 
+Scene *BKE_scene_find_from_collection(const Main *bmain, const SceneCollection *scene_collection)
+{
+       for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+               for (SceneLayer *layer = scene->render_layers.first; layer; layer = layer->next) {
+                       if (BKE_scene_layer_has_collection(layer, scene_collection)) {
+                               return scene;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
 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)
@@ -1161,47 +1291,54 @@ 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;
 }
 
+/* deprecated, use BKE_scene_layer_base_deselect_all */
 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;
 }
@@ -1255,109 +1392,6 @@ void BKE_scene_frame_set(struct Scene *scene, double cfra)
        scene->r.cfra = (int)intpart;
 }
 
-#ifdef WITH_LEGACY_DEPSGRAPH
-/* drivers support/hacks 
- *  - this method is called from scene_update_tagged_recursive(), so gets included in viewport + render
- *     - these are always run since the depsgraph can't handle non-object data
- *     - these happen after objects are all done so that we can read in their final transform values,
- *       though this means that objects can't refer to scene info for guidance...
- */
-static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene)
-{
-       SceneRenderLayer *srl;
-       float ctime = BKE_scene_frame_get(scene);
-       
-       /* scene itself */
-       if (scene->adt && scene->adt->drivers.first) {
-               BKE_animsys_evaluate_animdata(scene, &scene->id, scene->adt, ctime, ADT_RECALC_DRIVERS);
-       }
-
-       /* world */
-       /* TODO: what about world textures? but then those have nodes too... */
-       if (scene->world) {
-               ID *wid = (ID *)scene->world;
-               AnimData *adt = BKE_animdata_from_id(wid);
-               
-               if (adt && adt->drivers.first)
-                       BKE_animsys_evaluate_animdata(scene, wid, adt, ctime, ADT_RECALC_DRIVERS);
-       }
-       
-       /* nodes */
-       if (scene->nodetree) {
-               ID *nid = (ID *)scene->nodetree;
-               AnimData *adt = BKE_animdata_from_id(nid);
-               
-               if (adt && adt->drivers.first)
-                       BKE_animsys_evaluate_animdata(scene, nid, adt, ctime, ADT_RECALC_DRIVERS);
-       }
-
-       /* world nodes */
-       if (scene->world && scene->world->nodetree) {
-               ID *nid = (ID *)scene->world->nodetree;
-               AnimData *adt = BKE_animdata_from_id(nid);
-               
-               if (adt && adt->drivers.first)
-                       BKE_animsys_evaluate_animdata(scene, nid, adt, ctime, ADT_RECALC_DRIVERS);
-       }
-
-       /* freestyle */
-       for (srl = scene->r.layers.first; srl; srl = srl->next) {
-               FreestyleConfig *config = &srl->freestyleConfig;
-               FreestyleLineSet *lineset;
-
-               for (lineset = config->linesets.first; lineset; lineset = lineset->next) {
-                       if (lineset->linestyle) {
-                               ID *lid = &lineset->linestyle->id;
-                               AnimData *adt = BKE_animdata_from_id(lid);
-
-                               if (adt && adt->drivers.first)
-                                       BKE_animsys_evaluate_animdata(scene, lid, adt, ctime, ADT_RECALC_DRIVERS);
-                       }
-               }
-       }
-}
-
-/* deps hack - do extra recalcs at end */
-static void scene_depsgraph_hack(EvaluationContext *eval_ctx, Scene *scene, Scene *scene_parent)
-{
-       Base *base;
-               
-       scene->customdata_mask = scene_parent->customdata_mask;
-       
-       /* sets first, we allow per definition current scene to have
-        * dependencies on sets, but not the other way around. */
-       if (scene->set)
-               scene_depsgraph_hack(eval_ctx, scene->set, scene_parent);
-       
-       for (base = scene->base.first; base; base = base->next) {
-               Object *ob = base->object;
-               
-               if (ob->depsflag) {
-                       int recalc = 0;
-                       // printf("depshack %s\n", ob->id.name + 2);
-                       
-                       if (ob->depsflag & OB_DEPS_EXTRA_OB_RECALC)
-                               recalc |= OB_RECALC_OB;
-                       if (ob->depsflag & OB_DEPS_EXTRA_DATA_RECALC)
-                               recalc |= OB_RECALC_DATA;
-                       
-                       ob->recalc |= recalc;
-                       BKE_object_handle_update(eval_ctx, scene_parent, ob);
-                       
-                       if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) {
-                               GroupObject *go;
-                               
-                               for (go = ob->dup_group->gobject.first; go; go = go->next) {
-                                       if (go->ob)
-                                               go->ob->recalc |= recalc;
-                               }
-                               BKE_group_handle_recalc_and_update(eval_ctx, scene_parent, ob, ob->dup_group);
-                       }
-               }
-       }
-}
-#endif  /* WITH_LEGACY_DEPSGRAPH */
-
 /* That's like really a bummer, because currently animation data for armatures
  * might want to use pose, and pose might be missing on the object.
  * This happens when changing visible layers, which leads to situations when
@@ -1373,7 +1407,7 @@ static void scene_depsgraph_hack(EvaluationContext *eval_ctx, Scene *scene, Scen
 static void scene_armature_depsgraph_workaround(Main *bmain)
 {
        Object *ob;
-       if (BLI_listbase_is_empty(&bmain->armature) || !DAG_id_type_tagged(bmain, ID_OB)) {
+       if (BLI_listbase_is_empty(&bmain->armature) || !DEG_id_type_tagged(bmain, ID_OB)) {
                return;
        }
        for (ob = bmain->object.first; ob; ob = ob->id.next) {
@@ -1386,372 +1420,25 @@ static void scene_armature_depsgraph_workaround(Main *bmain)
 }
 #endif
 
-#ifdef WITH_LEGACY_DEPSGRAPH
-static void scene_rebuild_rbw_recursive(Scene *scene, float ctime)
-{
-       if (scene->set)
-               scene_rebuild_rbw_recursive(scene->set, ctime);
-
-       if (BKE_scene_check_rigidbody_active(scene))
-               BKE_rigidbody_rebuild_world(scene, ctime);
-}
-
-static void scene_do_rb_simulation_recursive(Scene *scene, float ctime)
-{
-       if (scene->set)
-               scene_do_rb_simulation_recursive(scene->set, ctime);
-
-       if (BKE_scene_check_rigidbody_active(scene))
-               BKE_rigidbody_do_simulation(scene, ctime);
-}
-#endif
-
-/* Used to visualize CPU threads activity during threaded object update,
- * would pollute STDERR with whole bunch of timing information which then
- * could be parsed and nicely visualized.
- */
-#ifdef WITH_LEGACY_DEPSGRAPH
-#  undef DETAILED_ANALYSIS_OUTPUT
-#else
-/* ALWAYS KEEY DISABLED! */
-#  undef DETAILED_ANALYSIS_OUTPUT
-#endif
-
-/* Mballs evaluation uses BKE_scene_base_iter_next which calls
- * duplilist for all objects in the scene. This leads to conflict
- * accessing and writing same data from multiple threads.
- *
- * Ideally Mballs shouldn't do such an iteration and use DAG
- * queries instead. For the time being we've got new DAG
- * let's keep it simple and update mballs in a single thread.
- */
-#define MBALL_SINGLETHREAD_HACK
-
-#ifdef WITH_LEGACY_DEPSGRAPH
-typedef struct StatisicsEntry {
-       struct StatisicsEntry *next, *prev;
-       Object *object;
-       double start_time;
-       double duration;
-} StatisicsEntry;
-
-typedef struct ThreadedObjectUpdateState {
-       /* TODO(sergey): We might want this to be per-thread object. */
-       EvaluationContext *eval_ctx;
-       Scene *scene;
-       Scene *scene_parent;
-       double base_time;
-
-#ifdef MBALL_SINGLETHREAD_HACK
-       bool has_mballs;
-#endif
-
-       /* Execution statistics */
-       bool has_updated_objects;
-       ListBase *statistics;
-} ThreadedObjectUpdateState;
-
-static void scene_update_object_add_task(void *node, void *user_data);
-
-static void scene_update_all_bases(EvaluationContext *eval_ctx, Scene *scene, Scene *scene_parent)
-{
-       Base *base;
-
-       for (base = scene->base.first; base; base = base->next) {
-               Object *object = base->object;
-
-               BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world, true);
-
-               if (object->dup_group && (object->transflag & OB_DUPLIGROUP))
-                       BKE_group_handle_recalc_and_update(eval_ctx, scene_parent, object, object->dup_group);
-
-               /* always update layer, so that animating layers works (joshua july 2010) */
-               /* XXX commented out, this has depsgraph issues anyway - and this breaks setting scenes
-                * (on scene-set, the base-lay is copied to ob-lay (ton nov 2012) */
-               // base->lay = ob->lay;
-       }
-}
-
-static void scene_update_object_func(TaskPool * __restrict pool, void *taskdata, int threadid)
-{
-/* Disable print for now in favor of summary statistics at the end of update. */
-#define PRINT if (false) printf
-
-       ThreadedObjectUpdateState *state = (ThreadedObjectUpdateState *) BLI_task_pool_userdata(pool);
-       void *node = taskdata;
-       Object *object = DAG_get_node_object(node);
-       EvaluationContext *eval_ctx = state->eval_ctx;
-       Scene *scene = state->scene;
-       Scene *scene_parent = state->scene_parent;
-
-#ifdef MBALL_SINGLETHREAD_HACK
-       if (object && object->type == OB_MBALL) {
-               state->has_mballs = true;
-       }
-       else
-#endif
-       if (object) {
-               double start_time = 0.0;
-               bool add_to_stats = false;
-
-               if (G.debug & G_DEBUG_DEPSGRAPH) {
-                       if (object->recalc & OB_RECALC_ALL) {
-                               printf("Thread %d: update object %s\n", threadid, object->id.name);
-                       }
-
-                       start_time = PIL_check_seconds_timer();
-
-                       if (object->recalc & OB_RECALC_ALL) {
-                               state->has_updated_objects = true;
-                               add_to_stats = true;
-                       }
-               }
-
-               /* We only update object itself here, dupli-group will be updated
-                * separately from main thread because of we've got no idea about
-                * dependencies inside the group.
-                */
-               BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world, false);
-
-               /* Calculate statistics. */
-               if (add_to_stats) {
-                       StatisicsEntry *entry;
-
-                       entry = MEM_mallocN(sizeof(StatisicsEntry), "update thread statistics");
-                       entry->object = object;
-                       entry->start_time = start_time;
-                       entry->duration = PIL_check_seconds_timer() - start_time;
-
-                       BLI_addtail(&state->statistics[threadid], entry);
-               }
-       }
-       else {
-               PRINT("Threda %d: update node %s\n", threadid,
-                     DAG_get_node_name(scene, node));
-       }
-
-       /* Update will decrease child's valency and schedule child with zero valency. */
-       DAG_threaded_update_handle_node_updated(node, scene_update_object_add_task, pool);
-
-#undef PRINT
-}
-
-static void scene_update_object_add_task(void *node, void *user_data)
-{
-       TaskPool *task_pool = user_data;
-
-       BLI_task_pool_push(task_pool, scene_update_object_func, node, false, TASK_PRIORITY_LOW);
-}
-
-static void print_threads_statistics(ThreadedObjectUpdateState *state)
-{
-       int i, tot_thread;
-       double finish_time;
-
-       if ((G.debug & G_DEBUG_DEPSGRAPH) == 0) {
-               return;
-       }
-
-#ifdef DETAILED_ANALYSIS_OUTPUT
-       if (state->has_updated_objects) {
-               tot_thread = BLI_system_thread_count();
-
-               fprintf(stderr, "objects update base time %f\n", state->base_time);
-
-               for (i = 0; i < tot_thread; i++) {
-                       StatisicsEntry *entry;
-                       for (entry = state->statistics[i].first;
-                            entry;
-                            entry = entry->next)
-                       {
-                               fprintf(stderr, "thread %d object %s start_time %f duration %f\n",
-                                       i, entry->object->id.name + 2,
-                                       entry->start_time, entry->duration);
-                       }
-                       BLI_freelistN(&state->statistics[i]);
-               }
-       }
-#else
-       finish_time = PIL_check_seconds_timer();
-       tot_thread = BLI_system_thread_count();
-       int total_objects = 0;
-
-       for (i = 0; i < tot_thread; i++) {
-               int thread_total_objects = 0;
-               double thread_total_time = 0.0;
-               StatisicsEntry *entry;
-
-               if (state->has_updated_objects) {
-                       /* Don't pollute output if no objects were updated. */
-                       for (entry = state->statistics[i].first;
-                            entry;
-                            entry = entry->next)
-                       {
-                               thread_total_objects++;
-                               thread_total_time += entry->duration;
-                       }
-
-                       printf("Thread %d: total %d objects in %f sec.\n",
-                              i,
-                              thread_total_objects,
-                              thread_total_time);
-
-                       for (entry = state->statistics[i].first;
-                            entry;
-                            entry = entry->next)
-                       {
-                               printf("  %s in %f sec\n", entry->object->id.name + 2, entry->duration);
-                       }
-
-                       total_objects += thread_total_objects;
-               }
-
-               BLI_freelistN(&state->statistics[i]);
-       }
-       if (state->has_updated_objects) {
-               printf("Scene updated %d objects in %f sec\n",
-                      total_objects,
-                      finish_time - state->base_time);
-       }
-#endif
-}
-
-static bool scene_need_update_objects(Main *bmain)
-{
-       return
-               /* Object datablocks themselves (for OB_RECALC_OB) */
-               DAG_id_type_tagged(bmain, ID_OB) ||
-
-               /* Objects data datablocks (for OB_RECALC_DATA) */
-               DAG_id_type_tagged(bmain, ID_ME)  ||  /* Mesh */
-               DAG_id_type_tagged(bmain, ID_CU)  ||  /* Curve */
-               DAG_id_type_tagged(bmain, ID_MB)  ||  /* MetaBall */
-               DAG_id_type_tagged(bmain, ID_LA)  ||  /* Lamp */
-               DAG_id_type_tagged(bmain, ID_LT)  ||  /* Lattice */
-               DAG_id_type_tagged(bmain, ID_CA)  ||  /* Camera */
-               DAG_id_type_tagged(bmain, ID_KE)  ||  /* KE */
-               DAG_id_type_tagged(bmain, ID_SPK) ||  /* Speaker */
-               DAG_id_type_tagged(bmain, ID_AR);     /* Armature */
-}
-
-static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Scene *scene_parent)
-{
-       TaskScheduler *task_scheduler;
-       TaskPool *task_pool;
-       ThreadedObjectUpdateState state;
-       bool need_singlethread_pass;
-       bool need_free_scheduler;
-
-       /* Early check for whether we need to invoke all the task-based
-        * things (spawn new ppol, traverse dependency graph and so on).
-        *
-        * Basically if there's no ID datablocks tagged for update which
-        * corresponds to object->recalc flags (which are checked in
-        * BKE_object_handle_update() then we do nothing here.
-        */
-       if (!scene_need_update_objects(bmain)) {
-               return;
-       }
-
-       state.eval_ctx = eval_ctx;
-       state.scene = scene;
-       state.scene_parent = scene_parent;
-
-       if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) {
-               task_scheduler = BLI_task_scheduler_create(1);
-               need_free_scheduler = true;
-       }
-       else {
-               task_scheduler = BLI_task_scheduler_get();
-               need_free_scheduler = false;
-       }
-
-       /* Those are only needed when blender is run with --debug argument. */
-       if (G.debug & G_DEBUG_DEPSGRAPH) {
-               const int tot_thread = BLI_task_scheduler_num_threads(task_scheduler);
-               state.statistics = MEM_callocN(tot_thread * sizeof(*state.statistics),
-                                              "scene update objects stats");
-               state.has_updated_objects = false;
-               state.base_time = PIL_check_seconds_timer();
-       }
-
-#ifdef MBALL_SINGLETHREAD_HACK
-       state.has_mballs = false;
-#endif
-
-       task_pool = BLI_task_pool_create(task_scheduler, &state);
-
-       DAG_threaded_update_begin(scene, scene_update_object_add_task, task_pool);
-       BLI_task_pool_work_and_wait(task_pool);
-       BLI_task_pool_free(task_pool);
-
-       if (G.debug & G_DEBUG_DEPSGRAPH) {
-               print_threads_statistics(&state);
-               MEM_freeN(state.statistics);
-       }
-
-       /* We do single thread pass to update all the objects which are in cyclic dependency.
-        * Such objects can not be handled by a generic DAG traverse and it's really tricky
-        * to detect whether cycle could be solved or not.
-        *
-        * In this situation we simply update all remaining objects in a single thread and
-        * it'll happen in the same exact order as it was in single-threaded DAG.
-        *
-        * We couldn't use threaded update for objects which are in cycle because they might
-        * access data of each other which is being re-evaluated.
-        *
-        * Also, as was explained above, for now we also update all the mballs in single thread.
-        *
-        *                                                                   - sergey -
-        */
-       need_singlethread_pass = DAG_is_acyclic(scene) == false;
-#ifdef MBALL_SINGLETHREAD_HACK
-       need_singlethread_pass |= state.has_mballs;
-#endif
-
-       if (need_singlethread_pass) {
-               scene_update_all_bases(eval_ctx, scene, scene_parent);
-       }
-
-       if (need_free_scheduler) {
-               BLI_task_scheduler_free(task_scheduler);
-       }
-}
-
-static void scene_update_tagged_recursive(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Scene *scene_parent)
-{
-       scene->customdata_mask = scene_parent->customdata_mask;
-
-       /* sets first, we allow per definition current scene to have
-        * dependencies on sets, but not the other way around. */
-       if (scene->set)
-               scene_update_tagged_recursive(eval_ctx, bmain, scene->set, scene_parent);
-
-       /* scene objects */
-       scene_update_objects(eval_ctx, bmain, scene, scene_parent);
-
-       /* scene drivers... */
-       scene_update_drivers(bmain, scene);
-
-       /* update masking curves */
-       BKE_mask_update_scene(bmain, scene);
-       
-}
-#endif  /* WITH_LEGACY_DEPSGRAPH */
-
 static bool check_rendered_viewport_visible(Main *bmain)
 {
        wmWindowManager *wm = bmain->wm.first;
        wmWindow *window;
        for (window = wm->windows.first; window != NULL; window = window->next) {
                bScreen *screen = window->screen;
+               Scene *scene = screen->scene;
                ScrArea *area;
+               RenderEngineType *type = RE_engines_find(scene->r.engine);
+               if ((type->draw_engine != NULL) || (type->render_to_view == NULL)) {
+                       continue;
+               }
+               const bool use_legacy = (type->flag & RE_USE_LEGACY_PIPELINE) != 0;
                for (area = screen->areabase.first; area != NULL; area = area->next) {
                        View3D *v3d = area->spacedata.first;
                        if (area->spacetype != SPACE_VIEW3D) {
                                continue;
                        }
-                       if (v3d->drawtype == OB_RENDER) {
+                       if (v3d->drawtype == OB_RENDER || !use_legacy) {
                                return true;
                        }
                }
@@ -1780,7 +1467,7 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
                        if (check_rendered_viewport_visible(bmain)) {
                                BMesh *bm = mesh->edit_btmesh->bm;
                                BM_mesh_bm_to_me(bm, mesh, (&(struct BMeshToMeshParams){0}));
-                               DAG_id_tag_update(&mesh->id, 0);
+                               DEG_id_tag_update(&mesh->id, 0);
                        }
                }
        }
@@ -1789,24 +1476,16 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
 void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *scene)
 {
        Scene *sce_iter;
-#ifdef WITH_LEGACY_DEPSGRAPH
-       bool use_new_eval = !DEG_depsgraph_use_legacy();
-#endif
 
        /* keep this first */
        BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_PRE);
 
        /* (re-)build dependency graph if needed */
        for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) {
-               DAG_scene_relations_update(bmain, sce_iter);
+               DEG_scene_relations_update(bmain, sce_iter);
                /* Uncomment this to check if graph was properly tagged for update. */
 #if 0
-#ifdef WITH_LEGACY_DEPSGRAPH
-               if (use_new_eval)
-#endif
-               {
-                       DAG_scene_relations_validate(bmain, sce_iter);
-               }
+               DEG_scene_relations_validate(bmain, sce_iter);
 #endif
        }
 
@@ -1814,7 +1493,7 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc
        prepare_mesh_for_viewport_render(bmain, scene);
 
        /* flush recalc flags to dependencies */
-       DAG_ids_flush_tagged(bmain);
+       DEG_ids_flush_tagged(bmain);
 
        /* removed calls to quick_cache, see pointcache.c */
        
@@ -1829,17 +1508,9 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc
         *
         * in the future this should handle updates for all datablocks, not
         * only objects and scenes. - brecht */
-#ifdef WITH_LEGACY_DEPSGRAPH
-       if (!use_new_eval) {
-               scene_update_tagged_recursive(eval_ctx, bmain, scene, scene);
-       }
-       else
-#endif
-       {
-               DEG_evaluate_on_refresh(eval_ctx, scene->depsgraph, scene);
-               /* TODO(sergey): This is to beocme a node in new depsgraph. */
-               BKE_mask_update_scene(bmain, scene);
-       }
+       DEG_evaluate_on_refresh(eval_ctx, scene->depsgraph, scene);
+       /* TODO(sergey): This is to beocme a node in new depsgraph. */
+       BKE_mask_update_scene(bmain, scene);
 
        /* update sound system animation (TODO, move to depsgraph) */
        BKE_sound_update_scene(bmain, scene);
@@ -1853,71 +1524,23 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc
                        BKE_animsys_evaluate_animdata(scene, &scene->id, adt, ctime, 0);
        }
 
-       /* Extra call here to recalc material animation.
-        *
-        * Need to do this so changing material settings from the graph/dopesheet
-        * will update stuff in the viewport.
-        */
-#ifdef WITH_LEGACY_DEPSGRAPH
-       if (!use_new_eval && DAG_id_type_tagged(bmain, ID_MA)) {
-               Material *material;
-               float ctime = BKE_scene_frame_get(scene);
-
-               for (material = bmain->mat.first;
-                    material;
-                    material = material->id.next)
-               {
-                       AnimData *adt = BKE_animdata_from_id(&material->id);
-                       if (adt && (adt->recalc & ADT_RECALC_ANIM))
-                               BKE_animsys_evaluate_animdata(scene, &material->id, adt, ctime, 0);
-               }
-       }
-
-       /* Also do the same for node trees. */
-       if (!use_new_eval && DAG_id_type_tagged(bmain, ID_NT)) {
-               float ctime = BKE_scene_frame_get(scene);
-
-               FOREACH_NODETREE(bmain, ntree, id)
-               {
-                       AnimData *adt = BKE_animdata_from_id(&ntree->id);
-                       if (adt && (adt->recalc & ADT_RECALC_ANIM))
-                               BKE_animsys_evaluate_animdata(scene, &ntree->id, adt, ctime, 0);
-               }
-               FOREACH_NODETREE_END
-       }
-#endif
-
        /* notify editors and python about recalc */
        BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_POST);
 
        /* Inform editors about possible changes. */
-       DAG_ids_check_recalc(bmain, scene, false);
+       DEG_ids_check_recalc(bmain, scene, false);
 
        /* clear recalc flags */
-       DAG_ids_clear_recalc(bmain);
+       DEG_ids_clear_recalc(bmain);
 }
 
 /* applies changes right away, does all sets too */
-void BKE_scene_update_for_newframe(EvaluationContext *eval_ctx, Main *bmain, Scene *sce, unsigned int lay)
-{
-       BKE_scene_update_for_newframe_ex(eval_ctx, bmain, sce, lay, false);
-}
-
-void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, Scene *sce, unsigned int lay, bool do_invisible_flush)
+void BKE_scene_update_for_newframe(EvaluationContext *eval_ctx, Main *bmain, Scene *sce)
 {
        float ctime = BKE_scene_frame_get(sce);
        Scene *sce_iter;
-#ifdef DETAILED_ANALYSIS_OUTPUT
-       double start_time = PIL_check_seconds_timer();
-#endif
-#ifdef WITH_LEGACY_DEPSGRAPH
-       bool use_new_eval = !DEG_depsgraph_use_legacy();
-#else
-       /* TODO(sergey): Pass to evaluation routines instead of storing layer in the graph? */
-       (void) do_invisible_flush;
-#endif
 
-       DAG_editors_update_pre(bmain, sce, true);
+       DEG_editors_update_pre(bmain, sce, true);
 
        /* keep this first */
        BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_PRE);
@@ -1926,37 +1549,14 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain,
        /* update animated image textures for particles, modifiers, gpu, etc,
         * call this at the start so modifiers with textures don't lag 1 frame */
        BKE_image_update_frame(bmain, sce->r.cfra);
-       
-#ifdef WITH_LEGACY_DEPSGRAPH
-       /* rebuild rigid body worlds before doing the actual frame update
-        * this needs to be done on start frame but animation playback usually starts one frame later
-        * we need to do it here to avoid rebuilding the world on every simulation change, which can be very expensive
-        */
-       if (!use_new_eval) {
-               scene_rebuild_rbw_recursive(sce, ctime);
-       }
-#endif
-       
+
        BKE_sound_set_cfra(sce->r.cfra);
-       
+
        /* clear animation overrides */
        /* XXX TODO... */
 
        for (sce_iter = sce; sce_iter; sce_iter = sce_iter->set)
-               DAG_scene_relations_update(bmain, sce_iter);
-
-#ifdef WITH_LEGACY_DEPSGRAPH
-       if (!use_new_eval) {
-               /* flush recalc flags to dependencies, if we were only changing a frame
-                * this would not be necessary, but if a user or a script has modified
-                * some datablock before BKE_scene_update_tagged was called, we need the flush */
-               DAG_ids_flush_tagged(bmain);
-
-               /* Following 2 functions are recursive
-                * so don't call within 'scene_update_tagged_recursive' */
-               DAG_scene_update_flags(bmain, sce, lay, true, do_invisible_flush);   // only stuff that moves or needs display still
-       }
-#endif
+               DEG_scene_relations_update(bmain, sce_iter);
 
        BKE_mask_evaluate_all_masks(bmain, ctime, true);
 
@@ -1967,67 +1567,27 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain,
        scene_armature_depsgraph_workaround(bmain);
 #endif
 
-       /* All 'standard' (i.e. without any dependencies) animation is handled here,
-        * with an 'local' to 'macro' order of evaluation. This should ensure that
-        * settings stored nestled within a hierarchy (i.e. settings in a Texture block
-        * can be overridden by settings from Scene, which owns the Texture through a hierarchy
-        * such as Scene->World->MTex/Texture) can still get correctly overridden.
-        */
-#ifdef WITH_LEGACY_DEPSGRAPH
-       if (!use_new_eval) {
-               BKE_animsys_evaluate_all_animation(bmain, sce, ctime);
-               /*...done with recursive funcs */
-       }
-#endif
-
        /* clear "LIB_TAG_DOIT" flag from all materials, to prevent infinite recursion problems later
         * when trying to find materials with drivers that need evaluating [#32017] 
         */
        BKE_main_id_tag_idcode(bmain, ID_MA, LIB_TAG_DOIT, false);
        BKE_main_id_tag_idcode(bmain, ID_LA, LIB_TAG_DOIT, false);
 
-       /* run rigidbody sim */
-       /* NOTE: current position is so that rigidbody sim affects other objects, might change in the future */
-#ifdef WITH_LEGACY_DEPSGRAPH
-       if (!use_new_eval) {
-               scene_do_rb_simulation_recursive(sce, ctime);
-       }
-#endif
-       
        /* BKE_object_handle_update() on all objects, groups and sets */
-#ifdef WITH_LEGACY_DEPSGRAPH
-       if (use_new_eval) {
-               DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay);
-       }
-       else {
-               scene_update_tagged_recursive(eval_ctx, bmain, sce, sce);
-       }
-#else
-       DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay);
-#endif
+       DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime);
 
        /* update sound system animation (TODO, move to depsgraph) */
        BKE_sound_update_scene(bmain, sce);
 
-#ifdef WITH_LEGACY_DEPSGRAPH
-       if (!use_new_eval) {
-               scene_depsgraph_hack(eval_ctx, sce, sce);
-       }
-#endif
-
        /* notify editors and python about recalc */
        BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_SCENE_UPDATE_POST);
        BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_POST);
 
        /* Inform editors about possible changes. */
-       DAG_ids_check_recalc(bmain, sce, true);
+       DEG_ids_check_recalc(bmain, sce, true);
 
        /* clear recalc flags */
-       DAG_ids_clear_recalc(bmain);
-
-#ifdef DETAILED_ANALYSIS_OUTPUT
-       fprintf(stderr, "frame update start_time %f duration %f\n", start_time, PIL_check_seconds_timer() - start_time);
-#endif
+       DEG_ids_clear_recalc(bmain);
 }
 
 /* return default layer, also used to patch old files */
@@ -2082,15 +1642,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);
                }
        }
 
@@ -2177,21 +1729,37 @@ float get_render_aosss_error(const RenderData *r, float error)
                return error;
 }
 
-/* helper function for the SETLOOPER macro */
+/**
+  * Helper function for the SETLOOPER macro
+  *
+  * It iterates over the bases of the active layer and then the bases
+  * of the active layer of the background (set) scenes recursively.
+  */
 Base *_setlooper_base_step(Scene **sce_iter, Base *base)
 {
        if (base && base->next) {
                /* common case, step to the next */
                return base->next;
        }
-       else if (base == NULL && (*sce_iter)->base.first) {
+       else if (base == NULL) {
                /* first time looping, return the scenes first base */
-               return (Base *)(*sce_iter)->base.first;
+
+               /* for the first loop we should get the layer from context */
+               SceneLayer *sl = BKE_scene_layer_context_active((*sce_iter));
+
+               if (sl->object_bases.first) {
+                       return (Base *)sl->object_bases.first;
+               }
+               /* no base on this scene layer */
+               goto next_set;
        }
        else {
+next_set:
                /* reached the end, get the next base in the set */
                while ((*sce_iter = (*sce_iter)->set)) {
-                       base = (Base *)(*sce_iter)->base.first;
+                       SceneLayer *sl = BKE_scene_layer_render_active((*sce_iter));
+                       base = (Base *)sl->object_bases.first;
+
                        if (base) {
                                return base;
                        }
@@ -2236,23 +1804,60 @@ bool BKE_scene_uses_blender_game(const Scene *scene)
        return STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME);
 }
 
-void BKE_scene_base_flag_to_objects(struct Scene *scene)
+bool BKE_scene_uses_blender_eevee(const Scene *scene)
+{
+       return STREQ(scene->r.engine, RE_engine_id_BLENDER_EEVEE);
+}
+
+void BKE_scene_base_flag_to_objects(SceneLayer *sl)
 {
-       Base *base = scene->base.first;
+       Base *base = sl->object_bases.first;
 
        while (base) {
-               base->object->flag = base->flag;
+               BKE_scene_object_base_flag_sync_from_base(base);
                base = base->next;
        }
 }
 
-void BKE_scene_base_flag_from_objects(struct Scene *scene)
+void BKE_scene_base_flag_sync_from_base(BaseLegacy *base)
 {
-       Base *base = scene->base.first;
+       BKE_scene_object_base_flag_sync_from_base(base);
+}
 
-       while (base) {
-               base->flag = base->object->flag;
-               base = base->next;
+void BKE_scene_base_flag_sync_from_object(BaseLegacy *base)
+{
+       BKE_scene_object_base_flag_sync_from_object(base);
+}
+
+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;
+
+       if ((base->flag & BASE_SELECTED) != 0) {
+               ob->flag |= SELECT;
+       }
+       else {
+               ob->flag &= ~SELECT;
+       }
+}
+
+void BKE_scene_object_base_flag_sync_from_object(Base *base)
+{
+       Object *ob = base->object;
+       base->flag = ob->flag;
+
+       if ((ob->flag & SELECT) != 0) {
+               base->flag |= BASE_SELECTED;
+               BLI_assert((base->flag & BASE_SELECTABLED) != 0);
+       }
+       else {
+               base->flag &= ~BASE_SELECTED;
        }
 }