Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / object / object_add.c
index 1bba15c93c1171829e5b86c6e4ef65c5cee847e1..c481a62acb786498045df48b8a0d67954d31feac 100644 (file)
 
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "MEM_guardedalloc.h"
 
 #include "DNA_anim_types.h"
 #include "DNA_camera_types.h"
+#include "DNA_collection_types.h"
 #include "DNA_curve_types.h"
-#include "DNA_group_types.h"
 #include "DNA_lamp_types.h"
 #include "DNA_key_types.h"
 #include "DNA_material_types.h"
@@ -45,9 +46,9 @@
 #include "DNA_object_fluidsim_types.h"
 #include "DNA_object_force_types.h"
 #include "DNA_object_types.h"
+#include "DNA_lightprobe_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_vfont_types.h"
-#include "DNA_actuator_types.h"
 #include "DNA_gpencil_types.h"
 
 #include "BLI_utildefines.h"
 #include "BKE_animsys.h"
 #include "BKE_armature.h"
 #include "BKE_camera.h"
+#include "BKE_collection.h"
 #include "BKE_context.h"
 #include "BKE_constraint.h"
 #include "BKE_curve.h"
-#include "BKE_depsgraph.h"
-#include "BKE_DerivedMesh.h"
 #include "BKE_displist.h"
 #include "BKE_effect.h"
 #include "BKE_font.h"
-#include "BKE_group.h"
+#include "BKE_gpencil.h"
+#include "BKE_key.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"
-#include "BKE_key.h"
+#include "BKE_lightprobe.h"
 #include "BKE_main.h"
 #include "BKE_material.h"
 #include "BKE_mball.h"
 #include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
 #include "BKE_nla.h"
 #include "BKE_object.h"
 #include "BKE_particle.h"
 #include "BKE_report.h"
-#include "BKE_sca.h"
 #include "BKE_scene.h"
 #include "BKE_screen.h"
 #include "BKE_speaker.h"
 
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
+
 #include "RNA_access.h"
 #include "RNA_define.h"
 #include "RNA_enum_types.h"
 
 #include "ED_armature.h"
 #include "ED_curve.h"
+#include "ED_gpencil.h"
 #include "ED_mball.h"
 #include "ED_mesh.h"
 #include "ED_node.h"
 
 #include "UI_resources.h"
 
-#include "GPU_material.h"
-
 #include "object_intern.h"
 
 /* this is an exact copy of the define in rna_lamp.c
  * kept here because of linking order.
  * Icons are only defined here */
-const EnumPropertyItem rna_enum_lamp_type_items[] = {
-       {LA_LOCAL, "POINT", ICON_LAMP_POINT, "Point", "Omnidirectional point light source"},
-       {LA_SUN, "SUN", ICON_LAMP_SUN, "Sun", "Constant direction parallel ray light source"},
-       {LA_SPOT, "SPOT", ICON_LAMP_SPOT, "Spot", "Directional cone light source"},
-       {LA_HEMI, "HEMI", ICON_LAMP_HEMI, "Hemi", "180 degree constant light source"},
-       {LA_AREA, "AREA", ICON_LAMP_AREA, "Area", "Directional area light source"},
+const EnumPropertyItem rna_enum_light_type_items[] = {
+       {LA_LOCAL, "POINT", ICON_LIGHT_POINT, "Point", "Omnidirectional point light source"},
+       {LA_SUN, "SUN", ICON_LIGHT_SUN, "Sun", "Constant direction parallel ray light source"},
+       {LA_SPOT, "SPOT", ICON_LIGHT_SPOT, "Spot", "Directional cone light source"},
+       {LA_AREA, "AREA", ICON_LIGHT_AREA, "Area", "Directional area light source"},
        {0, NULL, 0, NULL, NULL}
 };
 
@@ -146,17 +150,22 @@ static const EnumPropertyItem field_type_items[] = {
        {0, NULL, 0, NULL, NULL}
 };
 
+static EnumPropertyItem lightprobe_type_items[] = {
+       {LIGHTPROBE_TYPE_CUBE, "CUBEMAP", ICON_LIGHTPROBE_CUBEMAP, "Reflection Cubemap",
+     "Reflection probe with spherical or cubic attenuation"},
+       {LIGHTPROBE_TYPE_PLANAR, "PLANAR", ICON_LIGHTPROBE_PLANAR, "Reflection Plane",
+     "Planar reflection probe"},
+       {LIGHTPROBE_TYPE_GRID, "GRID", ICON_LIGHTPROBE_GRID, "Irradiance Volume",
+     "Irradiance probe to capture diffuse indirect lighting"},
+       {0, NULL, 0, NULL, NULL}
+};
+
 /************************** Exported *****************************/
 
 void ED_object_location_from_view(bContext *C, float loc[3])
 {
-       View3D *v3d = CTX_wm_view3d(C);
-       Scene *scene = CTX_data_scene(C);
-       const float *cursor;
-
-       cursor = ED_view3d_cursor3d_get(scene, v3d);
-
-       copy_v3_v3(loc, cursor);
+       const Scene *scene = CTX_data_scene(C);
+       copy_v3_v3(loc, scene->cursor.location);
 }
 
 void ED_object_rotation_from_quat(float rot[3], const float viewquat[4], const char align_axis)
@@ -207,6 +216,7 @@ void ED_object_base_init_transform(bContext *C, Base *base, const float loc[3],
 {
        Object *ob = base->object;
        Scene *scene = CTX_data_scene(C);
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
 
        if (!scene) return;
 
@@ -216,7 +226,7 @@ void ED_object_base_init_transform(bContext *C, Base *base, const float loc[3],
        if (rot)
                copy_v3_v3(ob->rot, rot);
 
-       BKE_object_where_is_calc(scene, ob);
+       BKE_object_where_is_calc(depsgraph, scene, ob);
 }
 
 /* Uses context to figure out transform for primitive.
@@ -261,7 +271,12 @@ static void view_align_update(struct Main *UNUSED(main), struct Scene *UNUSED(sc
        RNA_struct_idprops_unset(ptr, "rotation");
 }
 
-void ED_object_add_unit_props(wmOperatorType *ot)
+void ED_object_add_unit_props_size(wmOperatorType *ot)
+{
+       RNA_def_float_distance(ot->srna, "size", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Size", "", 0.001, 100.00);
+}
+
+void ED_object_add_unit_props_radius(wmOperatorType *ot)
 {
        RNA_def_float_distance(ot->srna, "radius", 1.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.001, 100.00);
 }
@@ -287,22 +302,18 @@ void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode)
                                      "Rotation", "Rotation for the newly added object",
                                      DEG2RADF(-360.0f), DEG2RADF(360.0f));
        RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-
-       prop = RNA_def_boolean_layer_member(ot->srna, "layers", 20, NULL, "Layer", "");
-       RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
 }
 
 void ED_object_add_mesh_props(wmOperatorType *ot)
 {
-       RNA_def_boolean(ot->srna, "calc_uvs", false, "Generate UVs", "Generate a default UV map");
+       RNA_def_boolean(ot->srna, "calc_uvs", true, "Generate UVs", "Generate a default UV map");
 }
 
-bool ED_object_add_generic_get_opts(bContext *C, wmOperator *op, const char view_align_axis,
-                                    float loc[3], float rot[3],
-                                    bool *enter_editmode, unsigned int *layer, bool *is_view_aligned)
+bool ED_object_add_generic_get_opts(
+        bContext *C, wmOperator *op, const char view_align_axis,
+        float loc[3], float rot[3],
+        bool *enter_editmode, ushort *local_view_bits, bool *is_view_aligned)
 {
-       View3D *v3d = CTX_wm_view3d(C);
-       unsigned int _layer;
        PropertyRNA *prop;
 
        /* Switch to Edit mode? optional prop */
@@ -319,35 +330,11 @@ bool ED_object_add_generic_get_opts(bContext *C, wmOperator *op, const char view
                }
        }
 
-       /* Get layers! */
-       {
-               int a;
-               bool layer_values[20];
-               if (!layer)
-                       layer = &_layer;
-
-               prop = RNA_struct_find_property(op->ptr, "layers");
-               if (RNA_property_is_set(op->ptr, prop)) {
-                       RNA_property_boolean_get_array(op->ptr, prop, layer_values);
-                       *layer = 0;
-                       for (a = 0; a < 20; a++) {
-                               if (layer_values[a])
-                                       *layer |= (1 << a);
-                       }
-               }
-               else {
-                       Scene *scene = CTX_data_scene(C);
-                       *layer = BKE_screen_view3d_layer_active_ex(v3d, scene, false);
-                       for (a = 0; a < 20; a++) {
-                               layer_values[a] = (*layer & (1 << a)) != 0;
-                       }
-                       RNA_property_boolean_set_array(op->ptr, prop, layer_values);
+       if (local_view_bits) {
+               View3D *v3d = CTX_wm_view3d(C);
+               if (v3d && v3d->localvd) {
+                       *local_view_bits = v3d->local_view_uuid;
                }
-
-               /* in local view we additionally add local view layers,
-                * not part of operator properties */
-               if (v3d && v3d->localvd)
-                       *layer |= v3d->lay;
        }
 
        /* Location! */
@@ -391,11 +378,6 @@ bool ED_object_add_generic_get_opts(bContext *C, wmOperator *op, const char view
                        RNA_float_get_array(op->ptr, "rotation", rot);
        }
 
-       if (layer && *layer == 0) {
-               BKE_report(op->reports, RPT_ERROR, "Property 'layer' has no values set");
-               return false;
-       }
-
        return true;
 }
 
@@ -405,10 +387,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, ushort local_view_bits)
 {
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
+       ViewLayer *view_layer = CTX_data_view_layer(C);
        Object *ob;
 
        /* for as long scene has editmode... */
@@ -416,25 +399,22 @@ Object *ED_object_add_type(
                ED_object_editmode_exit(C, EM_FREEDATA | EM_WAITCURSOR);
        }
 
-       /* deselects all, sets scene->basact */
-       ob = BKE_object_add(bmain, scene, type, name);
-       BASACT->lay = ob->lay = layer;
+       /* deselects all, sets active object */
+       ob = BKE_object_add(bmain, scene, view_layer, type, name);
+       BASACT(view_layer)->local_view_bits = local_view_bits;
        /* editor level activate, notifiers */
-       ED_base_object_activate(C, BASACT);
+       ED_object_base_activate(C, view_layer->basact);
 
        /* more editor stuff */
-       ED_object_base_init_transform(C, BASACT, loc, rot);
-
-       /* Ignore collisions by default for non-mesh objects */
-       if (type != OB_MESH) {
-               ob->body_type = OB_BODY_TYPE_NO_COLLISION;
-               ob->gameflag &= ~(OB_SENSOR | OB_RIGID_BODY | OB_SOFT_BODY | OB_COLLISION | OB_CHARACTER | OB_OCCLUDER | OB_DYNAMIC | OB_NAVMESH); /* copied from rna_object.c */
-       }
+       ED_object_base_init_transform(C, view_layer->basact, loc, rot);
 
-       DAG_id_type_tag(bmain, ID_OB);
-       DAG_relations_tag_update(bmain);
-       if (ob->data) {
-               ED_render_id_flush_update(bmain, ob->data);
+       /* TODO(sergey): This is weird to manually tag objects for update, better to
+        * use DEG_id_tag_update here perhaps.
+        */
+       DEG_id_type_tag(bmain, ID_OB);
+       DEG_relations_tag_update(bmain);
+       if (ob->data != NULL) {
+               DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS);
        }
 
        if (enter_editmode)
@@ -442,6 +422,9 @@ Object *ED_object_add_type(
 
        WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
 
+       /* TODO(sergey): Use proper flag for tagging here. */
+       DEG_id_tag_update(&scene->id, 0);
+
        return ob;
 }
 
@@ -450,15 +433,15 @@ static int object_add_exec(bContext *C, wmOperator *op)
 {
        Object *ob;
        bool enter_editmode;
-       unsigned int layer;
+       ushort local_view_bits;
        float loc[3], rot[3], radius;
 
        WM_operator_view3d_unit_defaults(C, op);
-       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
+       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
                return OPERATOR_CANCELLED;
-
+       }
        radius = RNA_float_get(op->ptr, "radius");
-       ob = ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), NULL, loc, rot, enter_editmode, layer);
+       ob = ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), NULL, loc, rot, enter_editmode, local_view_bits);
 
        if (ob->type == OB_LATTICE) {
                /* lattice is a special case!
@@ -487,12 +470,95 @@ void OBJECT_OT_add(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
-       ED_object_add_unit_props(ot);
+       ED_object_add_unit_props_radius(ot);
        RNA_def_enum(ot->srna, "type", rna_enum_object_type_items, 0, "Type", "");
 
        ED_object_add_generic_props(ot, true);
 }
 
+/********************** Add Probe Operator **********************/
+
+/* for object add operator */
+static const char *get_lightprobe_defname(int type)
+{
+       switch (type) {
+               case LIGHTPROBE_TYPE_GRID: return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "IrradianceVolume");
+               case LIGHTPROBE_TYPE_PLANAR: return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "ReflectionPlane");
+               case LIGHTPROBE_TYPE_CUBE: return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "ReflectionCubemap");
+               default:
+                       return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "LightProbe");
+       }
+}
+
+static int lightprobe_add_exec(bContext *C, wmOperator *op)
+{
+       Object *ob;
+       LightProbe *probe;
+       int type;
+       bool enter_editmode;
+       ushort local_view_bits;
+       float loc[3], rot[3];
+       float radius;
+
+       WM_operator_view3d_unit_defaults(C, op);
+       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
+               return OPERATOR_CANCELLED;
+       }
+       type = RNA_enum_get(op->ptr, "type");
+       radius = RNA_float_get(op->ptr, "radius");
+
+       ob = ED_object_add_type(C, OB_LIGHTPROBE, get_lightprobe_defname(type), loc, rot, false, local_view_bits);
+       BKE_object_obdata_size_init(ob, radius);
+
+       probe = (LightProbe *)ob->data;
+       probe->type = type;
+
+       switch (type) {
+               case LIGHTPROBE_TYPE_GRID:
+                       probe->distinf = 0.3f;
+                       probe->falloff = 1.0f;
+                       probe->clipsta = 0.01f;
+                       break;
+               case LIGHTPROBE_TYPE_PLANAR:
+                       probe->distinf = 0.1f;
+                       probe->falloff = 0.5f;
+                       probe->clipsta = 0.001f;
+                       ob->empty_drawsize = 0.5f;
+                       break;
+               case LIGHTPROBE_TYPE_CUBE:
+                       probe->attenuation_type = LIGHTPROBE_SHAPE_ELIPSOID;
+                       break;
+               default:
+                       BLI_assert(!"LightProbe type not configured.");
+                       break;
+       }
+
+       DEG_relations_tag_update(CTX_data_main(C));
+
+       return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_lightprobe_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Add Light Probe";
+       ot->description = "Add a light probe object";
+       ot->idname = "OBJECT_OT_lightprobe_add";
+
+       /* api callbacks */
+       ot->exec = lightprobe_add_exec;
+       ot->poll = ED_operator_objectmode;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+       /* properties */
+       ot->prop = RNA_def_enum(ot->srna, "type", lightprobe_type_items, 0, "Type", "");
+
+       ED_object_add_unit_props_radius(ot);
+       ED_object_add_generic_props(ot, true);
+}
+
 /********************* Add Effector Operator ********************/
 
 /* for object add operator */
