Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / space_view3d / space_view3d.c
index 833d54e..d4fa98c 100644 (file)
 #include "BLI_utildefines.h"
 
 #include "BKE_context.h"
-#include "BKE_depsgraph.h"
+#include "BKE_curve.h"
 #include "BKE_icons.h"
+#include "BKE_lattice.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
+#include "BKE_mball.h"
+#include "BKE_mesh.h"
 #include "BKE_object.h"
 #include "BKE_scene.h"
 #include "BKE_screen.h"
+#include "BKE_workspace.h"
 
 #include "ED_space_api.h"
 #include "ED_screen.h"
+#include "ED_transform.h"
 
-#include "GPU_compositing.h"
 #include "GPU_framebuffer.h"
 #include "GPU_material.h"
+#include "GPU_viewport.h"
+#include "GPU_matrix.h"
 
-#include "BIF_gl.h"
+#include "DRW_engine.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
 
 #include "RE_engine.h"
 #include "RE_pipeline.h"
 
 #include "RNA_access.h"
 
+#include "UI_interface.h"
 #include "UI_resources.h"
 
 #ifdef WITH_PYTHON
@@ -106,17 +115,17 @@ ARegion *view3d_has_buttons_region(ScrArea *sa)
 
 ARegion *view3d_has_tools_region(ScrArea *sa)
 {
-       ARegion *ar, *artool = NULL, *arprops = NULL, *arhead;
+       ARegion *ar, *artool = NULL, *arhead;
 
        for (ar = sa->regionbase.first; ar; ar = ar->next) {
                if (ar->regiontype == RGN_TYPE_TOOLS)
                        artool = ar;
-               if (ar->regiontype == RGN_TYPE_TOOL_PROPS)
-                       arprops = ar;
        }
 
        /* tool region hide/unhide also hides props */
-       if (arprops && artool) return artool;
+       if (artool) {
+               return artool;
+       }
 
        if (artool == NULL) {
                /* add subdiv level; after header */
@@ -135,15 +144,6 @@ ARegion *view3d_has_tools_region(ScrArea *sa)
                artool->flag = RGN_FLAG_HIDDEN;
        }
 
-       if (arprops == NULL) {
-               /* add extra subdivided region for tool properties */
-               arprops = MEM_callocN(sizeof(ARegion), "tool props for view3d");
-
-               BLI_insertlinkafter(&sa->regionbase, artool, arprops);
-               arprops->regiontype = RGN_TYPE_TOOL_PROPS;
-               arprops->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
-       }
-
        return artool;
 }
 
@@ -250,7 +250,7 @@ void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d)
        /* we have to multiply instead of loading viewmatob to make
         * it work with duplis using displists, otherwise it will
         * override the dupli-matrix */
-       glMultMatrixf(ob->obmat);
+       gpuMultMatrix(ob->obmat);
 }
 
 #ifdef DEBUG
@@ -283,8 +283,6 @@ void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar)
                BPy_END_ALLOW_THREADS;
 #endif
 
-               if (rv3d->render_engine->re)
-                       RE_Database_Free(rv3d->render_engine->re);
                RE_engine_free(rv3d->render_engine);
                rv3d->render_engine = NULL;
        }
@@ -306,9 +304,8 @@ void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
 
 /* ******************** default callbacks for view3d space ***************** */
 
