Merge branch 'master' into blender2.8
authorBastien Montagne <montagne29@wanadoo.fr>
Thu, 7 Jun 2018 16:45:45 +0000 (18:45 +0200)
committerBastien Montagne <montagne29@wanadoo.fr>
Thu, 7 Jun 2018 16:45:45 +0000 (18:45 +0200)
Conflicts:
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/sculpt_paint/sculpt_undo.c

1  2 
source/blender/blenkernel/intern/paint.c
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/sculpt_paint/sculpt_undo.c

@@@ -41,7 -41,6 +41,7 @@@
  #include "DNA_scene_types.h"
  #include "DNA_brush_types.h"
  #include "DNA_space_types.h"
 +#include "DNA_workspace_types.h"
  
  #include "BLI_bitmap.h"
  #include "BLI_utildefines.h"
  #include "BKE_main.h"
  #include "BKE_context.h"
  #include "BKE_crazyspace.h"
 -#include "BKE_depsgraph.h"
  #include "BKE_global.h"
  #include "BKE_image.h"
  #include "BKE_key.h"
  #include "BKE_library.h"
  #include "BKE_mesh.h"
 +#include "BKE_mesh_runtime.h"
  #include "BKE_modifier.h"
  #include "BKE_object.h"
  #include "BKE_paint.h"
  #include "BKE_pbvh.h"
  #include "BKE_subsurf.h"
  
 +#include "DEG_depsgraph.h"
 +
  #include "bmesh.h"
  
  const char PAINT_CURSOR_SCULPT[3] = {255, 100, 100};