@@ -501,22 +567,22 @@ static int effector_add_exec(bContext *C, wmOperator *op)
        Object *ob;
        int type;
        bool enter_editmode;
-       unsigned int layer;
+       ushort local_view_bits;
        float loc[3], rot[3];
        float mat[4][4];
        float dia;
 
        WM_operator_view3d_unit_defaults(C, op);
-       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
+       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
                return OPERATOR_CANCELLED;
-
+       }
        type = RNA_enum_get(op->ptr, "type");
        dia = RNA_float_get(op->ptr, "radius");
 
        if (type == PFIELD_GUIDE) {
                Curve *cu;
                const char *name = CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "CurveGuide");
-               ob = ED_object_add_type(C, OB_CURVE, name, loc, rot, false, layer);
+               ob = ED_object_add_type(C, OB_CURVE, name, loc, rot, false, local_view_bits);
 
                cu = ob->data;
                cu->flag |= CU_PATH | CU_3D;
@@ -528,7 +594,7 @@ static int effector_add_exec(bContext *C, wmOperator *op)
        }
        else {
                const char *name = CTX_DATA_(BLT_I18NCONTEXT_ID_OBJECT, "Field");
-               ob = ED_object_add_type(C, OB_EMPTY, name, loc, rot, false, layer);
+               ob = ED_object_add_type(C, OB_EMPTY, name, loc, rot, false, local_view_bits);
                BKE_object_obdata_size_init(ob, dia);
                if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX))
                        ob->empty_drawtype = OB_SINGLE_ARROW;
@@ -536,7 +602,7 @@ static int effector_add_exec(bContext *C, wmOperator *op)
 
        ob->pd = BKE_partdeflect_new(type);
 
-       DAG_relations_tag_update(CTX_data_main(C));
+       DEG_relations_tag_update(CTX_data_main(C));
 
        return OPERATOR_FINISHED;
 }
@@ -558,7 +624,7 @@ void OBJECT_OT_effector_add(wmOperatorType *ot)
        /* properties */
        ot->prop = RNA_def_enum(ot->srna, "type", field_type_items, 0, "Type", "");
 
-       ED_object_add_unit_props(ot);
+       ED_object_add_unit_props_radius(ot);
        ED_object_add_generic_props(ot, true);
 }
 
@@ -571,16 +637,16 @@ static int object_camera_add_exec(bContext *C, wmOperator *op)
        Object *ob;
        Camera *cam;
        bool enter_editmode;
-       unsigned int layer;
+       ushort local_view_bits;
        float loc[3], rot[3];
 
        /* force view align for cameras */
        RNA_boolean_set(op->ptr, "view_align", true);
 
-       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
+       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
                return OPERATOR_CANCELLED;
-
-       ob = ED_object_add_type(C, OB_CAMERA, NULL, loc, rot, false, layer);
+       }
+       ob = ED_object_add_type(C, OB_CAMERA, NULL, loc, rot, false, local_view_bits);
 
        if (v3d) {
                if (v3d->camera == NULL)
@@ -627,21 +693,21 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op)
        Object *obedit = CTX_data_edit_object(C);
        bool newob = false;
        bool enter_editmode;
-       unsigned int layer;
+       ushort local_view_bits;
        float loc[3], rot[3];
        float mat[4][4];
        float dia;
 
        WM_operator_view3d_unit_defaults(C, op);
-       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
+       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
                return OPERATOR_CANCELLED;
-
+       }
        if (obedit == NULL || obedit->type != OB_MBALL) {
-               obedit = ED_object_add_type(C, OB_MBALL, NULL, loc, rot, true, layer);
+               obedit = ED_object_add_type(C, OB_MBALL, NULL, loc, rot, true, local_view_bits);
                newob = true;
        }
        else {
-               DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+               DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
        }
 
        ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