-static SpaceLink *view3d_new(const bContext *C)
+static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene)
 {
-       Scene *scene = CTX_data_scene(C);
        ARegion *ar;
        View3D *v3d;
        RegionView3D *rv3d;
@@ -325,19 +322,24 @@ static SpaceLink *view3d_new(const bContext *C)
        v3d->gridlines = 16;
        v3d->gridsubdiv = 10;
        v3d->drawtype = OB_SOLID;
+       v3d->shading.flag = V3D_SHADING_SPECULAR_HIGHLIGHT;
+       v3d->shading.light = V3D_LIGHTING_STUDIO;
+       v3d->shading.shadow_intensity = 0.5f;
+       v3d->shading.xray_alpha = 0.5f;
+       copy_v3_fl(v3d->shading.single_color, 0.8f);
+
+       v3d->overlay.flag = V3D_OVERLAY_LOOK_DEV;
 
        v3d->gridflag = V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_FLOOR;
 
        v3d->flag = V3D_SELECT_OUTLINE;
        v3d->flag2 = V3D_SHOW_RECONSTRUCTION | V3D_SHOW_GPENCIL;
 
-       v3d->lens = 35.0f;
+       v3d->lens = 50.0f;
        v3d->near = 0.01f;
        v3d->far = 1000.0f;
 
-       v3d->twflag |= U.tw_flag & V3D_USE_MANIPULATOR;
-       v3d->twtype = V3D_MANIP_TRANSLATE;
-       v3d->around = V3D_AROUND_CENTER_MEAN;
+       v3d->twflag |= U.manipulator_flag & V3D_MANIPULATOR_DRAW;
 
        v3d->bundle_size = 0.2f;
        v3d->bundle_drawtype = OB_PLAINAXES;
@@ -353,7 +355,7 @@ static SpaceLink *view3d_new(const bContext *C)
 
        BLI_addtail(&v3d->regionbase, ar);
        ar->regiontype = RGN_TYPE_HEADER;
-       ar->alignment = RGN_ALIGN_BOTTOM;
+       ar->alignment = RGN_ALIGN_TOP;
 
        /* tool shelf */
        ar = MEM_callocN(sizeof(ARegion), "toolshelf for view3d");
@@ -363,14 +365,6 @@ static SpaceLink *view3d_new(const bContext *C)
        ar->alignment = RGN_ALIGN_LEFT;
        ar->flag = RGN_FLAG_HIDDEN;
 
-       /* tool properties */
-       ar = MEM_callocN(sizeof(ARegion), "tool properties for view3d");
-
-       BLI_addtail(&v3d->regionbase, ar);
-       ar->regiontype = RGN_TYPE_TOOL_PROPS;
-       ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
-       ar->flag = RGN_FLAG_HIDDEN;
-
        /* buttons/list view */
        ar = MEM_callocN(sizeof(ARegion), "buttons for view3d");
 
@@ -399,30 +393,11 @@ static SpaceLink *view3d_new(const bContext *C)
 static void view3d_free(SpaceLink *sl)
 {
        View3D *vd = (View3D *) sl;
-       BGpic *bgpic;
-
-       for (bgpic = vd->bgpicbase.first; bgpic; bgpic = bgpic->next) {
-               if (bgpic->source == V3D_BGPIC_IMAGE) {
-                       id_us_min((ID *)bgpic->ima);
-               }
-               else if (bgpic->source == V3D_BGPIC_MOVIE) {
-                       id_us_min((ID *)bgpic->clip);
-               }
-       }
-       BLI_freelistN(&vd->bgpicbase);
 
        if (vd->localvd) MEM_freeN(vd->localvd);
 
        if (vd->properties_storage) MEM_freeN(vd->properties_storage);
 
-       /* matcap material, its preview rect gets freed via icons */
-       if (vd->defmaterial) {
-               if (vd->defmaterial->gpumaterial.first)
-                       GPU_material_free(&vd->defmaterial->gpumaterial);
-               BKE_previewimg_free(&vd->defmaterial->preview);
-               MEM_freeN(vd->defmaterial);
-       }
-
        if (vd->fx_settings.ssao)
                MEM_freeN(vd->fx_settings.ssao);
        if (vd->fx_settings.dof)
@@ -440,7 +415,6 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
 {
        View3D *v3do = (View3D *)sl;
        View3D *v3dn = MEM_dupallocN(sl);
-       BGpic *bgpic;
 
        /* clear or remove stuff from old */
 
@@ -455,18 +429,6 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
 
        /* copy or clear inside new stuff */
 
-       v3dn->defmaterial = NULL;
-
-       BLI_duplicatelist(&v3dn->bgpicbase, &v3do->bgpicbase);
-       for (bgpic = v3dn->bgpicbase.first; bgpic; bgpic = bgpic->next) {
-               if (bgpic->source == V3D_BGPIC_IMAGE) {
-                       id_us_plus((ID *)bgpic->ima);
-               }
-               else if (bgpic->source == V3D_BGPIC_MOVIE) {
-                       id_us_plus((ID *)bgpic->clip);
-               }
-       }
-
        v3dn->properties_storage = NULL;
        if (v3dn->fx_settings.dof)
                v3dn->fx_settings.dof = MEM_dupallocN(v3do->fx_settings.dof);
@@ -482,6 +444,13 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar)
        ListBase *lb;
        wmKeyMap *keymap;
 
+       if (ar->manipulator_map == NULL) {
+               ar->manipulator_map = WM_manipulatormap_new_from_type(
+                       &(const struct wmManipulatorMapType_Params) {SPACE_VIEW3D, RGN_TYPE_WINDOW});
+       }
+
+       WM_manipulatormap_add_handlers(ar, ar->manipulator_map);
+
        /* object ops. */
 
        /* important to be before Pose keymap since they can both be enabled at once */
@@ -572,11 +541,6 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar)
                GPU_offscreen_free(rv3d->gpuoffscreen);
                rv3d->gpuoffscreen = NULL;
        }
-
-       if (rv3d->compositor) {
-               GPU_fx_compositor_destroy(rv3d->compositor);
-               rv3d->compositor = NULL;
-       }
 }
 
 static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