@@@ -77,9 -74,9 +77,9 @@@ const char PAINT_CURSOR_TEXTURE_PAINT[3
  
  static eOverlayControlFlags overlay_flags = 0;
  
 -void BKE_paint_invalidate_overlay_tex(Scene *scene, const Tex *tex)
 +void BKE_paint_invalidate_overlay_tex(Scene *scene, ViewLayer *view_layer, const Tex *tex)
  {
 -      Paint *p = BKE_paint_get_active(scene);
 +      Paint *p = BKE_paint_get_active(scene, view_layer);
        Brush *br = p->brush;
  
        if (!br)
@@@ -91,9 -88,9 +91,9 @@@
                overlay_flags |= PAINT_INVALID_OVERLAY_TEXTURE_SECONDARY;
  }
  
 -void BKE_paint_invalidate_cursor_overlay(Scene *scene, CurveMapping *curve)
 +void BKE_paint_invalidate_cursor_overlay(Scene *scene, ViewLayer *view_layer, CurveMapping *curve)
  {
 -      Paint *p = BKE_paint_get_active(scene);
 +      Paint *p = BKE_paint_get_active(scene, view_layer);
        Brush *br = p->brush;
  
        if (br && br->curve == curve)
@@@ -159,13 -156,13 +159,13 @@@ Paint *BKE_paint_get_active_from_paintm
        return NULL;
  }
  
 -Paint *BKE_paint_get_active(Scene *sce)
 +Paint *BKE_paint_get_active(Scene *sce, ViewLayer *view_layer)
  {
 -      if (sce) {
 +      if (sce && view_layer) {
                ToolSettings *ts = sce->toolsettings;
                
 -              if (sce->basact && sce->basact->object) {
 -                      switch (sce->basact->object->mode) {
 +              if (view_layer->basact && view_layer->basact->object) {
 +                      switch (view_layer->basact->object->mode) {
                                case OB_MODE_SCULPT:
                                        return &ts->sculpt->paint;
                                case OB_MODE_VERTEX_PAINT:
                                        if (ts->use_uv_sculpt)
                                                return &ts->uvsculpt->paint;
                                        return &ts->imapaint.paint;
 +                              default:
 +                                      break;
                        }
                }
  
  Paint *BKE_paint_get_active_from_context(const bContext *C)
  {
        Scene *sce = CTX_data_scene(C);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
        SpaceImage *sima;
  
 -      if (sce) {
 +      if (sce && view_layer) {
                ToolSettings *ts = sce->toolsettings;
                Object *obact = NULL;
  
 -              if (sce->basact && sce->basact->object)
 -                      obact = sce->basact->object;
 +              if (view_layer->basact && view_layer->basact->object)
 +                      obact = view_layer->basact->object;
  
                if ((sima = CTX_wm_space_image(C)) != NULL) {
                        if (obact && obact->mode == OB_MODE_EDIT) {
                        }
                }
                else {
 -                      return BKE_paint_get_active(sce);
 +                      return BKE_paint_get_active(sce, view_layer);
                }
        }
  
  ePaintMode BKE_paintmode_get_active_from_context(const bContext *C)
  {
        Scene *sce = CTX_data_scene(C);
 +      ViewLayer *view_layer = CTX_data_view_layer(C);
        SpaceImage *sima;
  
 -      if (sce) {
 +      if (sce && view_layer) {
                ToolSettings *ts = sce->toolsettings;
                Object *obact = NULL;
  
 -              if (sce->basact && sce->basact->object)
 -                      obact = sce->basact->object;
 +              if (view_layer->basact && view_layer->basact->object)
 +                      obact = view_layer->basact->object;
  
                if ((sima = CTX_wm_space_image(C)) != NULL) {
                        if (obact && obact->mode == OB_MODE_EDIT) {
@@@ -339,8 -332,8 +339,8 @@@ void BKE_paint_palette_set(Paint *p, Pa
  {
        if (p) {
                id_us_min((ID *)p->palette);
 -              id_us_plus((ID *)palette);
                p->palette = palette;
 +              id_us_plus((ID *)p->palette);
        }
  }
  
@@@ -348,8 -341,8 +348,8 @@@ void BKE_paint_curve_set(Brush *br, Pai
  {
        if (br) {
                id_us_min((ID *)br->paint_curve);
 -              id_us_plus((ID *)pc);
                br->paint_curve = pc;
 +              id_us_plus((ID *)br->paint_curve);
        }
  }
  
@@@ -382,7 -375,9 +382,7 @@@ void BKE_palette_clear(Palette *palette
  
  Palette *BKE_palette_add(Main *bmain, const char *name)
  {
 -      Palette *palette;
 -
 -      palette = BKE_libblock_alloc(bmain, ID_PAL, name, 0);
 +      Palette *palette = BKE_id_new(bmain, ID_PAL, name);
  
        /* enable fake user by default */
        id_fake_user_set(&palette->id);
@@@ -423,7 -418,7 +423,7 @@@ void BKE_palette_free(Palette *palette
  
  PaletteColor *BKE_palette_color_add(Palette *palette)
  {
 -      PaletteColor *color = MEM_callocN(sizeof(*color), "Pallete Color");
 +      PaletteColor *color = MEM_callocN(sizeof(*color), "Palette Color");
        BLI_addtail(&palette->colors, color);
        return color;
  }
@@@ -719,7 -714,7 +719,7 @@@ void BKE_sculptsession_bm_to_me(Object 
                sculptsession_bm_to_me_update_data_only(ob, reorder);
  
                /* ensure the objects DerivedMesh mesh doesn't hold onto arrays now realloc'd in the mesh [#34473] */
 -              DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +              DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
        }
  }
  
@@@ -729,7 -724,7 +729,7 @@@ void BKE_sculptsession_bm_to_me_for_ren
                if (object->sculpt->bm) {
                        /* Ensure no points to old arrays are stored in DM
                         *
 -                       * Apparently, we could not use DAG_id_tag_update
 +                       * Apparently, we could not use DEG_id_tag_update
                         * here because this will lead to the while object
                         * surface to disappear, so we'll release DM in place.
                         */
@@@ -860,19 -855,9 +860,19 @@@ static bool sculpt_modifiers_active(Sce
  /**
   * \param need_mask So the DerivedMesh thats returned has mask data
   */
 -void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
 -                                     bool need_pmap, bool need_mask)
 -{
 +void BKE_sculpt_update_mesh_elements(
 +        Depsgraph *depsgraph, Scene *scene, Sculpt *sd, Object *ob,
 +        bool need_pmap, bool need_mask)
 +{
 +      if (depsgraph == NULL) {
 +              /* Happens on file load.
 +               *
 +               * We do nothing in this case, it will be taken care about on depsgraph
 +               * evaluation.
 +               */
 +              return;
 +      }
 +
        DerivedMesh *dm;
        SculptSession *ss = ob->sculpt;
        Mesh *me = ob->data;
  
        ss->kb = (mmd == NULL) ? BKE_keyblock_from_object(ob) : NULL;
  
 -      dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
 +      dm = mesh_get_derived_final(depsgraph, scene, ob, CD_MASK_BAREMESH);
  
        /* VWPaint require mesh info for loop lookup, so require sculpt mode here */
        if (mmd && ob->mode & OB_MODE_SCULPT) {
  
                        ss->orig_cos = (ss->kb) ? BKE_keyblock_convert_to_vertcos(ob, ss->kb) : BKE_mesh_vertexCos_get(me, NULL);
  
 -                      BKE_crazyspace_build_sculpt(scene, ob, &ss->deform_imats, &ss->deform_cos);
 +                      BKE_crazyspace_build_sculpt(depsgraph, scene, ob, &ss->deform_imats, &ss->deform_cos);
                        BKE_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos);
  
                        for (a = 0; a < me->totvert; ++a) {
  
        /* if pbvh is deformed, key block is already applied to it */
        if (ss->kb) {
-               bool pbvh_deformd = BKE_pbvh_isDeformed(ss->pbvh);
-               if (!pbvh_deformd || ss->deform_cos == NULL) {
+               bool pbvh_deformed = BKE_pbvh_isDeformed(ss->pbvh);
+               if (!pbvh_deformed || ss->deform_cos == NULL) {
                        float (*vertCos)[3] = BKE_keyblock_convert_to_vertcos(ob, ss->kb);
  
                        if (vertCos) {
-                               if (!pbvh_deformd) {
+                               if (!pbvh_deformed) {
                                        /* apply shape keys coordinates to PBVH */
                                        BKE_pbvh_apply_vertCos(ss->pbvh, vertCos);
                                }
                        }
                }
        }
 +
 +      /* 2.8x - avoid full mesh update! */
 +      BKE_mesh_batch_cache_dirty(me, BKE_MESH_BATCH_DIRTY_SCULPT_COORDS);
  }
  
  int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd)
@@@ -54,9 -54,8 +54,9 @@@
  
  #include "BKE_brush.h"
  #include "BKE_context.h"
 -#include "BKE_depsgraph.h"
  #include "BKE_deform.h"
 +#include "BKE_global.h"
 +#include "BKE_main.h"
  #include "BKE_mesh.h"
  #include "BKE_mesh_mapping.h"
  #include "BKE_object_deform.h"
  #include "BKE_report.h"
  #include "BKE_subsurf.h"
  
 +#include "DEG_depsgraph.h"
 +
  #include "WM_api.h"
  #include "WM_types.h"
 +#include "WM_message.h"
 +#include "WM_toolsystem.h"
  
  #include "ED_object.h"
  #include "ED_mesh.h"
@@@ -208,7 -203,7 +208,7 @@@ int vertex_paint_mode_poll(bContext *C
        return ob && ob->mode == OB_MODE_VERTEX_PAINT && ((Mesh *)ob->data)->totpoly;
  }
  
 -int vertex_paint_poll(bContext *C)
 +static int vertex_paint_poll_ex(bContext *C, bool check_tool)
  {
        if (vertex_paint_mode_poll(C) &&
            BKE_paint_brush(&CTX_data_tool_settings(C)->vpaint->paint))
                ScrArea *sa = CTX_wm_area(C);
                if (sa && sa->spacetype == SPACE_VIEW3D) {
                        ARegion *ar = CTX_wm_region(C);
 -                      if (ar->regiontype == RGN_TYPE_WINDOW)
 -                              return 1;
 +                      if (ar->regiontype == RGN_TYPE_WINDOW) {
 +                              if (!check_tool || WM_toolsystem_active_tool_is_brush(C)) {
 +                                      return 1;
 +                              }
 +                      }
                }
        }
        return 0;
  }
  
 +int vertex_paint_poll(bContext *C)
 +{
 +      return vertex_paint_poll_ex(C, true);
 +}
 +
 +int vertex_paint_poll_ignore_tool(bContext *C)
 +{
 +      return vertex_paint_poll_ex(C, true);
 +}
 +
  int weight_paint_mode_poll(bContext *C)
  {
        Object *ob = CTX_data_active_object(C);
        return ob && ob->mode == OB_MODE_WEIGHT_PAINT && ((Mesh *)ob->data)->totpoly;
  }
  
 -int weight_paint_poll(bContext *C)
 +static int weight_paint_poll_ex(bContext *C, bool check_tool)
  {
        Object *ob = CTX_data_active_object(C);
        ScrArea *sa;
        {
                ARegion *ar = CTX_wm_region(C);
                if (ar->regiontype == RGN_TYPE_WINDOW) {
 -                      return 1;
 +                      if (!check_tool || WM_toolsystem_active_tool_is_brush(C)) {
 +                              return 1;
 +                      }
                }
        }
        return 0;
  }
  
 +int weight_paint_poll(bContext *C)
 +{
 +      return weight_paint_poll_ex(C, true);
 +}
 +
 +int weight_paint_poll_ignore_tool(bContext *C)
 +{
 +      return weight_paint_poll_ex(C, false);
 +}
 +
  static VPaint *new_vpaint(void)
  {
        VPaint *vp = MEM_callocN(sizeof(VPaint), "VPaint");
@@@ -967,14 -937,14 +967,14 @@@ static void do_weight_paint_vertex
  
  
  /* Toggle operator for turning vertex paint mode on or off (copied from sculpt.c) */
 -static void vertex_paint_init_session(Scene *scene, Object *ob)
 +static void vertex_paint_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob)
  {
        /* Create persistent sculpt mode data */
        BKE_sculpt_toolsettings_data_ensure(scene);
  
        if (ob->sculpt == NULL) {
                ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
-               BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, 0, false);
 -              BKE_sculpt_update_mesh_elements(scene, scene->toolsettings->sculpt, ob, false, false);
++              BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
        }
  }
  
@@@ -1061,7 -1031,8 +1061,7 @@@ static void vertex_paint_init_session_d
   * \{ */
  
  static void ed_vwpaintmode_enter_generic(
 -        wmWindowManager *wm,
 -        Scene *scene,
 +        Depsgraph *depsgraph, wmWindowManager *wm, Scene *scene,
          Object *ob, const eObjectMode mode_flag)
  {
        ob->mode |= mode_flag;
                BKE_sculptsession_free(ob);
        }
  
 -      vertex_paint_init_session(scene, ob);
 +      vertex_paint_init_session(depsgraph, scene, ob);
 +
 +      /* Flush object mode. */
 +      DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
  }
  
  void ED_object_vpaintmode_enter_ex(
 -        wmWindowManager *wm,
 +        Depsgraph *depsgraph, wmWindowManager *wm,
          Scene *scene, Object *ob)
  {
        ed_vwpaintmode_enter_generic(
 -              wm, scene, ob, OB_MODE_VERTEX_PAINT);
 +              depsgraph, wm, scene, ob, OB_MODE_VERTEX_PAINT);
  }
  void ED_object_vpaintmode_enter(struct bContext *C)
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        wmWindowManager *wm = CTX_wm_manager(C);
        Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
 -      ED_object_vpaintmode_enter_ex(wm, scene, ob);
 +      ED_object_vpaintmode_enter_ex(depsgraph, wm, scene, ob);
  }
  
  void ED_object_wpaintmode_enter_ex(
 -        wmWindowManager *wm,
 +        Depsgraph *depsgraph, wmWindowManager *wm,
          Scene *scene, Object *ob)
  {
        ed_vwpaintmode_enter_generic(
 -              wm, scene, ob, OB_MODE_WEIGHT_PAINT);
 +              depsgraph, wm, scene, ob, OB_MODE_WEIGHT_PAINT);
  }
  void ED_object_wpaintmode_enter(struct bContext *C)
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        wmWindowManager *wm = CTX_wm_manager(C);
        Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
 -      ED_object_wpaintmode_enter_ex(wm, scene, ob);
 +      ED_object_wpaintmode_enter_ex(depsgraph, wm, scene, ob);
  }
  
  /** \} */
@@@ -1191,9 -1157,6 +1191,9 @@@ static void ed_vwpaintmode_exit_generic
                ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
                ED_mesh_mirror_topo_table(NULL, NULL, 'e');
        }
 +
 +      /* Flush object mode. */
 +      DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
  }
  
  void ED_object_vpaintmode_exit_ex(Object *ob)
@@@ -1225,7 -1188,6 +1225,7 @@@ void ED_object_wpaintmode_exit(struct b
   */
  static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
  {
 +      struct wmMsgBus *mbus = CTX_wm_message_bus(C);
        Object *ob = CTX_data_active_object(C);
        const int mode_flag = OB_MODE_WEIGHT_PAINT;
        const bool is_mode_set = (ob->mode & mode_flag) != 0;
                ED_object_wpaintmode_exit_ex(ob);
        }
        else {
 +              Depsgraph *depsgraph = CTX_data_depsgraph_on_load(C);
                wmWindowManager *wm = CTX_wm_manager(C);
 -              ED_object_wpaintmode_enter_ex(wm, scene, ob);
 +              ED_object_wpaintmode_enter_ex(depsgraph, wm, scene, ob);
        }
  
        /* Weightpaint works by overriding colors in mesh,
         * exit (exit needs doing regardless because we
         * should redeform).
         */
 -      DAG_id_tag_update(&me->id, 0);
 +      DEG_id_tag_update(&me->id, 0);
  
        WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
  
 +      WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
 +
 +      WM_toolsystem_update_from_context_view3d(C);
 +
        return OPERATOR_FINISHED;
  }
  
@@@ -1440,7 -1397,6 +1440,7 @@@ static bool wpaint_stroke_test_start(bC
        bool *defbase_sel;
        SculptSession *ss = ob->sculpt;
        VPaint *vp = CTX_data_tool_settings(C)->wpaint;
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
  
        if (ED_wpaint_ensure_data(C, op->reports, WPAINT_ENSURE_MIRROR, &vgroup_index) == false) {
                return false;
        }
  
        /* If not previously created, create vertex/weight paint mode session data */
 -      vertex_paint_init_session(scene, ob);
 +      vertex_paint_init_session(depsgraph, scene, ob);
        vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
        vertex_paint_init_session_data(ts, ob);
  
@@@ -1985,8 -1941,7 +1985,8 @@@ static void wpaint_paint_leaves
  
        /* threaded loop over nodes */
        SculptThreadedTaskData data = {
 -              .sd = sd, .ob = ob, .brush = brush, .nodes = nodes, .vp = vp, .wpd = wpd, .wpi = wpi, .me = me, .C = C,
 +               .C = C, .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
 +               .vp = vp, .wpd = wpd, .wpi = wpi, .me = me,
        };
  
        /* Use this so average can modify its weight without touching the brush. */
@@@ -2214,9 -2169,7 +2214,9 @@@ static void wpaint_stroke_update_step(b
        /* also needed for "View Selected" on last stroke */
        paint_last_stroke_update(scene, vc->ar, mval);
  
 -      DAG_id_tag_update(ob->data, 0);
 +      BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
 +
 +      DEG_id_tag_update(ob->data, 0);
        WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
        swap_m4m4(wpd->vc.rv3d->persmat, mat);
  
@@@ -2280,7 -2233,7 +2280,7 @@@ static void wpaint_stroke_done(const bC
                }
        }
  
 -      DAG_id_tag_update(ob->data, 0);
 +      DEG_id_tag_update(ob->data, 0);
  
        WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
  
@@@ -2362,7 -2315,6 +2362,7 @@@ void PAINT_OT_weight_paint(wmOperatorTy
   */
  static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
  {
 +      struct wmMsgBus *mbus = CTX_wm_message_bus(C);
        Object *ob = CTX_data_active_object(C);
        const int mode_flag = OB_MODE_VERTEX_PAINT;
        const bool is_mode_set = (ob->mode & mode_flag) != 0;
                ED_object_vpaintmode_exit_ex(ob);
        }
        else {
 +              Depsgraph *depsgraph = CTX_data_depsgraph_on_load(C);
                wmWindowManager *wm = CTX_wm_manager(C);
 -              ED_object_vpaintmode_enter_ex(wm, scene, ob);
 +              ED_object_vpaintmode_enter_ex(depsgraph, wm, scene, ob);
        }
  
 +      BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
 +
        /* update modifier stack for mapping requirements */
 -      DAG_id_tag_update(&me->id, 0);
 +      DEG_id_tag_update(&me->id, 0);
  
        WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
  
 +      WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
 +
 +      WM_toolsystem_update_from_context_view3d(C);
 +
        return OPERATOR_FINISHED;
  }
  
@@@ -2479,7 -2424,6 +2479,7 @@@ static bool vpaint_stroke_test_start(bC
        Object *ob = CTX_data_active_object(C);
        Mesh *me;
        SculptSession *ss = ob->sculpt;
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
  
        /* context checks could be a poll() */
        me = BKE_mesh_from_object(ob);
        /* Create projection handle */
        if (vpd->is_texbrush) {
                ob->sculpt->building_vp_handle = true;
 -              vpd->vp_handle = ED_vpaint_proj_handle_create(scene, ob, &vpd->vertexcosnos);
 +              vpd->vp_handle = ED_vpaint_proj_handle_create(depsgraph, scene, ob, &vpd->vertexcosnos);
                ob->sculpt->building_vp_handle = false;
        }
  
        /* If not previously created, create vertex/weight paint mode session data */
 -      vertex_paint_init_session(scene, ob);
 +      vertex_paint_init_session(depsgraph, scene, ob);
        vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
        vertex_paint_init_session_data(ts, ob);
  
@@@ -2988,8 -2932,8 +2988,8 @@@ static void vpaint_paint_leaves
        const Brush *brush = ob->sculpt->cache->brush;
  
        SculptThreadedTaskData data = {
 -              .sd = sd, .ob = ob, .brush = brush, .nodes = nodes, .vp = vp, .vpd = vpd,
 -              .lcol = (uint *)me->mloopcol, .me = me, .C = C,
 +              .C = C, .sd = sd, .ob = ob, .brush = brush, .nodes = nodes, .vp = vp, .vpd = vpd,
 +              .lcol = (uint *)me->mloopcol, .me = me,
        };
        ParallelRangeSettings settings;
        BLI_parallel_range_settings_defaults(&settings);
@@@ -3126,8 -3070,6 +3126,8 @@@ static void vpaint_stroke_update_step(b
  
        swap_m4m4(vc->rv3d->persmat, mat);
  
 +      BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
 +
        if (vp->paint.brush->vertexpaint_tool == PAINT_BLEND_SMEAR) {
                memcpy(vpd->smear.color_prev, vpd->smear.color_curr, sizeof(uint) * ((Mesh *)ob->data)->totloop);
        }
        if (vpd->use_fast_update == false) {
                /* recalculate modifier stack to get new colors, slow,
                 * avoid this if we can! */
 -              DAG_id_tag_update(ob->data, 0);
 +              DEG_id_tag_update(ob->data, 0);
        }
        else {
 -              /* If using new VBO drawing, mark mcol as dirty to force colors gpu buffer refresh! */
 -              ob->derivedFinal->dirty |= DM_DIRTY_MCOL_UPDATE_DRAW;
 +              /* Flush changes through DEG. */
 +              DEG_id_tag_update(ob->data, DEG_TAG_COPY_ON_WRITE);
        }
  }
  
@@@ -56,6 -56,7 +56,6 @@@
  #include "BKE_brush.h"
  #include "BKE_ccg.h"
  #include "BKE_context.h"
 -#include "BKE_depsgraph.h"
  #include "BKE_global.h"
  #include "BKE_image.h"
  #include "BKE_key.h"
  #include "BKE_subsurf.h"
  #include "BKE_colortools.h"
  
 +#include "DEG_depsgraph.h"
 +
  #include "WM_api.h"
  #include "WM_types.h"
 +#include "WM_message.h"
 +#include "WM_toolsystem.h"
  
  #include "ED_sculpt.h"
  #include "ED_object.h"
@@@ -89,6 -86,9 +89,6 @@@
  #include "RNA_access.h"
  #include "RNA_define.h"
  
 -#include "GPU_buffers.h"
 -#include "GPU_extensions.h"
 -
  #include "UI_interface.h"
  #include "UI_resources.h"
  
@@@ -500,7 -500,8 +500,7 @@@ bool sculpt_get_redraw_rect(ARegion *ar
        return 1;
  }
  
 -void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar,
 -                                 RegionView3D *rv3d, Object *ob)
 +void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar, Object *ob)
  {
        PBVH *pbvh = ob->sculpt->pbvh;
        /* copy here, original will be used below */
  
        sculpt_extend_redraw_rect_previous(ob, &rect);
  
 -      paint_calc_redraw_planes(planes, ar, rv3d, ob, &rect);
 +      paint_calc_redraw_planes(planes, ar, ob, &rect);
  
        /* we will draw this rect, so now we can set it as the previous partial rect.
         * Note that we don't update with the union of previous/current (rect), only with
@@@ -2100,10 -2101,6 +2100,10 @@@ static void do_draw_brush(Sculpt *sd, O
        mul_v3_v3(offset, ss->cache->scale);
        mul_v3_fl(offset, bstrength);
  
 +      /* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise
 +       * initialize before threads so they can do curve mapping */
 +      curvemapping_initialize(brush->curve);
 +
        /* threaded loop over nodes */
        SculptThreadedTaskData data = {
            .sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
@@@ -4603,11 -4600,10 +4603,11 @@@ static void sculpt_stroke_modifiers_che
        SculptSession *ss = ob->sculpt;
  
        if (ss->kb || ss->modifiers_active) {
 +              Depsgraph *depsgraph = CTX_data_depsgraph(C);
                Scene *scene = CTX_data_scene(C);
                Sculpt *sd = scene->toolsettings->sculpt;
                bool need_pmap = sculpt_any_smooth_mode(brush, ss->cache, 0);
 -              BKE_sculpt_update_mesh_elements(scene, sd, ob, need_pmap, false);
 +              BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, need_pmap, false);
        }
  }
  
@@@ -4692,7 -4688,7 +4692,7 @@@ static float sculpt_raycast_init
        RegionView3D *rv3d = vc->ar->regiondata;
  
        /* TODO: what if the segment is totally clipped? (return == 0) */
 -      ED_view3d_win_to_segment(vc->ar, vc->v3d, mouse, ray_start, ray_end, true);
 +      ED_view3d_win_to_segment(vc->depsgraph, vc->ar, vc->v3d, mouse, ray_start, ray_end, true);
  
        invert_m4_m4(obimat, ob->obmat);
        mul_m4_v3(obimat, ray_start);
@@@ -4810,7 -4806,6 +4810,7 @@@ static void sculpt_brush_init_tex(cons
  
  static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op)
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
        Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
        sculpt_brush_init_tex(scene, sd, ss);
  
        is_smooth = sculpt_any_smooth_mode(brush, NULL, mode);
 -      BKE_sculpt_update_mesh_elements(scene, sd, ob, is_smooth, need_mask);
 +      BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, is_smooth, need_mask);
  
        return 1;
  }
@@@ -4868,9 -4863,11 +4868,9 @@@ static void sculpt_flush_update(bContex
  
        if (mmd)
                multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
 -      if (ob->derivedFinal) /* VBO no longer valid */
 -              GPU_drawobject_free(ob->derivedFinal);
  
        if (ss->kb || ss->modifiers_active) {
 -              DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +              DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
                ED_region_tag_redraw(ar);
        }
        else {
                        ED_region_tag_redraw_partial(ar, &r);
                }
        }
 +
 +      /* 2.8x - avoid full mesh update! */
 +      BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_SCULPT_COORDS);
  }
  
  /* Returns whether the mouse/stylus is over the mesh (1)
@@@ -4986,7 -4980,7 +4986,7 @@@ static void sculpt_stroke_update_step(b
         * Could be optimized later, but currently don't think it's so
         * much common scenario.
         *
 -       * Same applies to the DAG_id_tag_update() invoked from
 +       * Same applies to the DEG_id_tag_update() invoked from
         * sculpt_flush_update().
         */
        if (ss->modifiers_active) {
@@@ -5061,7 -5055,7 +5061,7 @@@ static void sculpt_stroke_done(const bC
  
                /* try to avoid calling this, only for e.g. linked duplicates now */
                if (((Mesh *)ob->data)->id.us > 1)
 -                      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +                      DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
  
                WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
        }
@@@ -5254,18 -5248,16 +5254,18 @@@ void sculpt_dyntopo_node_layers_add(Scu
  
  
  void sculpt_update_after_dynamic_topology_toggle(
 +        Depsgraph *depsgraph,
          Scene *scene, Object *ob)
  {
        Sculpt *sd = scene->toolsettings->sculpt;
  
        /* Create the PBVH */
 -      BKE_sculpt_update_mesh_elements(scene, sd, ob, false, false);
 +      BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, false);
        WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
  }
  
  void sculpt_dynamic_topology_enable_ex(
 +        Depsgraph *depsgraph,
          Scene *scene, Object *ob)
  {
        SculptSession *ss = ob->sculpt;
        ss->bm_log = BM_log_create(ss->bm);
  
        /* Refresh */
 -      sculpt_update_after_dynamic_topology_toggle(scene, ob);
 +      sculpt_update_after_dynamic_topology_toggle(depsgraph, scene, ob);
  }
  
  /* Free the sculpt BMesh and BMLog
   * If 'unode' is given, the BMesh's data is copied out to the unode
   * before the BMesh is deleted so that it can be restored from */
  void sculpt_dynamic_topology_disable_ex(
 +        Depsgraph *depsgraph,
          Scene *scene, Object *ob, SculptUndoNode *unode)
  {
        SculptSession *ss = ob->sculpt;
        }
  
        /* Refresh */
 -      sculpt_update_after_dynamic_topology_toggle(scene, ob);
 +      sculpt_update_after_dynamic_topology_toggle(depsgraph, scene, ob);
  }
  
  void sculpt_dynamic_topology_disable(bContext *C, SculptUndoNode *unode)
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
 -      sculpt_dynamic_topology_disable_ex(scene, ob, unode);
 +      sculpt_dynamic_topology_disable_ex(depsgraph, scene, ob, unode);
  }
  
  static void sculpt_dynamic_topology_disable_with_undo(
 -        Scene *scene, Object *ob)
 +        Depsgraph *depsgraph, Scene *scene, Object *ob)
  {
        SculptSession *ss = ob->sculpt;
        if (ss->bm) {
                sculpt_undo_push_begin("Dynamic topology disable");
                sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END);
 -              sculpt_dynamic_topology_disable_ex(scene, ob, NULL);
 +              sculpt_dynamic_topology_disable_ex(depsgraph, scene, ob, NULL);
                sculpt_undo_push_end();
        }
  }
  
  static void sculpt_dynamic_topology_enable_with_undo(
 +        Depsgraph *depsgraph,
          Scene *scene, Object *ob)
  {
        SculptSession *ss = ob->sculpt;
        if (ss->bm == NULL) {
                sculpt_undo_push_begin("Dynamic topology enable");
 -              sculpt_dynamic_topology_enable_ex(scene, ob);
 +              sculpt_dynamic_topology_enable_ex(depsgraph, scene, ob);
                sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
                sculpt_undo_push_end();
        }
  
  static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(op))
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
        SculptSession *ss = ob->sculpt;
        WM_cursor_wait(1);
  
        if (ss->bm) {
 -              sculpt_dynamic_topology_disable_with_undo(scene, ob);
 +              sculpt_dynamic_topology_disable_with_undo(depsgraph, scene, ob);
        }
        else {
 -              sculpt_dynamic_topology_enable_with_undo(scene, ob);
 +              sculpt_dynamic_topology_enable_with_undo(depsgraph, scene, ob);
        }
  
        WM_cursor_wait(0);
@@@ -5622,14 -5610,13 +5622,14 @@@ static void SCULPT_OT_symmetrize(wmOper
  
  /**** Toggle operator for turning sculpt mode on or off ****/
  
 -static void sculpt_init_session(Scene *scene, Object *ob)
 +static void sculpt_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob)
  {
        /* Create persistent sculpt mode data */
        BKE_sculpt_toolsettings_data_ensure(scene);
  
        ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
 -      BKE_sculpt_update_mesh_elements(scene, scene->toolsettings->sculpt, ob, false, false);
 +      ob->sculpt->mode_type = OB_MODE_SCULPT;
-       BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, 0, false);
++      BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
  }
  
  static int ed_object_sculptmode_flush_recalc_flag(Scene *scene, Object *ob, MultiresModifierData *mmd)
  }
  
  void ED_object_sculptmode_enter_ex(
 +        Depsgraph *depsgraph,
          Scene *scene, Object *ob,
          ReportList *reports)
  {
        /* Enter sculptmode */
        ob->mode |= mode_flag;
  
 -
        MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
  
        const int flush_recalc = ed_object_sculptmode_flush_recalc_flag(scene, ob, mmd);
  
 -      if (flush_recalc) {
 -              DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 -      }
 +      if (flush_recalc)
 +              DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
  
        /* Create sculpt mode session data */
        if (ob->sculpt) {
                BKE_sculptsession_free(ob);
        }
  
 -      sculpt_init_session(scene, ob);
 +      sculpt_init_session(depsgraph, scene, ob);
  
        /* Mask layer is required */
        if (mmd) {
                if (message_unsupported == NULL) {
                        /* undo push is needed to prevent memory leak */
                        sculpt_undo_push_begin("Dynamic topology enable");
 -                      sculpt_dynamic_topology_enable_ex(scene, ob);
 +                      sculpt_dynamic_topology_enable_ex(depsgraph, scene, ob);
                        sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN);
                }
                else {
                }
        }
  
 -      /* VBO no longer valid */
 -      if (ob->derivedFinal) {
 -              GPU_drawobject_free(ob->derivedFinal);
 -      }
 +      // ED_workspace_object_mode_sync_from_object(G.main->wm.first, workspace, ob);
 +
 +      /* Flush object mode. */
 +      DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
  }
  
  void ED_object_sculptmode_enter(struct bContext *C, ReportList *reports)
  {
        Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
 -      ED_object_sculptmode_enter_ex(scene, ob, reports);
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +      ED_object_sculptmode_enter_ex(depsgraph, scene, ob, reports);
  }
  
  void ED_object_sculptmode_exit_ex(
 +        Depsgraph *depsgraph,
          Scene *scene, Object *ob)
  {
        const int mode_flag = OB_MODE_SCULPT;
         * a consistent state.
         */
        if (true || /* flush_recalc || */ (ob->sculpt && ob->sculpt->bm)) {
 -              DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +              DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
        }
  
        if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
                /* Dynamic topology must be disabled before exiting sculpt
                 * mode to ensure the undo stack stays in a consistent
                 * state */
 -              sculpt_dynamic_topology_disable_with_undo(scene, ob);
 +              sculpt_dynamic_topology_disable_with_undo(depsgraph, scene, ob);
  
                /* store so we know to re-enable when entering sculpt mode */
                me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
        /* Leave sculptmode */
        ob->mode &= ~mode_flag;
  
 +      // ED_workspace_object_mode_sync_from_object(G.main->wm.first, workspace, ob);
 +
        BKE_sculptsession_free(ob);
  
        paint_cursor_delete_textures();
  
 -      /* VBO no longer valid */
 -      if (ob->derivedFinal) {
 -              GPU_drawobject_free(ob->derivedFinal);
 -      }
 +      /* Flush object mode. */
 +      DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
  }
  
  void ED_object_sculptmode_exit(bContext *C)
  {
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
 -      ED_object_sculptmode_exit_ex(scene, ob);
 +      ED_object_sculptmode_exit_ex(depsgraph, scene, ob);
  }
  
  static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
  {
 +      struct wmMsgBus *mbus = CTX_wm_message_bus(C);
 +      Depsgraph *depsgraph = CTX_data_depsgraph_on_load(C);
        Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
        const int mode_flag = OB_MODE_SCULPT;
        }
  
        if (is_mode_set) {
 -              ED_object_sculptmode_exit_ex(scene, ob);
 +              ED_object_sculptmode_exit_ex(depsgraph, scene, ob);
        }
        else {
 -              ED_object_sculptmode_enter_ex(scene, ob, op->reports);
 +              ED_object_sculptmode_enter_ex(depsgraph, scene, ob, op->reports);
        }
  
        WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene);
  
 +      WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
 +
 +      WM_toolsystem_update_from_context_view3d(C);
 +
        return OPERATOR_FINISHED;
  }
  
  #include "DNA_mesh_types.h"
  #include "DNA_screen_types.h"
  #include "DNA_space_types.h"
 +#include "DNA_workspace_types.h"
  
  #include "BKE_ccg.h"
  #include "BKE_context.h"
 -#include "BKE_depsgraph.h"
  #include "BKE_multires.h"
  #include "BKE_paint.h"
  #include "BKE_key.h"
  #include "BKE_mesh.h"
 +#include "BKE_mesh_runtime.h"
  #include "BKE_subsurf.h"
  #include "BKE_undo_system.h"
  
 +#include "DEG_depsgraph.h"
 +
  #include "WM_api.h"
  #include "WM_types.h"
  
 -#include "GPU_buffers.h"
 -
  #include "ED_paint.h"
  #include "ED_object.h"
  #include "ED_sculpt.h"
@@@ -141,7 -140,6 +141,7 @@@ static bool sculpt_undo_restore_coords(
        Scene *scene = CTX_data_scene(C);
        Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
        Object *ob = CTX_data_active_object(C);
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        SculptSession *ss = ob->sculpt;
        MVert *mvert;
        int *index;
                        if (kb) {
                                ob->shapenr = BLI_findindex(&key->block, kb) + 1;
  
-                               BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, 0, false);
 -                              BKE_sculpt_update_mesh_elements(scene, sd, ob, false, false);
++                              BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, false);
                                WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob);
                        }
                        else {
@@@ -380,8 -378,8 +380,8 @@@ static void sculpt_undo_bmesh_restore_g
  }
  
  /* Create empty sculpt BMesh and enable logging */
 -static void sculpt_undo_bmesh_enable(Object *ob,
 -                                     SculptUndoNode *unode)
 +static void sculpt_undo_bmesh_enable(
 +        Object *ob, SculptUndoNode *unode)
  {
        SculptSession *ss = ob->sculpt;
        Mesh *me = ob->data;
@@@ -474,7 -472,6 +474,7 @@@ static void sculpt_undo_restore_list(bC
        Scene *scene = CTX_data_scene(C);
        Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
        Object *ob = CTX_data_active_object(C);
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
        DerivedMesh *dm;
        SculptSession *ss = ob->sculpt;
        SculptUndoNode *unode;
                }
        }
  
 -      BKE_sculpt_update_mesh_elements(scene, sd, ob, false, need_mask);
 +      DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
 +
-       BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, 0, need_mask);
++      BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, need_mask);
  
        /* call _after_ sculpt_update_mesh_elements() which may update 'ob->derivedFinal' */
 -      dm = mesh_get_derived_final(scene, ob, 0);
 +      dm = mesh_get_derived_final(depsgraph, scene, ob, 0);
  
        if (lb->first && sculpt_undo_bmesh_restore(C, lb->first, ob, ss))
                return;
                }
  
                if (tag_update) {
 -                      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +                      DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
                }
                else {
                        sculpt_update_object_bounding_box(ob);
                }
 -
 -              /* for non-PBVH drawing, need to recreate VBOs */
 -              GPU_drawobject_free(ob->derivedFinal);
        }
  }