@@ -676,7 +742,7 @@ void OBJECT_OT_metaball_add(wmOperatorType *ot)
 
        ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_metaelem_type_items, 0, "Primitive", "");
 
-       ED_object_add_unit_props(ot);
+       ED_object_add_unit_props_radius(ot);
        ED_object_add_generic_props(ot, true);
 }
 
@@ -686,17 +752,17 @@ static int object_add_text_exec(bContext *C, wmOperator *op)
 {
        Object *obedit = CTX_data_edit_object(C);
        bool enter_editmode;
-       unsigned int layer;
+       ushort local_view_bits;
        float loc[3], rot[3];
 
        WM_operator_view3d_unit_defaults(C, op);
-       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
+       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
                return OPERATOR_CANCELLED;
-
+       }
        if (obedit && obedit->type == OB_FONT)
                return OPERATOR_CANCELLED;
 
-       obedit = ED_object_add_type(C, OB_FONT, NULL, loc, rot, enter_editmode, layer);
+       obedit = ED_object_add_type(C, OB_FONT, NULL, loc, rot, enter_editmode, local_view_bits);
        BKE_object_obdata_size_init(obedit, RNA_float_get(op->ptr, "radius"));
 
        WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit);
@@ -719,7 +785,7 @@ void OBJECT_OT_text_add(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
-       ED_object_add_unit_props(ot);
+       ED_object_add_unit_props_radius(ot);
        ED_object_add_generic_props(ot, true);
 }
 
@@ -731,21 +797,21 @@ static int object_armature_add_exec(bContext *C, wmOperator *op)
        RegionView3D *rv3d = CTX_wm_region_view3d(C);
        bool newob = false;
        bool enter_editmode;
-       unsigned int layer;
+       ushort local_view_bits;
        float loc[3], rot[3], dia;
        bool view_aligned = rv3d && (U.flag & USER_ADD_VIEWALIGNED);
 
        WM_operator_view3d_unit_defaults(C, op);
-       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL))
+       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
                return OPERATOR_CANCELLED;
-
+       }
        if ((obedit == NULL) || (obedit->type != OB_ARMATURE)) {
-               obedit = ED_object_add_type(C, OB_ARMATURE, NULL, loc, rot, true, layer);
+               obedit = ED_object_add_type(C, OB_ARMATURE, NULL, loc, rot, true, local_view_bits);
                ED_object_editmode_enter(C, 0);
                newob = true;
        }
        else {
-               DAG_id_tag_update(&obedit->id, OB_RECALC_DATA);
+               DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
        }
 
        if (obedit == NULL) {
@@ -780,7 +846,7 @@ void OBJECT_OT_armature_add(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
-       ED_object_add_unit_props(ot);
+       ED_object_add_unit_props_radius(ot);
        ED_object_add_generic_props(ot, true);
 }
 
@@ -790,14 +856,14 @@ static int object_empty_add_exec(bContext *C, wmOperator *op)
 {
        Object *ob;
        int type = RNA_enum_get(op->ptr, "type");
-       unsigned int layer;
+       ushort local_view_bits;
        float loc[3], rot[3];
 
        WM_operator_view3d_unit_defaults(C, op);
-       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL))
+       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
                return OPERATOR_CANCELLED;
-
-       ob = ED_object_add_type(C, OB_EMPTY, NULL, loc, rot, false, layer);
+       }
+       ob = ED_object_add_type(C, OB_EMPTY, NULL, loc, rot, false, local_view_bits);
 
        BKE_object_empty_draw_type_set(ob, type);
        BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
@@ -823,7 +889,7 @@ void OBJECT_OT_empty_add(wmOperatorType *ot)
        /* properties */
        ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_empty_drawtype_items, 0, "Type", "");
 
-       ED_object_add_unit_props(ot);
+       ED_object_add_unit_props_radius(ot);
        ED_object_add_generic_props(ot, false);
 }
 
@@ -831,9 +897,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv
 {
        Scene *scene = CTX_data_scene(C);
 
-       Base *base = NULL;
        Image *ima = NULL;
-       Object *ob = NULL;
 
        ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
        if (!ima) {
@@ -842,26 +906,29 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv
        /* handled below */
        id_us_min((ID *)ima);
 
-       base = ED_view3d_give_base_under_cursor(C, event->mval);
+       Object *ob = NULL;
+       Object *ob_cursor = ED_view3d_give_object_under_cursor(C, event->mval);
 
-       /* if empty under cursor, then set object */
-       if (base && base->object->type == OB_EMPTY) {
-               ob = base->object;
+       /* either change empty under cursor or create a new empty */
+       if (ob_cursor && ob_cursor->type == OB_EMPTY) {
                WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+               DEG_id_tag_update((ID *)ob_cursor, ID_RECALC_TRANSFORM);
+               ob = ob_cursor;
        }
        else {
                /* add new empty */
-               unsigned int layer;
+               ushort local_view_bits;
                float rot[3];
 
-               if (!ED_object_add_generic_get_opts(C, op, 'Z', NULL, rot, NULL, &layer, NULL))
+               if (!ED_object_add_generic_get_opts(C, op, 'Z', NULL, rot, NULL, &local_view_bits, NULL)) {
                        return OPERATOR_CANCELLED;
+               }
+               ob = ED_object_add_type(C, OB_EMPTY, NULL, NULL, rot, false, local_view_bits);
 
-               ob = ED_object_add_type(C, OB_EMPTY, NULL, NULL, rot, false, layer);
-
-               /* add under the mouse */
                ED_object_location_from_view(C, ob->loc);
-               ED_view3d_cursor3d_position(C, event->mval, ob->loc);
+               ED_view3d_cursor3d_position(C, event->mval, false, ob->loc);
+               ED_object_rotation_from_view(C, ob->rot, 'Z');
+               ob->empty_drawsize = 5.0f;
        }
 
        BKE_object_empty_draw_type_set(ob, OB_EMPTY_IMAGE);
@@ -899,41 +966,173 @@ void OBJECT_OT_drop_named_image(wmOperatorType *ot)
        ED_object_add_generic_props(ot, false);
 }
 
-/********************* Add Lamp Operator ********************/
+/********************* Add Gpencil Operator ********************/
+
+static int object_gpencil_add_exec(bContext *C, wmOperator *op)
+{
+       Object *ob = CTX_data_active_object(C);
+       bGPdata *gpd = (ob && (ob->type == OB_GPENCIL)) ? ob->data : NULL;
+
+       const int type = RNA_enum_get(op->ptr, "type");
+
+       ushort local_view_bits;
+       float loc[3], rot[3];
+       bool newob = false;
+
+       /* Note: We use 'Y' here (not 'Z'), as */
+       WM_operator_view3d_unit_defaults(C, op);
+       if (!ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, NULL, &local_view_bits, NULL)) {
+               return OPERATOR_CANCELLED;
+       }
+       /* add new object if not currently editing a GP object,
+        * or if "empty" was chosen (i.e. user wants a blank GP canvas)
+        */
+       if ((gpd == NULL) || (GPENCIL_ANY_MODE(gpd) == false) || (type == GP_EMPTY)) {
+               const char *ob_name = NULL;
+               switch (type) {
+                       case GP_MONKEY:
+                       {
+                               ob_name = "Suzanne";
+                               break;
+                       }
+                       case GP_STROKE:
+                       {
+                               ob_name = "Stroke";
+                               break;
+                       }
+                       default:
+                       {
+                               break;
+                       }
+               }
+
+               float radius = RNA_float_get(op->ptr, "radius");
+               ob = ED_object_add_type(C, OB_GPENCIL, ob_name, loc, rot, true, local_view_bits);
+               gpd = ob->data;
+               newob = true;
+
+               BKE_object_obdata_size_init(ob, GP_OBGPENCIL_DEFAULT_SIZE * radius);
+       }
+       else {
+               DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+               WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_ADDED, NULL);
+       }
+
+       /* create relevant geometry */
+       switch (type) {
+               case GP_STROKE:
+               {
+                       float radius = RNA_float_get(op->ptr, "radius");
+                       float mat[4][4];
+
+                       ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
+                       mul_v3_fl(mat[0], radius);
+                       mul_v3_fl(mat[1], radius);
+                       mul_v3_fl(mat[2], radius);
+
+                       ED_gpencil_create_stroke(C, mat);
+                       break;
+               }
+               case GP_MONKEY:
+               {
+                       float radius = RNA_float_get(op->ptr, "radius");
+                       float mat[4][4];
+
+                       ED_object_new_primitive_matrix(C, ob, loc, rot, mat);
+                       mul_v3_fl(mat[0], radius);
+                       mul_v3_fl(mat[1], radius);
+                       mul_v3_fl(mat[2], radius);
+
+                       ED_gpencil_create_monkey(C, mat);
+                       break;
+               }
+               case GP_EMPTY:
+                       /* do nothing */
+                       break;
+
+               default:
+                       BKE_report(op->reports, RPT_WARNING, "Not implemented");
+                       break;
+       }
+
+       /* if this is a new object, initialise default stuff (colors, etc.) */
+       if (newob) {
+               ED_gpencil_add_defaults(C);
+       }
+
+       return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_gpencil_add(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Add Grease Pencil";
+       ot->description = "Add a Grease Pencil object to the scene";
+       ot->idname = "OBJECT_OT_gpencil_add";
+
+       /* api callbacks */
+       ot->invoke = WM_menu_invoke;
+       ot->exec = object_gpencil_add_exec;
+       ot->poll = ED_operator_scene_editable;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+       /* properties */
+       ED_object_add_unit_props_radius(ot);
+       ED_object_add_generic_props(ot, false);
+
+       ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_gpencil_type_items, 0, "Type", "");
+}
+
+/********************* Add Light Operator ********************/
 