@@ -589,7 +553,7 @@ static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent
        return 0;
 }
 
-static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
+static int view3d_collection_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
 {
        if (drag->type == WM_DRAG_ID) {
                ID *id = drag->poin;
@@ -664,7 +628,7 @@ static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop)
        RNA_string_set(drop->ptr, "name", id->name + 2);
 }
 
-static void view3d_group_drop_copy(wmDrag *drag, wmDropBox *drop)
+static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop)
 {
        ID *id = drag->poin;
 
@@ -704,9 +668,32 @@ static void view3d_dropboxes(void)
        WM_dropbox_add(lb, "MESH_OT_drop_named_image", view3d_ima_mesh_drop_poll, view3d_id_path_drop_copy);
        WM_dropbox_add(lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy);
        WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy);
-       WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy);
+       WM_dropbox_add(lb, "OBJECT_OT_collection_instance_add", view3d_collection_drop_poll, view3d_collection_drop_copy);
 }
 
+static void view3d_widgets(void)
+{
+       wmManipulatorMapType *mmap_type = WM_manipulatormaptype_ensure(
+               &(const struct wmManipulatorMapType_Params){SPACE_VIEW3D, RGN_TYPE_WINDOW});
+
+       WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_spot);
+       WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_area);
+       WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_lamp_target);
+       WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_force_field);
+       WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_camera);
+       WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_camera_view);
+       WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_empty_image);
+       WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_armature_spline);
+
+       WM_manipulatorgrouptype_append(TRANSFORM_WGT_manipulator);
+       WM_manipulatorgrouptype_append(VIEW3D_WGT_xform_cage);
+
+       WM_manipulatorgrouptype_append(VIEW3D_WGT_ruler);
+       WM_manipulatortype_append(VIEW3D_WT_ruler_item);
+
+       WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_navigate);
+       WM_manipulatortype_append(VIEW3D_WT_navigate_rotate);
+}
 
 
 /* type callback, not region itself */
@@ -731,9 +718,6 @@ static void view3d_main_region_free(ARegion *ar)
                if (rv3d->gpuoffscreen) {
                        GPU_offscreen_free(rv3d->gpuoffscreen);
                }
-               if (rv3d->compositor) {
-                       GPU_fx_compositor_destroy(rv3d->compositor);
-               }
 
                MEM_freeN(rv3d);
                ar->regiondata = NULL;
@@ -757,33 +741,21 @@ static void *view3d_main_region_duplicate(void *poin)
                new->render_engine = NULL;
                new->sms = NULL;
                new->smooth_timer = NULL;
-               new->compositor = NULL;
 
                return new;
        }
        return NULL;
 }
 
