diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint/paint_vertex.c')
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_vertex.c | 135 |
1 files changed, 100 insertions, 35 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 095ba088e0c..85a1f11be4b 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -54,18 +54,22 @@ #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,7 +967,7 @@ 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, eObjectMode object_mode) +static void vertex_paint_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob, eObjectMode object_mode) { /* Create persistent sculpt mode data */ BKE_sculpt_toolsettings_data_ensure(scene); @@ -946,12 +975,12 @@ static void vertex_paint_init_session(Scene *scene, Object *ob, eObjectMode obje BLI_assert(ob->sculpt == NULL); ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session"); ob->sculpt->mode_type = object_mode; - 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); } -static void vertex_paint_init_stroke(Scene *scene, Object *ob) +static void vertex_paint_init_stroke(Depsgraph *depsgraph, Scene *scene, Object *ob) { - 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); } static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) @@ -1037,14 +1066,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); @@ -1085,39 +1118,44 @@ static void ed_vwpaintmode_enter_generic( BKE_sculptsession_free(ob); } - vertex_paint_init_session(scene, ob, mode_flag); + vertex_paint_init_session(depsgraph, scene, ob, mode_flag); + + /* 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); } /** \} */ @@ -1166,6 +1204,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) @@ -1198,6 +1242,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; @@ -1215,8 +1260,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, @@ -1224,10 +1270,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; } @@ -1407,6 +1457,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; @@ -1510,7 +1561,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_stroke(scene, ob); + vertex_paint_init_stroke(depsgraph, scene, ob); vwpaint_update_cache_invariants(C, vp, ss, op, mouse); vertex_paint_init_session_data(ts, ob); @@ -1951,7 +2002,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. */ @@ -2179,7 +2231,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); @@ -2243,7 +2297,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); @@ -2326,6 +2380,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; @@ -2344,15 +2399,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; } @@ -2435,6 +2497,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); @@ -2482,12 +2545,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_stroke(scene, ob); + vertex_paint_init_stroke(depsgraph, scene, ob); vwpaint_update_cache_invariants(C, vp, ss, op, mouse); vertex_paint_init_session_data(ts, ob); @@ -2943,8 +3006,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); @@ -3081,6 +3144,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); } @@ -3094,11 +3159,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); } } |