-static const char *get_lamp_defname(int type)
+static const char *get_light_defname(int type)
 {
        switch (type) {
                case LA_LOCAL: return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "Point");
                case LA_SUN: return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "Sun");
                case LA_SPOT: return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "Spot");
-               case LA_HEMI: return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "Hemi");
                case LA_AREA: return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "Area");
                default:
-                       return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "Lamp");
+                       return CTX_DATA_(BLT_I18NCONTEXT_ID_LAMP, "Light");
        }
 }
 
-static int object_lamp_add_exec(bContext *C, wmOperator *op)
+static int object_light_add_exec(bContext *C, wmOperator *op)
 {
        Scene *scene = CTX_data_scene(C);
        Object *ob;
        Lamp *la;
        int type = RNA_enum_get(op->ptr, "type");
-       unsigned int layer;
+       ushort local_view_bits;
        float loc[3], rot[3];
 
        WM_operator_view3d_unit_defaults(C, op);
-       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL))
+       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
                return OPERATOR_CANCELLED;
+       }
+       ob = ED_object_add_type(C, OB_LAMP, get_light_defname(type), loc, rot, false, local_view_bits);
 
-       ob = ED_object_add_type(C, OB_LAMP, get_lamp_defname(type), loc, rot, false, layer);
-       BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius"));
+       float size = RNA_float_get(op->ptr, "radius");
+       /* Better defaults for light size. */
+       switch (type) {
+               case LA_LOCAL:
+               case LA_SPOT:
+                       break;
+               case LA_AREA:
+                       size *= 4.0f;
+                       break;
+               default:
+                       size *= 0.5f;
+                       break;
+       }
+       BKE_object_obdata_size_init(ob, size);
 
        la = (Lamp *)ob->data;
        la->type = type;
 
-       if (BKE_scene_use_new_shading_nodes(scene)) {
+       if (BKE_scene_uses_cycles(scene)) {
                ED_node_shader_default(C, &la->id);
                la->use_nodes = true;
        }
@@ -941,43 +1140,43 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void OBJECT_OT_lamp_add(wmOperatorType *ot)
+void OBJECT_OT_light_add(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name = "Add Lamp";
-       ot->description = "Add a lamp object to the scene";
-       ot->idname = "OBJECT_OT_lamp_add";
+       ot->name = "Add Light";
+       ot->description = "Add a light object to the scene";
+       ot->idname = "OBJECT_OT_light_add";
 
        /* api callbacks */
        ot->invoke = WM_menu_invoke;
-       ot->exec = object_lamp_add_exec;
+       ot->exec = object_light_add_exec;
        ot->poll = ED_operator_objectmode;
 
        /* flags */
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
-       ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_lamp_type_items, 0, "Type", "");
+       ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_light_type_items, 0, "Type", "");
        RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_LAMP);
 
-       ED_object_add_unit_props(ot);
+       ED_object_add_unit_props_radius(ot);
        ED_object_add_generic_props(ot, false);
 }
 
-/********************* Add Group Instance Operator ********************/
+/********************* Add Collection Instance Operator ********************/
 
-static int group_instance_add_exec(bContext *C, wmOperator *op)
+static int collection_instance_add_exec(bContext *C, wmOperator *op)
 {
        Main *bmain = CTX_data_main(C);
-       Group *group;
-       unsigned int layer;
+       Collection *collection;
+       ushort local_view_bits;
        float loc[3], rot[3];
 
        if (RNA_struct_property_is_set(op->ptr, "name")) {
                char name[MAX_ID_NAME - 2];
 
                RNA_string_get(op->ptr, "name", name);
-               group = (Group *)BKE_libblock_find_name(bmain, ID_GR, name);
+               collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, name);
 
                if (0 == RNA_struct_property_is_set(op->ptr, "location")) {
                        const wmEvent *event = CTX_wm_window(C)->eventstate;
@@ -985,26 +1184,34 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
                        const int mval[2] = {event->x - ar->winrct.xmin,
                                             event->y - ar->winrct.ymin};
                        ED_object_location_from_view(C, loc);
-                       ED_view3d_cursor3d_position(C, mval, loc);
+                       ED_view3d_cursor3d_position(C, mval, false, loc);
                        RNA_float_set_array(op->ptr, "location", loc);
                }
        }
        else
-               group = BLI_findlink(&CTX_data_main(C)->group, RNA_enum_get(op->ptr, "group"));
+               collection = BLI_findlink(&CTX_data_main(C)->collection, RNA_enum_get(op->ptr, "collection"));
 
-       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL))
+       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
                return OPERATOR_CANCELLED;
-
-       if (group) {
+       }
+       if (collection) {
                Scene *scene = CTX_data_scene(C);
-               Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, loc, rot, false, layer);
-               ob->dup_group = group;
-               ob->transflag |= OB_DUPLIGROUP;
-               id_us_plus(&group->id);
+               ViewLayer *view_layer = CTX_data_view_layer(C);
 
-               /* works without this except if you try render right after, see: 22027 */
-               DAG_relations_tag_update(bmain);
+               /* Avoid dependency cycles. */
+               LayerCollection *active_lc = BKE_layer_collection_get_active(view_layer);
+               while (BKE_collection_find_cycle(active_lc->collection, collection)) {
+                       active_lc = BKE_layer_collection_activate_parent(view_layer, active_lc);
+               }
+
+               Object *ob = ED_object_add_type(C, OB_EMPTY, collection->id.name + 2, loc, rot, false, local_view_bits);
+               ob->dup_group = collection;
+               ob->transflag |= OB_DUPLICOLLECTION;
+               id_us_plus(&collection->id);
 
+               /* works without this except if you try render right after, see: 22027 */
+               DEG_relations_tag_update(bmain);
+               DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
                WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
 
                return OPERATOR_FINISHED;
@@ -1014,27 +1221,27 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
 }
 
 /* only used as menu */
-void OBJECT_OT_group_instance_add(wmOperatorType *ot)
+void OBJECT_OT_collection_instance_add(wmOperatorType *ot)
 {
        PropertyRNA *prop;
 
        /* identifiers */
-       ot->name = "Add Group Instance";
-       ot->description = "Add a dupligroup instance";
-       ot->idname = "OBJECT_OT_group_instance_add";
+       ot->name = "Add Collection Instance";
+       ot->description = "Add a collection instance";
+       ot->idname = "OBJECT_OT_collection_instance_add";
 
        /* api callbacks */
        ot->invoke = WM_enum_search_invoke;
-       ot->exec = group_instance_add_exec;
+       ot->exec = collection_instance_add_exec;
        ot->poll = ED_operator_objectmode;
 
        /* flags */
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
        /* properties */
-       RNA_def_string(ot->srna, "name", "Group", MAX_ID_NAME - 2, "Name", "Group name to add");
-       prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "");
-       RNA_def_enum_funcs(prop, RNA_group_itemf);
+       RNA_def_string(ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Collection name to add");
+       prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "");
+       RNA_def_enum_funcs(prop, RNA_collection_itemf);
        RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
        ot->prop = prop;
        ED_object_add_generic_props(ot, false);
@@ -1045,14 +1252,14 @@ void OBJECT_OT_group_instance_add(wmOperatorType *ot)
 static int object_speaker_add_exec(bContext *C, wmOperator *op)
 {
        Object *ob;
-       unsigned int layer;
+       ushort local_view_bits;
        float loc[3], rot[3];
        Scene *scene = CTX_data_scene(C);
 
-       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL))
+       if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &local_view_bits, NULL)) {
                return OPERATOR_CANCELLED;
-
-       ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, layer);
+       }
+       ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, local_view_bits);
 
        /* to make it easier to start using this immediately in NLA, a default sound clip is created
         * ready to be moved around to retime the sound and/or make new sound clips
@@ -1097,35 +1304,22 @@ void OBJECT_OT_speaker_add(wmOperatorType *ot)
 
 /**************************** Delete Object *************************/
 
-static void object_delete_check_glsl_update(Object *ob)
-{
-       /* some objects could affect on GLSL shading, make sure GLSL settings
-        * are being tagged to be updated when object is removing from scene
-        */
-       if (ob->type == OB_LAMP) {
-               if (ob->gpulamp.first)
-                       GPU_lamp_free(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_object_base_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);
-       DAG_id_type_tag(bmain, ID_OB);
+       DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_BASE_FLAGS);
+
+       BKE_scene_collections_object_remove(bmain, scene, ob, true);
 }
 
 static int object_delete_exec(bContext *C, wmOperator *op)
@@ -1135,34 +1329,40 @@ static int object_delete_exec(bContext *C, wmOperator *op)
        wmWindowManager *wm = CTX_wm_manager(C);
        wmWindow *win;
        const bool use_global = RNA_boolean_get(op->ptr, "use_global");
-       bool changed = false;
+       uint changed_count = 0;
 
        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;
                }
 
+               /* if grease pencil object, set cache as dirty */
+               if (ob->type == OB_GPENCIL) {
+                       bGPdata *gpd = (bGPdata *)ob->data;
+                       DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+               }
+
                /* This is sort of a quick hack to address T51243 - Proper thing to do here would be to nuke most of all this
                 * custom scene/object/base handling, and use generic lib remap/query for that.
                 * But this is for later (aka 2.8, once layers & co are settled and working).
                 */