-static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene)
+static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene))
 {
        wmWindow *win = wmn->wm->winactive;
-       ScrArea *sa;
        unsigned int lay_used = 0;
-       Base *base;
 
        if (!win) return;
 
-       base = scene->base.first;
-       while (base) {
-               lay_used |= base->lay & ((1 << 20) - 1); /* ignore localview */
-
-               if (lay_used == (1 << 20) - 1)
-                       break;
-
-               base = base->next;
-       }
-
-       for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+       const bScreen *screen = WM_window_get_active_screen(win);
+       for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
                if (sa->spacetype == SPACE_VIEW3D) {
                        if (BLI_findindex(&sa->regionbase, ar) != -1) {
                                View3D *v3d = sa->spacedata.first;
@@ -794,13 +766,21 @@ static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene
        }
 }
 
-static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmNotifier *wmn)
+static void view3d_main_region_listener(
+        bScreen *UNUSED(sc), ScrArea *sa, ARegion *ar,
+        wmNotifier *wmn, const Scene *scene)
 {
-       Scene *scene = sc->scene;
        View3D *v3d = sa->spacedata.first;
+       RegionView3D *rv3d = ar->regiondata;
+       wmManipulatorMap *mmap = ar->manipulator_map;
 
        /* context changes */
        switch (wmn->category) {
+               case NC_WM:
+                       if (ELEM(wmn->data, ND_UNDO)) {
+                               WM_manipulatormap_tag_refresh(mmap);
+                       }
+                       break;
                case NC_ANIMATION:
                        switch (wmn->data) {
                                case ND_KEYFRAME_PROP:
@@ -820,21 +800,32 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
                        break;
                case NC_SCENE:
                        switch (wmn->data) {
+                               case ND_SCENEBROWSE:
                                case ND_LAYER_CONTENT:
                                        if (wmn->reference)
                                                view3d_recalc_used_layers(ar, wmn, wmn->reference);
                                        ED_region_tag_redraw(ar);
+                                       WM_manipulatormap_tag_refresh(mmap);
+                                       break;
+                               case ND_LAYER:
+                                       if (wmn->reference) {
+                                               BKE_screen_view3d_sync(v3d, wmn->reference);
+                                       }
+                                       ED_region_tag_redraw(ar);
+                                       WM_manipulatormap_tag_refresh(mmap);
                                        break;
-                               case ND_FRAME:
-                               case ND_TRANSFORM:
                                case ND_OB_ACTIVE:
                                case ND_OB_SELECT:
+                                       DEG_id_tag_update((ID *)&scene->id, DEG_TAG_SELECT_UPDATE);
+                                       ATTR_FALLTHROUGH;
+                               case ND_FRAME:
+                               case ND_TRANSFORM:
                                case ND_OB_VISIBLE:
-                               case ND_LAYER:
                                case ND_RENDER_OPTIONS:
                                case ND_MARKERS:
                                case ND_MODE:
                                        ED_region_tag_redraw(ar);
+                                       WM_manipulatormap_tag_refresh(mmap);
                                        break;
                                case ND_WORLD:
                                        /* handled by space_view3d_listener() for v3d access */
@@ -842,7 +833,6 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
                                case ND_DRAW_RENDER_VIEWPORT:
                                {
                                        if (v3d->camera && (scene == wmn->reference)) {
-                                               RegionView3D *rv3d = ar->regiondata;
                                                if (rv3d->persp == RV3D_CAMOB) {
                                                        ED_region_tag_redraw(ar);
                                                }
@@ -867,6 +857,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
                                case ND_POINTCACHE:
                                case ND_LOD:
                                        ED_region_tag_redraw(ar);
+                                       WM_manipulatormap_tag_refresh(mmap);
                                        break;
                        }
                        switch (wmn->action) {
@@ -877,9 +868,25 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
                        break;
                case NC_GEOM:
                        switch (wmn->data) {
+                               case ND_SELECT:
+                               {
+                                       WM_manipulatormap_tag_refresh(mmap);
+
+                                       ID *ob_data = wmn->reference;
+                                       if (ob_data == NULL) {
+                                               BLI_assert(wmn->window); // Use `WM_event_add_notifier` instead of `WM_main_add_notifier`
+                                               ViewLayer *view_layer = WM_window_get_active_view_layer(wmn->window);
+                                               ob_data = OBEDIT_FROM_VIEW_LAYER(view_layer)->data;
+                                       }
+                                       if (ob_data) {
+                                               BLI_assert(OB_DATA_SUPPORT_ID(GS(ob_data->name)));
+                                               /* TODO(sergey): Notifiers shouldn't really be doing DEG tags. */
+                                               DEG_id_tag_update(ob_data, DEG_TAG_SELECT_UPDATE);
+                                       }
+                                       ATTR_FALLTHROUGH;
+                               }
                                case ND_DATA:
                                case ND_VERTEX_GROUP:
-                               case ND_SELECT:
                                        ED_region_tag_redraw(ar);
                                        break;
                        }
@@ -894,7 +901,6 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
                                case ND_DRAW_RENDER_VIEWPORT:
                                {
                                        if (v3d->camera && (v3d->camera->data == wmn->reference)) {
-                                               RegionView3D *rv3d = ar->regiondata;
                                                if (rv3d->persp == RV3D_CAMOB) {
                                                        ED_region_tag_redraw(ar);
                                                }
@@ -923,21 +929,13 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
                        switch (wmn->data) {
                                case ND_SHADING:
                                case ND_NODES:
-                               {
-#ifdef WITH_LEGACY_DEPSGRAPH
-                                       Object *ob = OBACT;
-                                       if ((v3d->drawtype == OB_MATERIAL) ||
-                                           (ob && (ob->mode == OB_MODE_TEXTURE_PAINT)) ||
-                                           (v3d->drawtype == OB_TEXTURE &&
-                                            (scene->gm.matmode == GAME_MAT_GLSL ||
-                                             BKE_scene_use_new_shading_nodes(scene))) ||
-                                           !DEG_depsgraph_use_legacy())
-#endif
-                                       {
-                                               ED_region_tag_redraw(ar);
-                                       }
+                                       /* TODO(sergey) This is a bit too much updates, but needed to
+                                        * have proper material drivers update in the viewport.
+                                        *
+                                        * How to solve?
+                                        */
+                                       ED_region_tag_redraw(ar);
                                        break;
-                               }
                                case ND_SHADING_DRAW:
                                case ND_SHADING_LINKS:
                                        ED_region_tag_redraw(ar);
@@ -949,20 +947,23 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
                                case ND_WORLD_DRAW:
                                        /* handled by space_view3d_listener() for v3d access */
                                        break;
+                               case ND_WORLD:
+                                       /* Needed for updating world materials */
+                                       ED_region_tag_redraw(ar);
+                                       break;
                        }
                        break;
                case NC_LAMP:
                        switch (wmn->data) {
                                case ND_LIGHTING:
-                                       if ((v3d->drawtype == OB_MATERIAL) ||
-                                           (v3d->drawtype == OB_TEXTURE && (scene->gm.matmode == GAME_MAT_GLSL)) ||
-                                           !DEG_depsgraph_use_legacy())
-                                       {
-                                               ED_region_tag_redraw(ar);
-                                       }
+                                       /* TODO(sergey): This is a bit too much, but needed to
+                                        * handle updates from new depsgraph.
+                                        */
+                                       ED_region_tag_redraw(ar);
                                        break;
                                case ND_LIGHTING_DRAW:
                                        ED_region_tag_redraw(ar);
+                                       WM_manipulatormap_tag_refresh(mmap);
                                        break;
                        }
                        break;
@@ -982,10 +983,10 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
                case NC_SPACE:
                        if (wmn->data == ND_SPACE_VIEW3D) {
                                if (wmn->subtype == NS_VIEW3D_GPU) {
-                                       RegionView3D *rv3d = ar->regiondata;
                                        rv3d->rflag |= RV3D_GPULIGHT_UPDATE;
                                }
                                ED_region_tag_redraw(ar);
+                               WM_manipulatormap_tag_refresh(mmap);
                        }
                        break;
                case NC_ID:
@@ -998,15 +999,13 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
                                case ND_SKETCH:
                                        ED_region_tag_redraw(ar);
                                        break;
-                               case ND_SCREENBROWSE:
-                               case ND_SCREENDELETE:
-                               case ND_SCREENSET:
-                                       /* screen was changed, need to update used layers due to NC_SCENE|ND_LAYER_CONTENT */
-                                       /* updates used layers only for View3D in active screen */
-                                       if (wmn->reference) {
-                                               bScreen *sc_ref = wmn->reference;
-                                               view3d_recalc_used_layers(ar, wmn, sc_ref->scene);
-                                       }
+                               case ND_LAYOUTBROWSE:
+                               case ND_LAYOUTDELETE:
+                               case ND_LAYOUTSET:
+                                       WM_manipulatormap_tag_refresh(mmap);
+                                       ED_region_tag_redraw(ar);
+                                       break;
+                               case ND_LAYER:
                                        ED_region_tag_redraw(ar);
                                        break;
                        }
@@ -1020,12 +1019,118 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
        }
 }
 
+static void view3d_main_region_message_subscribe(
+        const struct bContext *C,
+        struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene),
+        struct bScreen *UNUSED(screen), struct ScrArea *sa, struct ARegion *ar,
+        struct wmMsgBus *mbus)
+{
+       /* Developer note: there are many properties that impact 3D view drawing,
+        * so instead of subscribing to individual properties, just subscribe to types
+        * accepting some redundant redraws.
+        *
+        * For other space types we might try avoid this, keep the 3D view as an exceptional case! */
+       wmMsgParams_RNA msg_key_params = {{{0}}};
+
+       /* Only subscribe to types. */
+       StructRNA *type_array[] = {
+               &RNA_Window,
+
+               /* These object have properties that impact drawing. */
+               &RNA_AreaLamp,
+               &RNA_Camera,
+               &RNA_Lamp,
+               &RNA_Speaker,
+               &RNA_SunLamp,
+
+               /* General types the 3D view depends on. */
+               &RNA_Object,
+               &RNA_UnitSettings,  /* grid-floor */
+
+               &RNA_View3DOverlay,
+               &RNA_View3DShading,
+               &RNA_World,
+       };
+
+       wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+               .owner = ar,
+               .user_data = ar,
+               .notify = ED_region_do_msg_notify_tag_redraw,
+       };
+
+       for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
+               msg_key_params.ptr.type = type_array[i];
+               WM_msg_subscribe_rna_params(
+                       mbus,
+                       &msg_key_params,
+                       &msg_sub_value_region_tag_redraw,
+                       __func__);
+       }
+
+       /* Subscribe to a handful of other properties. */
+       RegionView3D *rv3d = ar->regiondata;
+
+       WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, engine, &msg_sub_value_region_tag_redraw);
+       WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_region_tag_redraw);
+       WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_region_tag_redraw);
+       WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_region_tag_redraw);
+       WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_region_tag_redraw);
+       if (rv3d->persp == RV3D_CAMOB) {
+               WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, use_border, &msg_sub_value_region_tag_redraw);
+       }
+
+       WM_msg_subscribe_rna_anon_type(mbus, SceneEEVEE, &msg_sub_value_region_tag_redraw);
+       WM_msg_subscribe_rna_anon_type(mbus, SceneDisplay, &msg_sub_value_region_tag_redraw);
+       WM_msg_subscribe_rna_anon_type(mbus, ObjectDisplay, &msg_sub_value_region_tag_redraw);
+
+       ViewLayer *view_layer = CTX_data_view_layer(C);
+       Object *obact = OBACT(view_layer);
+       if (obact != NULL) {
+               switch (obact->mode) {
+                       case OB_MODE_PARTICLE_EDIT:
+                               WM_msg_subscribe_rna_anon_type(mbus, ParticleEdit, &msg_sub_value_region_tag_redraw);
+                               break;
+                       default:
+                               break;
+               }
+       }
+
+       {
+               wmMsgSubscribeValue msg_sub_value_region_tag_refresh = {
+                       .owner = ar,
+                       .user_data = sa,
+                       .notify = WM_toolsystem_do_msg_notify_tag_refresh,
+               };
+               WM_msg_subscribe_rna_anon_prop(
+                       mbus, Object, mode,
+                       &msg_sub_value_region_tag_refresh);
+       }
+}
+
+static void view3d_tools_region_message_subscribe(
+        const struct bContext *UNUSED(C),
+        struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene),
+        struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
+        struct wmMsgBus *mbus)
+{
+       wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+               .owner = ar,
+               .user_data = ar,
+               .notify = ED_region_do_msg_notify_tag_redraw,
+       };
+       WM_msg_subscribe_rna_anon_prop(mbus, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
+}
+
 /* concept is to retrieve cursor type context-less */
