Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / sculpt_paint / paint_vertex.c
index 93c8b1c..ac6bfe0 100644 (file)
 
 #include "BKE_brush.h"
 #include "BKE_context.h"
-#include "BKE_depsgraph.h"
 #include "BKE_deform.h"
 #include "BKE_main.h"
 #include "BKE_mesh.h"
 #include "BKE_mesh_mapping.h"
+#include "BKE_object.h"
 #include "BKE_object_deform.h"
 #include "BKE_paint.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"
@@ -204,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))
@@ -212,13 +216,26 @@ int vertex_paint_poll(bContext *C)
                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);
@@ -226,7 +243,7 @@ int weight_paint_mode_poll(bContext *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;
@@ -239,12 +256,24 @@ int weight_paint_poll(bContext *C)
        {
                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");
@@ -938,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(scene, scene->toolsettings->sculpt, ob, false, false);
+               BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
        }
 }
 
@@ -1032,14 +1061,18 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob)
  * \{ */
 
 static void ed_vwpaintmode_enter_generic(
-        Main *bmain,
-        wmWindowManager *wm,
-        Scene *scene,
+        Main *bmain, Depsgraph *depsgraph,
+        wmWindowManager *wm, Scene *scene,
         Object *ob, const eObjectMode mode_flag)
 {
        ob->mode |= mode_flag;
        Mesh *me = BKE_mesh_from_object(ob);
 
+       /* Same as sculpt mode, make sure we don't have cached derived mesh which
+        * points to freed arrays.
+        */
+       BKE_object_free_derived_caches(ob);
+
        if (mode_flag == OB_MODE_VERTEX_PAINT) {
                const ePaintMode paint_mode = ePaintVertex;
                ED_mesh_color_ensure(me, NULL);
@@ -1080,39 +1113,44 @@ static void ed_vwpaintmode_enter_generic(
                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(
-        Main *bmain, wmWindowManager *wm,
+        Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm,
         Scene *scene, Object *ob)
 {
        ed_vwpaintmode_enter_generic(
-               bmain, wm, scene, ob, OB_MODE_VERTEX_PAINT);
+               bmain, depsgraph, wm, scene, ob, OB_MODE_VERTEX_PAINT);
 }
 void ED_object_vpaintmode_enter(struct bContext *C)
 {
        Main *bmain = CTX_data_main(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(bmain, wm, scene, ob);
+       ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
 }
 
 void ED_object_wpaintmode_enter_ex(
-        Main *bmain, wmWindowManager *wm,
+        Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm,
         Scene *scene, Object *ob)
 {
        ed_vwpaintmode_enter_generic(
-               bmain, wm, scene, ob, OB_MODE_WEIGHT_PAINT);
+               bmain, depsgraph, wm, scene, ob, OB_MODE_WEIGHT_PAINT);
 }
 void ED_object_wpaintmode_enter(struct bContext *C)
 {
        Main *bmain = CTX_data_main(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(bmain, wm, scene, ob);
+       ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
 }
 
 /** \} */
@@ -1161,6 +1199,12 @@ static void ed_vwpaintmode_exit_generic(
                ED_mesh_mirror_spatial_table(NULL, NULL, NULL, NULL, 'e');
                ED_mesh_mirror_topo_table(NULL, NULL, 'e');
        }
+
+       /* Never leave derived meshes behind. */
+       BKE_object_free_derived_caches(ob);
+
+       /* Flush object mode. */
+       DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
 }
 
 void ED_object_vpaintmode_exit_ex(Object *ob)
@@ -1193,6 +1237,7 @@ void ED_object_wpaintmode_exit(struct bContext *C)
 static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
 {
        Main *bmain = CTX_data_main(C);
+       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;
@@ -1210,8 +1255,9 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
                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(bmain, wm, scene, ob);
+               ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
        }
 
        /* Weightpaint works by overriding colors in mesh,
@@ -1219,10 +1265,14 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
         * 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;
 }
 
@@ -1402,6 +1452,7 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
        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;
@@ -1505,7 +1556,7 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
        }
 
        /* 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);
 
@@ -1946,7 +1997,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. */
@@ -2174,7 +2226,9 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
        /* 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);
 
@@ -2238,7 +2292,7 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke)
                }
        }
 
-       DAG_id_tag_update(ob->data, 0);
+       DEG_id_tag_update(ob->data, 0);
 
        WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
 
@@ -2321,6 +2375,7 @@ void PAINT_OT_weight_paint(wmOperatorType *ot)
 static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
 {
        Main *bmain = CTX_data_main(C);
+       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;
@@ -2339,15 +2394,22 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
                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(bmain, wm, scene, ob);
+               ED_object_vpaintmode_enter_ex(bmain, 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;
 }
 
@@ -2430,6 +2492,7 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
        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);
@@ -2477,12 +2540,12 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
        /* 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);
 
@@ -2938,8 +3001,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);
@@ -3076,6 +3139,8 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
 
        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);
        }
@@ -3089,11 +3154,11 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
        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);
        }
 }