-               if (use_global && base->object->id.lib == NULL) {
+               if (use_global && ob->id.lib == NULL) {
                        /* We want to nuke the object, let's nuke it the easy way (not for linked data though)... */
-                       BKE_libblock_delete(bmain, &base->object->id);
-                       changed = true;
+                       BKE_libblock_delete(bmain, &ob->id);
+                       changed_count += 1;
                        continue;
                }
 
@@ -1172,38 +1372,28 @@ static int object_delete_exec(bContext *C, wmOperator *op)
                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);
-               changed = true;
+               ED_object_base_free_and_unlink(bmain, scene, ob);
+               changed_count += 1;
 
                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(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_object_base_free_and_unlink(bmain, scene_iter, ob);
                                }
                        }
                }
@@ -1211,19 +1401,23 @@ static int object_delete_exec(bContext *C, wmOperator *op)
        }
        CTX_DATA_END;
 
-       if (!changed)
+       BKE_reportf(op->reports, RPT_INFO, "Deleted %u object(s)", changed_count);
+
+       if (changed_count == 0) {
                return OPERATOR_CANCELLED;
+       }
 
        /* delete has to handle all open scenes */
        BKE_main_id_tag_listbase(&bmain->scene, LIB_TAG_DOIT, true);
        for (win = wm->windows.first; win; win = win->next) {
-               scene = win->screen->scene;
+               scene = WM_window_get_active_scene(win);
 
                if (scene->id.tag & LIB_TAG_DOIT) {
                        scene->id.tag &= ~LIB_TAG_DOIT;
 
-                       DAG_relations_tag_update(bmain);
+                       DEG_relations_tag_update(bmain);
 
+                       DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
                        WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
                        WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
                }
@@ -1240,14 +1434,17 @@ void OBJECT_OT_delete(wmOperatorType *ot)
        ot->idname = "OBJECT_OT_delete";
 
        /* api callbacks */
-       ot->invoke = WM_operator_confirm;
+       ot->invoke = WM_operator_confirm_or_exec;
        ot->exec = object_delete_exec;
        ot->poll = ED_operator_objectmode;
 
        /* flags */
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 
-       RNA_def_boolean(ot->srna, "use_global", 0, "Delete Globally", "Remove object from all scenes");
+       PropertyRNA *prop;
+       prop = RNA_def_boolean(ot->srna, "use_global", 0, "Delete Globally", "Remove object from all scenes");
+       RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+       WM_operator_properties_confirm_or_exec(ot);
 }
 
 /**************************** Copy Utilities ******************************/
@@ -1263,15 +1460,13 @@ static void copy_object_set_idnew(bContext *C)
        }
        CTX_DATA_END;
 
-       set_sca_new_poins();
-
        BKE_main_id_clear_newpoins(bmain);
 }
 
 /********************* Make Duplicates Real ************************/
 
 /**
- * \note regarding hashing dupli-objects when using OB_DUPLIGROUP, skip the first member of #DupliObject.persistent_id
+ * \note regarding hashing dupli-objects when using OB_DUPLICOLLECTION, skip the first member of #DupliObject.persistent_id
  * since its a unique index and we only want to know if the group objects are from the same dupli-group instance.
  */
 static unsigned int dupliobject_group_hash(const void *ptr)
@@ -1286,7 +1481,7 @@ static unsigned int dupliobject_group_hash(const void *ptr)
 }
 
 /**
- * \note regarding hashing dupli-objects when NOT using OB_DUPLIGROUP, include the first member of #DupliObject.persistent_id
+ * \note regarding hashing dupli-objects when NOT using OB_DUPLICOLLECTION, include the first member of #DupliObject.persistent_id
  * since its the index of the vertex/face the object is instantiated on and we want to identify objects on the same vertex/face.
  */
 static unsigned int dupliobject_hash(const void *ptr)
@@ -1344,6 +1539,8 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
                                        const bool use_hierarchy)
 {
        Main *bmain = CTX_data_main(C);
+       ViewLayer *view_layer = CTX_data_view_layer(C);
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
        ListBase *lb_duplis;
        DupliObject *dob;
        GHash *dupli_gh, *parent_gh = NULL;
@@ -1352,11 +1549,12 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
                return;
        }
 
-       lb_duplis = object_duplilist(bmain, bmain->eval_ctx, scene, base->object);
+       Object *object_eval = DEG_get_evaluated_object(depsgraph, base->object);
+       lb_duplis = object_duplilist(depsgraph, scene, object_eval);
 
        dupli_gh = BLI_ghash_ptr_new(__func__);
        if (use_hierarchy) {
-               if (base->object->transflag & OB_DUPLIGROUP) {
+               if (base->object->transflag & OB_DUPLICOLLECTION) {
                        parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
                }
                else {
@@ -1365,7 +1563,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
        }
 
        for (dob = lb_duplis->first; dob; dob = dob->next) {
-               Object *ob_src = dob->ob;
+               Object *ob_src = DEG_get_original_object(dob->ob);
                Object *ob_dst = ID_NEW_SET(dob->ob, BKE_object_copy(bmain, ob_src));
                Base *base_dst;
 
@@ -1376,12 +1574,11 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
                        ob_dst->totcol = 0;
                }
 
-               base_dst = MEM_dupallocN(base);
-               base_dst->flag &= ~(OB_FROMDUPLI | OB_FROMGROUP);
-               ob_dst->flag = base_dst->flag;
-               base_dst->lay = base->lay;
-               BLI_addhead(&scene->base, base_dst);   /* addhead: othwise eternal loop */
-               base_dst->object = ob_dst;
+               BKE_collection_object_add_from(bmain, scene, base->object, ob_dst);
+               base_dst = BKE_view_layer_base_find(view_layer, ob_dst);
+               BLI_assert(base_dst != NULL);
+
+               BKE_scene_object_base_flag_sync_from_base(base_dst);
 
                /* make sure apply works */
                BKE_animdata_free(&ob_dst->id, true);
@@ -1394,9 +1591,8 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
 
                ob_dst->parent = NULL;
                BKE_constraints_free(&ob_dst->constraints);
-               ob_dst->curve_cache = NULL;
+               ob_dst->runtime.curve_cache = NULL;
                ob_dst->transflag &= ~OB_DUPLI;
-               ob_dst->lay = base->lay;
 
                copy_m4_m4(ob_dst->obmat, dob->mat);
                BKE_object_apply_mat4(ob_dst, ob_dst->obmat, false, false);
@@ -1413,14 +1609,13 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
        }
 
        for (dob = lb_duplis->first; dob; dob = dob->next) {
-               Object *ob_src = dob->ob;
+               Object *ob_src = DEG_get_original_object(dob->ob);
                Object *ob_dst = BLI_ghash_lookup(dupli_gh, dob);
 
                /* Remap new object to itself, and clear again newid pointer of orig object. */
                BKE_libblock_relink_to_newid(&ob_dst->id);
-               set_sca_new_poins_ob(ob_dst);
 
-               DAG_id_tag_update(&ob_dst->id, OB_RECALC_DATA);
+               DEG_id_tag_update(&ob_dst->id, ID_RECALC_GEOMETRY);
 
                if (use_hierarchy) {
                        /* original parents */
@@ -1433,7 +1628,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
                                 * they won't be read, this is simply for a hash lookup. */
                                DupliObject dob_key;
                                dob_key.ob = ob_src_par;
-                               if (base->object->transflag & OB_DUPLIGROUP) {
+                               if (base->object->transflag & OB_DUPLICOLLECTION) {
                                        memcpy(&dob_key.persistent_id[1],
                                               &dob->persistent_id[1],
                                               sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
@@ -1473,17 +1668,17 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
                         * still work out ok */
                        BKE_object_apply_mat4(ob_dst, dob->mat, false, true);
 
-                       /* to set ob_dst->orig and in case theres any other discrepicies */
-                       DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB);
+                       /* to set ob_dst->orig and in case there's any other discrepancies */
+                       DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM);
                }
        }
 
-       if (base->object->transflag & OB_DUPLIGROUP && base->object->dup_group) {
+       if (base->object->transflag & OB_DUPLICOLLECTION && base->object->dup_group) {
                for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
                        if (ob->proxy_group == base->object) {
                                ob->proxy = NULL;
                                ob->proxy_from = NULL;
-                               DAG_id_tag_update(&ob->id, OB_RECALC_OB);
+                               DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
                        }
                }
        }
@@ -1498,6 +1693,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
        BKE_main_id_clear_newpoins(bmain);
 
        base->object->transflag &= ~OB_DUPLI;
+       DEG_id_tag_update(&base->object->id, ID_RECALC_COPY_ON_WRITE);
 }
 
 static int object_duplicates_make_real_exec(bContext *C, wmOperator *op)
@@ -1519,7 +1715,7 @@ static int object_duplicates_make_real_exec(bContext *C, wmOperator *op)
        }
        CTX_DATA_END;
 
-       DAG_relations_tag_update(bmain);
+       DEG_relations_tag_update(bmain);
        WM_event_add_notifier(C, NC_SCENE, scene);
        WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
 
@@ -1539,7 +1735,7 @@ void OBJECT_OT_duplicates_make_real(wmOperatorType *ot)
        ot->poll = ED_operator_objectmode;
 
        /* flags */
-       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
 
        RNA_def_boolean(ot->srna, "use_base_parent", 0, "Parent", "Parent newly created objects to the original duplicator");
        RNA_def_boolean(ot->srna, "use_hierarchy", 0, "Keep Hierarchy", "Maintain parent child relationships");