-static void view3d_main_region_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar))
+static void view3d_main_region_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
 {
-       Scene *scene = win->screen->scene;
+       if (WM_cursor_set_from_tool(win, sa, ar)) {
+               return;
+       }
 
-       if (scene->obedit) {
+       ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+       Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
+       if (obedit) {
                WM_cursor_set(win, CURSOR_EDIT);
        }
        else {
@@ -1048,7 +1153,9 @@ static void view3d_header_region_draw(const bContext *C, ARegion *ar)
        ED_region_header(C, ar);
 }
 
-static void view3d_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void view3d_header_region_listener(
+        bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+        wmNotifier *wmn, const Scene *UNUSED(scene))
 {
        /* context changes */
        switch (wmn->category) {
@@ -1078,6 +1185,36 @@ static void view3d_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(s
        }
 }
 
+static void view3d_header_region_message_subscribe(
+        const struct bContext *UNUSED(C),
+        struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene),
+        struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
+        struct wmMsgBus *mbus)
+{
+       wmMsgParams_RNA msg_key_params = {{{0}}};
+
+       /* Only subscribe to types. */
+       StructRNA *type_array[] = {
+               &RNA_View3DShading,
+       };
+
+       wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+               .owner = ar,
+               .user_data = ar,
+               .notify = ED_region_do_msg_notify_tag_redraw,
+       };
+
+       for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
+               msg_key_params.ptr.type = type_array[i];
+               WM_msg_subscribe_rna_params(
+                       mbus,
+                       &msg_key_params,
+                       &msg_sub_value_region_tag_redraw,
+                       __func__);
+       }
+}
+
+
 /* add handlers, stuff you only do once or on area/region changes */
 static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar)
 {
@@ -1094,7 +1231,9 @@ static void view3d_buttons_region_draw(const bContext *C, ARegion *ar)
        ED_region_panels(C, ar, NULL, -1, true);
 }
 
-static void view3d_buttons_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void view3d_buttons_region_listener(
+        bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar,
+        wmNotifier *wmn, const Scene *UNUSED(scene))
 {
        /* context changes */
        switch (wmn->category) {
@@ -1184,6 +1323,27 @@ static void view3d_buttons_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(
        }
 }
 
+static int view3d_tools_region_snap_size(const ARegion *ar, int size, int axis)
+{
+       if (axis == 0) {
+               /* Note, this depends on the icon size: see #ICON_DEFAULT_HEIGHT_TOOLBAR. */
+               const float snap_units[] = {3 + 0.25f, 5 + 0.25};
+               const float aspect = BLI_rctf_size_x(&ar->v2d.cur) / (BLI_rcti_size_x(&ar->v2d.mask) + 1);
+               int best_diff = INT_MAX;
+               int best_size = size;
+               for (uint i = 0; i < ARRAY_SIZE(snap_units); i += 1) {
+                       const int test_size = (snap_units[i] * U.widget_unit) / (UI_DPI_FAC * aspect);
+                       const int test_diff = ABS(test_size - size);
+                       if (test_diff < best_diff) {
+                               best_size = test_size;
+                               best_diff = test_diff;
+                       }
+               }
+               return best_size;
+       }
+       return size;
+}
+
 /* add handlers, stuff you only do once or on area/region changes */
 static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar)
 {
@@ -1197,30 +1357,13 @@ static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar)
 
 static void view3d_tools_region_draw(const bContext *C, ARegion *ar)
 {
-       ED_region_panels(C, ar, CTX_data_mode_string(C), -1, true);
-}
-
-static void view3d_props_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
-{
-       /* context changes */
-       switch (wmn->category) {
-               case NC_WM:
-                       if (wmn->data == ND_HISTORY)
-                               ED_region_tag_redraw(ar);
-                       break;
-               case NC_SCENE:
-                       if (wmn->data == ND_MODE)
-                               ED_region_tag_redraw(ar);
-                       break;
-               case NC_SPACE:
-                       if (wmn->data == ND_SPACE_VIEW3D)
-                               ED_region_tag_redraw(ar);
-                       break;
-       }
+       ED_region_panels(C, ar, (const char * []){CTX_data_mode_string(C), NULL}, -1, true);
 }
 
 /* area (not region) level listener */