@@ -1553,46 +1749,46 @@ static const EnumPropertyItem convert_target_items[] = {
        {0, NULL, 0, NULL, NULL}
 };
 
-static void convert_ensure_curve_cache(Main *bmain, Scene *scene, Object *ob)
+static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Object *ob)
 {
-       if (ob->curve_cache == NULL) {
+       if (ob->runtime.curve_cache == NULL) {
                /* Force creation. This is normally not needed but on operator
                 * redo we might end up with an object which isn't evaluated yet.
+                * Also happens in case we are working on a copy of the object (all its caches have been nuked then).
                 */
                if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
-                       BKE_displist_make_curveTypes(scene, ob, false);
+                       /* We need 'for render' ON here, to enable computing bevel dipslist if needed.
+                        * Also makes sense anyway, we would not want e.g. to loose hidden parts etc. */
+                       BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false);
                }
                else if (ob->type == OB_MBALL) {
-                       BKE_displist_make_mball(bmain, bmain->eval_ctx, scene, ob);
+                       BKE_displist_make_mball(depsgraph, scene, ob);
                }
        }
 }
 
-static void curvetomesh(Main *bmain, Scene *scene, Object *ob)
+static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
 {
-       convert_ensure_curve_cache(bmain, scene, ob);
+       convert_ensure_curve_cache(depsgraph, scene, ob);
        BKE_mesh_from_nurbs(bmain, ob); /* also does users */
 
        if (ob->type == OB_MESH) {
                BKE_object_free_modifiers(ob, 0);
-
-               /* Game engine defaults for mesh objects */
-               ob->body_type = OB_BODY_TYPE_STATIC;
-               ob->gameflag = OB_PROP | OB_COLLISION;
        }
 }
 
 static bool convert_poll(bContext *C)
 {
-       Object *obact = CTX_data_active_object(C);
        Scene *scene = CTX_data_scene(C);
+       Base *base_act = CTX_data_active_base(C);
+       Object *obact = base_act ? base_act->object : NULL;
 
-       return (!ID_IS_LINKED(scene) && obact && scene->obedit != obact &&
-               (obact->flag & SELECT) && !ID_IS_LINKED(obact));
+       return (!ID_IS_LINKED(scene) && obact && (BKE_object_is_in_editmode(obact) == false) &&
+               (base_act->flag & BASE_SELECTED) && !ID_IS_LINKED(obact));
 }
 
 /* Helper for convert_exec */