-static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNotifier *wmn)
+static void space_view3d_listener(
+        bScreen *UNUSED(sc), ScrArea *sa, struct wmNotifier *wmn, Scene *UNUSED(scene),
+        WorkSpace *UNUSED(workspace))
 {
        View3D *v3d = sa->spacedata.first;
 
@@ -1255,8 +1398,6 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot
 }
 
 const char *view3d_context_dir[] = {
-       "selected_objects", "selected_bases", "selected_editable_objects",
-       "selected_editable_bases", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases",
        "active_base", "active_object", NULL
 };
 
@@ -1267,109 +1408,27 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
        if (CTX_data_dir(member)) {
                CTX_data_dir_set(result, view3d_context_dir);
        }
-       else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
-               View3D *v3d = CTX_wm_view3d(C);
-               Scene *scene = CTX_data_scene(C);
-               const unsigned int lay = v3d ? v3d->lay : scene->lay;
-               Base *base;
-               const bool selected_objects = CTX_data_equals(member, "selected_objects");
-
-               for (base = scene->base.first; base; base = base->next) {
-                       if ((base->flag & SELECT) && (base->lay & lay)) {
-                               if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) {
-                                       if (selected_objects)
-                                               CTX_data_id_list_add(result, &base->object->id);
-                                       else
-                                               CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
-                               }
-                       }
-               }
-               CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
-               return 1;
-       }
-       else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) {
-               View3D *v3d = CTX_wm_view3d(C);
-               Scene *scene = CTX_data_scene(C);
-               const unsigned int lay = v3d ? v3d->lay : scene->lay;
-               Base *base;
-               const bool selected_editable_objects = CTX_data_equals(member, "selected_editable_objects");
-
-               for (base = scene->base.first; base; base = base->next) {
-                       if ((base->flag & SELECT) && (base->lay & lay)) {
-                               if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) {
-                                       if (0 == BKE_object_is_libdata(base->object)) {
-                                               if (selected_editable_objects)
-                                                       CTX_data_id_list_add(result, &base->object->id);
-                                               else
-                                                       CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
-                                       }
-                               }
-                       }
-               }
-               CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
-               return 1;
-       }
-       else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) {
-               View3D *v3d = CTX_wm_view3d(C);
-               Scene *scene = CTX_data_scene(C);
-               const unsigned int lay = v3d ? v3d->lay : scene->lay;
-               Base *base;
-               const bool visible_objects = CTX_data_equals(member, "visible_objects");
-
-               for (base = scene->base.first; base; base = base->next) {
-                       if (base->lay & lay) {
-                               if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) {
-                                       if (visible_objects)
-                                               CTX_data_id_list_add(result, &base->object->id);
-                                       else
-                                               CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
-                               }
-                       }
-               }
-               CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
-               return 1;
-       }
-       else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) {
-               View3D *v3d = CTX_wm_view3d(C);
-               Scene *scene = CTX_data_scene(C);
-               const unsigned int lay = v3d ? v3d->lay : scene->lay;
-               Base *base;
-               const bool selectable_objects = CTX_data_equals(member, "selectable_objects");
-
-               for (base = scene->base.first; base; base = base->next) {
-                       if (base->lay & lay) {
-                               if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) {
-                                       if (selectable_objects)
-                                               CTX_data_id_list_add(result, &base->object->id);
-                                       else
-                                               CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
-                               }
-                       }
-               }
-               CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
-               return 1;
-       }
        else if (CTX_data_equals(member, "active_base")) {
-               View3D *v3d = CTX_wm_view3d(C);
                Scene *scene = CTX_data_scene(C);
-               const unsigned int lay = v3d ? v3d->lay : scene->lay;
-               if (scene->basact && (scene->basact->lay & lay)) {
-                       Object *ob = scene->basact->object;
+               ViewLayer *view_layer = CTX_data_view_layer(C);
+               if (view_layer->basact) {
+                       Object *ob = view_layer->basact->object;
                        /* if hidden but in edit mode, we still display, can happen with animation */
-                       if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT))
-                               CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, scene->basact);
+                       if ((view_layer->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT)) {
+                               CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact);
+                       }
                }
 
                return 1;
        }
        else if (CTX_data_equals(member, "active_object")) {
-               View3D *v3d = CTX_wm_view3d(C);
-               Scene *scene = CTX_data_scene(C);
-               const unsigned int lay = v3d ? v3d->lay : scene->lay;
-               if (scene->basact && (scene->basact->lay & lay)) {
-                       Object *ob = scene->basact->object;
-                       if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT))
-                               CTX_data_id_pointer_set(result, &scene->basact->object->id);
+               ViewLayer *view_layer = CTX_data_view_layer(C);
+               if (view_layer->basact) {
+                       Object *ob = view_layer->basact->object;
+                       /* if hidden but in edit mode, we still display, can happen with animation */
+                       if ((view_layer->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT) != 0) {
+                               CTX_data_id_pointer_set(result, &ob->id);
+                       }
                }
 
                return 1;
@@ -1410,8 +1469,6 @@ static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_i
 
                /* Values in local-view aren't used, see: T52663 */
                if (is_local == false) {
-                       /* Skip 'v3d->defmaterial', it's not library data.  */
-
                        if ((ID *)v3d->ob_centre == old_id) {
                                v3d->ob_centre = (Object *)new_id;
                                /* Otherwise, bonename may remain valid... We could be smart and check this, too? */
@@ -1419,21 +1476,6 @@ static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_i
                                        v3d->ob_centre_bone[0] = '\0';
                                }
                        }
-
-                       if (ELEM(GS(old_id->name), ID_IM, ID_MC)) {
-                               for (BGpic *bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
-                                       if ((ID *)bgpic->ima == old_id) {
-                                               bgpic->ima = (Image *)new_id;
-                                               id_us_min(old_id);
-                                               id_us_plus(new_id);
-                                       }
-                                       if ((ID *)bgpic->clip == old_id) {
-                                               bgpic->clip = (MovieClip *)new_id;
-                                               id_us_min(old_id);
-                                               id_us_plus(new_id);
-                                       }
-                               }
-                       }
                }
 
                if (is_local) {
@@ -1459,6 +1501,7 @@ void ED_spacetype_view3d(void)
        st->operatortypes = view3d_operatortypes;
        st->keymap = view3d_keymap;
        st->dropboxes = view3d_dropboxes;
+       st->manipulators = view3d_widgets;
        st->context = view3d_context;
        st->id_remap = view3d_id_remap;
 
@@ -1472,6 +1515,7 @@ void ED_spacetype_view3d(void)
        art->free = view3d_main_region_free;
        art->duplicate = view3d_main_region_duplicate;
        art->listener = view3d_main_region_listener;
+       art->message_subscribe = view3d_main_region_message_subscribe;
        art->cursor = view3d_main_region_cursor;
        art->lock = 1;   /* can become flag, see BKE_spacedata_draw_locks */
        BLI_addhead(&st->regiontypes, art);
@@ -1495,6 +1539,8 @@ void ED_spacetype_view3d(void)
        art->prefsizey = 50; /* XXX */
        art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
        art->listener = view3d_buttons_region_listener;
+       art->message_subscribe = view3d_tools_region_message_subscribe;
+       art->snap_size = view3d_tools_region_snap_size;
        art->init = view3d_tools_region_init;
        art->draw = view3d_tools_region_draw;
        BLI_addhead(&st->regiontypes, art);
@@ -1504,20 +1550,6 @@ void ED_spacetype_view3d(void)
        view3d_toolshelf_register(art);
 #endif
 
-       /* regions: tool properties */
-       art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tool properties region");
-       art->regionid = RGN_TYPE_TOOL_PROPS;
-       art->prefsizex = 0;
-       art->prefsizey = 120;
-       art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
-       art->listener = view3d_props_region_listener;
-       art->init = view3d_tools_region_init;
-       art->draw = view3d_tools_region_draw;
-       BLI_addhead(&st->regiontypes, art);
-
-       view3d_tool_props_register(art);
-
-
        /* regions: header */
        art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region");
        art->regionid = RGN_TYPE_HEADER;
@@ -1526,8 +1558,8 @@ void ED_spacetype_view3d(void)
        art->listener = view3d_header_region_listener;
        art->init = view3d_header_region_init;
        art->draw = view3d_header_region_draw;
+       art->message_subscribe = view3d_header_region_message_subscribe;
        BLI_addhead(&st->regiontypes, art);
 
        BKE_spacetype_register(st);
 }
-