-static Base *duplibase_for_convert(Main *bmain, Scene *scene, Base *base, Object *ob)
+static Base *duplibase_for_convert(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, Object *ob)
 {
        Object *obn;
        Base *basen;
@@ -1602,27 +1798,23 @@ static Base *duplibase_for_convert(Main *bmain, Scene *scene, Base *base, Object
        }
 
        obn = BKE_object_copy(bmain, ob);
-       DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
-
-       basen = MEM_mallocN(sizeof(Base), "duplibase");
-       *basen = *base;
-       BLI_addhead(&scene->base, basen);   /* addhead: otherwise eternal loop */
-       basen->object = obn;
-       basen->flag |= SELECT;
-       obn->flag |= SELECT;
-       base->flag &= ~SELECT;
-       ob->flag &= ~SELECT;
+       DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
+       BKE_collection_object_add_from(bmain, scene, ob, obn);
 
+       basen = BKE_view_layer_base_find(view_layer, obn);
+       ED_object_base_select(basen, BA_SELECT);
+       ED_object_base_select(basen, BA_DESELECT);
        return basen;
 }
 
 static int convert_exec(bContext *C, wmOperator *op)
 {
        Main *bmain = CTX_data_main(C);
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
+       ViewLayer *view_layer = CTX_data_view_layer(C);
        Base *basen = NULL, *basact = NULL;
-       Object *ob, *ob1, *obact = CTX_data_active_object(C);
-       DerivedMesh *dm;
+       Object *ob1, *obact = CTX_data_active_object(C);
        Curve *cu;
        Nurb *nu;
        MetaBall *mb;
@@ -1634,13 +1826,11 @@ static int convert_exec(bContext *C, wmOperator *op)
        /* don't forget multiple users! */
 
        {
-               Base *base;
-
-               for (base = scene->base.first; base; base = base->next) {
-                       ob = base->object;
+               FOREACH_SCENE_OBJECT_BEGIN(scene, ob)
+               {
                        ob->flag &= ~OB_DONE;
 
-                       /* flag data thats not been edited (only needed for !keep_original) */
+                       /* flag data that's not been edited (only needed for !keep_original) */
                        if (ob->data) {
                                ((ID *)ob->data)->tag |= LIB_TAG_DOIT;
                        }
@@ -1649,13 +1839,14 @@ static int convert_exec(bContext *C, wmOperator *op)
                        if (ob->type == OB_MBALL && target == OB_MESH) {
                                if (BKE_mball_is_basis(ob) == false) {
                                        Object *ob_basis;
-                                       ob_basis = BKE_mball_basis_find(bmain, bmain->eval_ctx, scene, ob);
+                                       ob_basis = BKE_mball_basis_find(scene, ob);
                                        if (ob_basis) {
                                                ob_basis->flag &= ~OB_DONE;
                                        }
                                }
                        }
                }
+               FOREACH_SCENE_OBJECT_END;
        }
 
        ListBase selected_editable_bases = CTX_data_collection_get(C, "selected_editable_bases");
@@ -1666,7 +1857,7 @@ static int convert_exec(bContext *C, wmOperator *op)
        {
                for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
                        Base *base = link->ptr.data;
-                       ob = base->object;
+                       Object *ob = base->object;
 
                        /* The way object type conversion works currently (enforcing conversion of *all* objects using converted
                         * object-data, even some un-selected/hidden/another scene ones, sounds totally bad to me.
@@ -1679,19 +1870,19 @@ static int convert_exec(bContext *C, wmOperator *op)
                                            "Converting some linked object/object data, enforcing 'Keep Original' option to True");
                        }
 
-                       DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
+                       DEG_id_tag_update(&base->object->id, ID_RECALC_GEOMETRY);
                }
 
                uint64_t customdata_mask_prev = scene->customdata_mask;
                scene->customdata_mask |= CD_MASK_MESH;
-               BKE_scene_update_tagged(bmain->eval_ctx, bmain, scene);
+               BKE_scene_graph_update_tagged(depsgraph, bmain);
                scene->customdata_mask = customdata_mask_prev;
        }
 
        for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
                Object *newob = NULL;
                Base *base = link->ptr.data;
-               ob = base->object;
+               Object *ob = base->object;
 
                if (ob->flag & OB_DONE || !IS_TAGGED(ob->data)) {
                        if (ob->type != target) {
@@ -1706,13 +1897,17 @@ static int convert_exec(bContext *C, wmOperator *op)
                                if (ob->type == OB_MESH) {
                                        BKE_object_free_modifiers(ob, 0);  /* after derivedmesh calls! */
                                }
+                               if (ob->type == OB_GPENCIL) {
+                                       BKE_object_free_modifiers(ob, 0);  /* after derivedmesh calls! */
+                                       BKE_object_free_shaderfx(ob, 0);
+                               }
                        }
                }
                else if (ob->type == OB_MESH && target == OB_CURVE) {
                        ob->flag |= OB_DONE;
 
                        if (keep_original) {
-                               basen = duplibase_for_convert(bmain, scene, base, NULL);
+                               basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
                                newob = basen->object;
 
                                /* decrement original mesh's usage count  */
@@ -1726,7 +1921,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                                newob = ob;
                        }
 
-                       BKE_mesh_to_curve(bmain, scene, newob);
+                       BKE_mesh_to_curve(bmain, depsgraph, scene, newob);
 
                        if (newob->type == OB_CURVE) {
                                BKE_object_free_modifiers(newob, 0);   /* after derivedmesh calls! */
@@ -1737,7 +1932,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                        ob->flag |= OB_DONE;
 
                        if (keep_original) {
-                               basen = duplibase_for_convert(bmain, scene, base, NULL);
+                               basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
                                newob = basen->object;
 
                                /* decrement original mesh's usage count  */
@@ -1749,26 +1944,25 @@ static int convert_exec(bContext *C, wmOperator *op)
                        }
                        else {
                                newob = ob;
-                               DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+                               DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
                        }
 
                        /* make new mesh data from the original copy */
                        /* note: get the mesh from the original, not from the copy in some
-                        * cases this doesnt give correct results (when MDEF is used for eg)
+                        * cases this doesn't give correct results (when MDEF is used for eg)
                         */
-                       dm = mesh_get_derived_final(scene, newob, CD_MASK_MESH);
-
-                       DM_to_mesh(dm, newob->data, newob, CD_MASK_MESH, true);
-
-                       /* re-tessellation is called by DM_to_mesh */
-
+                       Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
+                       Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+                       Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, CD_MASK_MESH);
+                       me_eval = BKE_mesh_copy_for_eval(me_eval, false);
+                       BKE_mesh_nomain_to_mesh(me_eval, newob->data, newob, CD_MASK_MESH, true);
                        BKE_object_free_modifiers(newob, 0);   /* after derivedmesh calls! */
                }
                else if (ob->type == OB_FONT) {
                        ob->flag |= OB_DONE;
 
                        if (keep_original) {
-                               basen = duplibase_for_convert(bmain, scene, base, NULL);
+                               basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
                                newob = basen->object;
 
                                /* decrement original curve's usage count  */
@@ -1787,6 +1981,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                         *               datablock, but for until we've got granular update
                         *               lets take care by selves.
                         */
+                       /* XXX This may fail/crash, since BKE_vfont_to_curve() accesses evaluated data in some cases (bastien). */
                        BKE_vfont_to_curve(newob, FO_EDIT);
 
                        newob->type = OB_CURVE;
@@ -1815,7 +2010,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                                        for (ob1 = bmain->object.first; ob1; ob1 = ob1->id.next) {
                                                if (ob1->data == ob->data) {
                                                        ob1->type = OB_CURVE;
-                                                       DAG_id_tag_update(&ob1->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+                                                       DEG_id_tag_update(&ob1->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
                                                }
                                        }
                                }
@@ -1828,7 +2023,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                        BKE_curve_curve_dimension_update(cu);
 
                        if (target == OB_MESH) {
-                               curvetomesh(bmain, scene, newob);
+                               curvetomesh(bmain, depsgraph, scene, newob);
 
                                /* meshes doesn't use displist */
                                BKE_object_free_curve_cache(newob);
@@ -1839,7 +2034,7 @@ static int convert_exec(bContext *C, wmOperator *op)
 
                        if (target == OB_MESH) {
                                if (keep_original) {
-                                       basen = duplibase_for_convert(bmain, scene, base, NULL);
+                                       basen = duplibase_for_convert(bmain, scene, view_layer, base, NULL);
                                        newob = basen->object;
 
                                        /* decrement original curve's usage count  */
@@ -1852,7 +2047,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                                        newob = ob;
                                }
 
-                               curvetomesh(bmain, scene, newob);
+                               curvetomesh(bmain, depsgraph, scene, newob);
 
                                /* meshes doesn't use displist */
                                BKE_object_free_curve_cache(newob);
@@ -1861,10 +2056,10 @@ static int convert_exec(bContext *C, wmOperator *op)
                else if (ob->type == OB_MBALL && target == OB_MESH) {
                        Object *baseob;
 
-                       base->flag &= ~SELECT;
-                       ob->flag &= ~SELECT;
+                       base->flag &= ~BASE_SELECTED;
+                       ob->base_flag &= ~BASE_SELECTED;
 
-                       baseob = BKE_mball_basis_find(bmain, bmain->eval_ctx, scene, ob);
+                       baseob = BKE_mball_basis_find(scene, ob);
 
                        if (ob != baseob) {
                                /* if motherball is converting it would be marked as done later */
@@ -1874,7 +2069,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                        if (!(baseob->flag & OB_DONE)) {
                                baseob->flag |= OB_DONE;
 
-                               basen = duplibase_for_convert(bmain, scene, base, baseob);
+                               basen = duplibase_for_convert(bmain, scene, view_layer, base, baseob);
                                newob = basen->object;
 
                                mb = newob->data;
@@ -1890,8 +2085,8 @@ static int convert_exec(bContext *C, wmOperator *op)
                                        for (a = 0; a < newob->totcol; a++) id_us_plus((ID *)me->mat[a]);
                                }
 
-                               convert_ensure_curve_cache(bmain, scene, baseob);
-                               BKE_mesh_from_metaball(&baseob->curve_cache->disp, newob->data);
+                               convert_ensure_curve_cache(depsgraph, scene, baseob);
+                               BKE_mesh_from_metaball(&baseob->runtime.curve_cache->disp, newob->data);
 
                                if (obact->type == OB_MBALL) {
                                        basact = basen;
@@ -1922,7 +2117,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                }
 
                if (!keep_original && (ob->flag & OB_DONE)) {
-                       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+                       DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
                        ((ID *)ob->data)->tag &= ~LIB_TAG_DOIT; /* flag not to convert this datablock again */
                }
        }
@@ -1930,27 +2125,21 @@ static int convert_exec(bContext *C, wmOperator *op)
 
        if (!keep_original) {
                if (mballConverted) {
-                       Base *base, *base_next;
-
-                       for (base = scene->base.first; base; base = base_next) {
-                               base_next = base->next;
-
-                               ob = base->object;
-                               if (ob->type == OB_MBALL) {
-                                       if (ob->flag & OB_DONE) {
+                       FOREACH_SCENE_OBJECT_BEGIN(scene, ob_mball)
+                       {
+                               if (ob_mball->type == OB_MBALL) {
+                                       if (ob_mball->flag & OB_DONE) {
                                                Object *ob_basis = NULL;
-                                               if (BKE_mball_is_basis(ob) ||
-                                                   ((ob_basis = BKE_mball_basis_find(bmain, bmain->eval_ctx, scene, ob)) && (ob_basis->flag & OB_DONE)))
+                                               if (BKE_mball_is_basis(ob_mball) ||
+                                                   ((ob_basis = BKE_mball_basis_find(scene, ob_mball)) && (ob_basis->flag & OB_DONE)))
                                                {
-                                                       ED_base_object_free_and_unlink(bmain, scene, base);
+                                                       ED_object_base_free_and_unlink(bmain, scene, ob_mball);
                                                }
                                        }
                                }
                        }
+                       FOREACH_SCENE_OBJECT_END;
                }
-
-               /* delete object should renew depsgraph */
-               DAG_relations_tag_update(bmain);
        }
 
 // XXX ED_object_editmode_enter(C, 0);
@@ -1958,15 +2147,16 @@ static int convert_exec(bContext *C, wmOperator *op)
 
        if (basact) {
                /* active base was changed */
-               ED_base_object_activate(C, basact);
-               BASACT = basact;
+               ED_object_base_activate(C, basact);
+               BASACT(view_layer) = basact;
        }
-       else if (BASACT->object->flag & OB_DONE) {
-               WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT->object);
-               WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT->object);
+       else if (BASACT(view_layer)->object->flag & OB_DONE) {
+               WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT(view_layer)->object);
+               WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT(view_layer)->object);
        }
 
-       DAG_relations_tag_update(bmain);
+       DEG_relations_tag_update(bmain);
+       DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
        WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
        WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
 
@@ -2005,39 +2195,44 @@ void OBJECT_OT_convert(wmOperatorType *ot)
 /* used below, assumes id.new is correct */
 /* leaves selection of base/object unaltered */
 /* Does set ID->newid pointers. */
-static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base, int dupflag)
+static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob, int dupflag)
 {
 #define ID_NEW_REMAP_US(a)     if (      (a)->id.newid) { (a) = (void *)(a)->id.newid;       (a)->id.us++; }
 #define ID_NEW_REMAP_US2(a)    if (((ID *)a)->newid)    { (a) = ((ID  *)a)->newid;     ((ID *)a)->us++;    }
 
-       Base *basen = NULL;
+       Base *base, *basen = NULL;
        Material ***matarar;
-       Object *ob, *obn;
+       Object *obn;
        ID *id;
        int a, didit;
 
-       ob = base->object;
        if (ob->mode & OB_MODE_POSE) {
                ; /* nothing? */
        }
        else {
                obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
-               DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+               DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
 
-               basen = MEM_mallocN(sizeof(Base), "duplibase");
-               *basen = *base;
-               BLI_addhead(&scene->base, basen);   /* addhead: prevent eternal loop */
-               basen->object = obn;
+               base = BKE_view_layer_base_find(view_layer, ob);
+               if ((base != NULL) && (base->flag & BASE_VISIBLE)) {
+                       BKE_collection_object_add_from(bmain, scene, ob, obn);
+               }
+               else {
+                       LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
+                       BKE_collection_object_add(bmain, layer_collection->collection, obn);
+               }
+               basen = BKE_view_layer_base_find(view_layer, obn);
+               basen->local_view_bits = base->local_view_bits;
 
-               /* 1) duplis should end up in same group as the original
-                * 2) Rigid Body sim participants MUST always be part of a group...
+               /* 1) duplis should end up in same collection as the original
+                * 2) Rigid Body sim participants MUST always be part of a collection...
                 */
                // XXX: is 2) really a good measure here?
-               if ((basen->flag & OB_FROMGROUP) || ob->rigidbody_object || ob->rigidbody_constraint) {
-                       Group *group;
-                       for (group = bmain->group.first; group; group = group->id.next) {
-                               if (BKE_group_object_exists(group, ob))
-                                       BKE_group_object_add(group, obn, scene, basen);
+               if (ob->rigidbody_object || ob->rigidbody_constraint) {
+                       Collection *collection;
+                       for (collection = bmain->collection.first; collection; collection = collection->id.next) {
+                               if (BKE_collection_has_object(collection, ob))
+                                       BKE_collection_object_add(bmain, collection, obn);
                        }
                }
 
@@ -2053,6 +2248,10 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                                        ID_NEW_REMAP_US(obn->mat[a])
                                        else {
                                                obn->mat[a] = ID_NEW_SET(obn->mat[a], BKE_material_copy(bmain, obn->mat[a]));
+                                               /* duplicate grease pencil settings */
+                                               if (ob->mat[a]->gp_style) {
+                                                       obn->mat[a]->gp_style = MEM_dupallocN(ob->mat[a]->gp_style);
+                                               }
                                        }
                                        id_us_min(id);
 
@@ -2146,14 +2345,14 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                                }
                                break;
                        case OB_ARMATURE:
-                               DAG_id_tag_update(&obn->id, OB_RECALC_DATA);
+                               DEG_id_tag_update(&obn->id, ID_RECALC_GEOMETRY);
                                if (obn->pose)
                                        BKE_pose_tag_recalc(bmain, obn->pose);
                                if (dupflag & USER_DUP_ARM) {
                                        ID_NEW_REMAP_US2(obn->data)
                                        else {
                                                obn->data = ID_NEW_SET(obn->data, BKE_armature_copy(bmain, obn->data));
-                                               BKE_pose_rebuild(obn, obn->data);
+                                               BKE_pose_rebuild(bmain, obn, obn->data, true);
                                                didit = 1;
                                        }
                                        id_us_min(id);
@@ -2179,6 +2378,16 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                                        id_us_min(id);
                                }
                                break;
+                       case OB_LIGHTPROBE:
+                               if (dupflag != 0) {
+                                       ID_NEW_REMAP_US2(obn->data)
+                                       else {
+                                               obn->data = ID_NEW_SET(obn->data, BKE_lightprobe_copy(bmain, obn->data));
+                                               didit = 1;
+                                       }
+                                       id_us_min(id);
+                               }
+                               break;
                        case OB_SPEAKER:
                                if (dupflag != 0) {
                                        ID_NEW_REMAP_US2(obn->data)
@@ -2189,6 +2398,16 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                                        id_us_min(id);
                                }
                                break;
+                       case OB_GPENCIL:
+                               if (dupflag != 0) {
+                                       ID_NEW_REMAP_US2(obn->data)
+                                       else {
+                                               obn->data = ID_NEW_SET(obn->data, BKE_gpencil_copy(bmain, obn->data));
+                                               didit = 1;
+                                       }
+                                       id_us_min(id);
+                               }
+                               break;
                }
 
                /* check if obdata is copied */
@@ -2201,25 +2420,10 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
                        }
 
                        if (dupflag & USER_DUP_ACT) {
-                               bActuator *act;
-
                                BKE_animdata_copy_id_action(bmain, (ID *)obn->data, true);
                                if (key) {
                                        BKE_animdata_copy_id_action(bmain, (ID *)key, true);
                                }
-
-                               /* Update the duplicated action in the action actuators */
-                               /* XXX TODO this code is all wrong! actact->act is user-refcounted (see readfile.c),
-                                * and what about other ID pointers of other BGE logic bricks,
-                                * and since this is object-level, why is it only ran if obdata was duplicated??? -mont29 */
-                               for (act = obn->actuators.first; act; act = act->next) {
-                                       if (act->type == ACT_ACTION) {
-                                               bActionActuator *actact = (bActionActuator *) act->data;
-                                               if (ob->adt && actact->act == ob->adt->action) {
-                                                       actact->act = obn->adt->action;
-                                               }
-                                       }
-                               }
                        }
 
                        if (dupflag & USER_DUP_MAT) {
@@ -2250,14 +2454,12 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
  * note: don't call this within a loop since clear_* funcs loop over the entire database.
  * note: caller must do DAG_relations_tag_update(bmain);
  *       this is not done automatic since we may duplicate many objects in a batch */
-Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag)
+Base *ED_object_add_duplicate(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, int dupflag)
 {
        Base *basen;
        Object *ob;
 
-       clear_sca_new_poins();  /* BGE logic */
-
-       basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
+       basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag);
        if (basen == NULL) {
                return NULL;
        }
@@ -2266,12 +2468,11 @@ Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag
 
        /* link own references to the newly duplicated data [#26816] */
        BKE_libblock_relink_to_newid(&ob->id);
-       set_sca_new_poins_ob(ob);
 
        /* DAG_relations_tag_update(bmain); */ /* caller must do */
 
-       if (ob->data) {
-               ED_render_id_flush_update(bmain, ob->data);
+       if (ob->data != NULL) {
+               DEG_id_tag_update_ex(bmain, (ID *)ob->data, ID_RECALC_EDITORS);
        }
 
        BKE_main_id_clear_newpoins(bmain);
@@ -2284,29 +2485,29 @@ static int duplicate_exec(bContext *C, wmOperator *op)
 {
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
+       ViewLayer *view_layer = CTX_data_view_layer(C);
        const bool linked = RNA_boolean_get(op->ptr, "linked");
        int dupflag = (linked) ? 0 : U.dupflag;
 
-       clear_sca_new_poins();  /* BGE logic */
-
        CTX_DATA_BEGIN (C, Base *, base, selected_bases)
        {
-               Base *basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
+               Base *basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag);
 
                /* note that this is safe to do with this context iterator,
                 * the list is made in advance */
-               ED_base_object_select(base, BA_DESELECT);
+               ED_object_base_select(base, BA_DESELECT);
+               ED_object_base_select(basen, BA_SELECT);
 
                if (basen == NULL) {
                        continue;
                }
 
                /* new object becomes active */
-               if (BASACT == base)
-                       ED_base_object_activate(C, basen);
+               if (BASACT(view_layer) == base)
+                       ED_object_base_activate(C, basen);
 
                if (basen->object->data) {
-                       DAG_id_tag_update(basen->object->data, 0);
+                       DEG_id_tag_update(basen->object->data, 0);
                }
        }
        CTX_DATA_END;
@@ -2315,7 +2516,8 @@ static int duplicate_exec(bContext *C, wmOperator *op)
 
        BKE_main_id_clear_newpoins(bmain);
 
-       DAG_relations_tag_update(bmain);
+       DEG_relations_tag_update(bmain);
+       DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
 
        WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
 
@@ -2351,9 +2553,9 @@ static int add_named_exec(bContext *C, wmOperator *op)
        wmWindow *win = CTX_wm_window(C);
        const wmEvent *event = win ? win->eventstate : NULL;
        Main *bmain = CTX_data_main(C);
-       View3D *v3d = CTX_wm_view3d(C);  /* may be NULL */
        Scene *scene = CTX_data_scene(C);
-       Base *basen, *base;
+       ViewLayer *view_layer = CTX_data_view_layer(C);
+       Base *basen;
        Object *ob;
        const bool linked = RNA_boolean_get(op->ptr, "linked");
        int dupflag = (linked) ? 0 : U.dupflag;
@@ -2368,22 +2570,15 @@ static int add_named_exec(bContext *C, wmOperator *op)
                return OPERATOR_CANCELLED;
        }
 
-       base = MEM_callocN(sizeof(Base), "duplibase");
-       base->object = ob;
-       base->flag = ob->flag;
-
        /* prepare dupli */
-       clear_sca_new_poins();  /* BGE logic */
-
-       basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
+       basen = object_add_duplicate_internal(bmain, scene, view_layer, ob, dupflag);
 
        if (basen == NULL) {
-               MEM_freeN(base);
                BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated");
                return OPERATOR_CANCELLED;
        }
 
-       basen->lay = basen->object->lay = BKE_screen_view3d_layer_active(v3d, scene);
+       BKE_scene_object_base_flag_sync_from_object(basen);
        basen->object->restrictflag &= ~OB_RESTRICT_VIEW;
 
        if (event) {
@@ -2391,20 +2586,20 @@ static int add_named_exec(bContext *C, wmOperator *op)
                const int mval[2] = {event->x - ar->winrct.xmin,
                                     event->y - ar->winrct.ymin};
                ED_object_location_from_view(C, basen->object->loc);
-               ED_view3d_cursor3d_position(C, mval, basen->object->loc);
+               ED_view3d_cursor3d_position(C, mval, false, basen->object->loc);
        }
 
-       ED_base_object_select(basen, BA_SELECT);
-       ED_base_object_activate(C, basen);
+       ED_object_base_select(basen, BA_SELECT);
+       ED_object_base_activate(C, basen);
 
        copy_object_set_idnew(C);
 
        BKE_main_id_clear_newpoins(bmain);
 
-       DAG_relations_tag_update(bmain);
-
-       MEM_freeN(base);
+       /* TODO(sergey): Only update relations for the current scene. */
+       DEG_relations_tag_update(bmain);
 
+       DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
        WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
        WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
 
@@ -2437,7 +2632,7 @@ static bool join_poll(bContext *C)
 
        if (!ob || ID_IS_LINKED(ob)) return 0;
 
-       if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE))
+       if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE, OB_GPENCIL))
                return ED_operator_screenactive(C);
        else
                return 0;
@@ -2445,10 +2640,9 @@ static bool join_poll(bContext *C)
 
 static int join_exec(bContext *C, wmOperator *op)
 {
-       Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
 
-       if (scene->obedit) {
+       if (ob->mode & OB_MODE_EDIT) {
                BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode");
                return OPERATOR_CANCELLED;
        }
@@ -2456,6 +2650,13 @@ static int join_exec(bContext *C, wmOperator *op)
                BKE_report(op->reports, RPT_ERROR, "Cannot edit external libdata");
                return OPERATOR_CANCELLED;
        }
+       else if (ob->type == OB_GPENCIL) {
+               bGPdata *gpd = (bGPdata *)ob->data;
+               if ((!gpd) || GPENCIL_ANY_MODE(gpd)) {
+                       BKE_report(op->reports, RPT_ERROR, "This data does not support joining in this mode");
+                       return OPERATOR_CANCELLED;
+               }
+       }
 
        if (ob->type == OB_MESH)
                return join_mesh_exec(C, op);
@@ -2463,6 +2664,8 @@ static int join_exec(bContext *C, wmOperator *op)
                return join_curve_exec(C, op);
        else if (ob->type == OB_ARMATURE)
                return join_armature_exec(C, op);
+       else if (ob->type == OB_GPENCIL)
+               return ED_gpencil_join_objects_exec(C, op);
 
        return OPERATOR_CANCELLED;
 }
@@ -2499,10 +2702,9 @@ static bool join_shapes_poll(bContext *C)
 
 static int join_shapes_exec(bContext *C, wmOperator *op)
 {
-       Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
 
-       if (scene->obedit) {
+       if (ob->mode & OB_MODE_EDIT) {
                BKE_report(op->reports, RPT_ERROR, "This data does not support joining in edit mode");
                return OPERATOR_CANCELLED;
        }