diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint/paint_vertex.cc')
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_vertex.cc | 313 |
1 files changed, 145 insertions, 168 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc index 67b60acc667..c38a79cb6bb 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex.cc @@ -36,6 +36,7 @@ #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_deform.h" +#include "BKE_editmesh.h" #include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" @@ -227,22 +228,6 @@ static MDeformVert *defweight_prev_init(MDeformVert *dvert_prev, return dv_prev; } -/* check if we can do partial updates and have them draw realtime - * (without evaluating modifiers) */ -static bool vertex_paint_use_fast_update_check(Object *ob) -{ - const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob); - - if (me_eval != nullptr) { - const Mesh *me = BKE_mesh_from_object(ob); - if (me && me->mloopcol) { - return (me->mloopcol == CustomData_get_layer(&me_eval->ldata, CD_PROP_BYTE_COLOR)); - } - } - - return false; -} - static void paint_last_stroke_update(Scene *scene, const float location[3]) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; @@ -788,6 +773,8 @@ struct WeightPaintGroupData { * paint stroke update - campbell */ struct WeightPaintInfo { + MutableSpan<MDeformVert> dvert; + int defbase_tot; /* both must add up to 'defbase_tot' */ @@ -830,7 +817,7 @@ static void do_weight_paint_vertex_single( float paintweight) { Mesh *me = (Mesh *)ob->data; - MDeformVert *dv = &me->dvert[index]; + MDeformVert *dv = &wpi->dvert[index]; bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; MDeformWeight *dw; @@ -890,7 +877,7 @@ static void do_weight_paint_vertex_single( /* get the mirror def vars */ if (index_mirr != -1) { - dv_mirr = &me->dvert[index_mirr]; + dv_mirr = &wpi->dvert[index_mirr]; if (wp->flag & VP_FLAG_VGROUP_RESTRICT) { dw_mirr = BKE_defvert_find_index(dv_mirr, vgroup_mirr); @@ -930,9 +917,9 @@ static void do_weight_paint_vertex_single( if (!brush_use_accumulate(wp)) { MDeformVert *dvert_prev = ob->sculpt->mode.wpaint.dvert_prev; - MDeformVert *dv_prev = defweight_prev_init(dvert_prev, me->dvert, index); + MDeformVert *dv_prev = defweight_prev_init(dvert_prev, wpi->dvert.data(), index); if (index_mirr != -1) { - defweight_prev_init(dvert_prev, me->dvert, index_mirr); + defweight_prev_init(dvert_prev, wpi->dvert.data(), index_mirr); } weight_prev = BKE_defvert_find_weight(dv_prev, wpi->active.index); @@ -1043,7 +1030,7 @@ static void do_weight_paint_vertex_multi( float paintweight) { Mesh *me = (Mesh *)ob->data; - MDeformVert *dv = &me->dvert[index]; + MDeformVert *dv = &wpi->dvert[index]; bool topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; /* mirror vars */ @@ -1059,7 +1046,7 @@ static void do_weight_paint_vertex_multi( index_mirr = mesh_get_x_mirror_vert(ob, nullptr, index, topology); if (!ELEM(index_mirr, -1, index)) { - dv_mirr = &me->dvert[index_mirr]; + dv_mirr = &wpi->dvert[index_mirr]; } else { index_mirr = -1; @@ -1086,9 +1073,9 @@ static void do_weight_paint_vertex_multi( if (!brush_use_accumulate(wp)) { MDeformVert *dvert_prev = ob->sculpt->mode.wpaint.dvert_prev; - MDeformVert *dv_prev = defweight_prev_init(dvert_prev, me->dvert, index); + MDeformVert *dv_prev = defweight_prev_init(dvert_prev, wpi->dvert.data(), index); if (index_mirr != -1) { - defweight_prev_init(dvert_prev, me->dvert, index_mirr); + defweight_prev_init(dvert_prev, wpi->dvert.data(), index_mirr); } oldw = BKE_defvert_multipaint_collective_weight( @@ -1191,12 +1178,12 @@ static void vertex_paint_init_session(Depsgraph *depsgraph, BLI_assert(ob->sculpt == nullptr); ob->sculpt = (SculptSession *)MEM_callocN(sizeof(SculptSession), "sculpt session"); ob->sculpt->mode_type = object_mode; - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, true); } static void vwpaint_init_stroke(Depsgraph *depsgraph, Object *ob) { - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, true); SculptSession *ss = ob->sculpt; /* Ensure ss->cache is allocated. It will mostly be initialized in @@ -1250,6 +1237,8 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) } Mesh *me = (Mesh *)ob->data; + const Span<MPoly> polys = me->polys(); + const Span<MLoop> loops = me->loops(); if (gmap->vert_to_loop == nullptr) { gmap->vert_map_mem = nullptr; @@ -1258,15 +1247,15 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) gmap->vert_to_poly = nullptr; BKE_mesh_vert_loop_map_create(&gmap->vert_to_loop, &gmap->vert_map_mem, - me->mpoly, - me->mloop, + polys.data(), + loops.data(), me->totvert, me->totpoly, me->totloop); BKE_mesh_vert_poly_map_create(&gmap->vert_to_poly, &gmap->poly_map_mem, - me->mpoly, - me->mloop, + polys.data(), + loops.data(), me->totvert, me->totpoly, me->totloop); @@ -1804,7 +1793,8 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo /* set up auto-normalize, and generate map for detecting which * vgroups affect deform bones */ wpd->lock_flags = BKE_object_defgroup_lock_flags_get(ob, wpd->defbase_tot); - if (ts->auto_normalize || ts->multipaint || wpd->lock_flags || ts->wpaint_lock_relative) { + if (ts->auto_normalize || ts->multipaint || wpd->lock_flags != nullptr || + ts->wpaint_lock_relative) { wpd->vgroup_validmap = BKE_object_defgroup_validmap_get(ob, wpd->defbase_tot); } @@ -1914,7 +1904,7 @@ static void do_wpaint_precompute_weight_cb_ex(void *__restrict userdata, const TaskParallelTLS *__restrict UNUSED(tls)) { SculptThreadedTaskData *data = (SculptThreadedTaskData *)userdata; - const MDeformVert *dv = &data->me->dvert[n]; + const MDeformVert *dv = &data->wpi->dvert[n]; data->wpd->precomputed_weight[n] = wpaint_get_active_weight(dv, data->wpi); } @@ -1975,10 +1965,9 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, if (sculpt_brush_test_sq_fn(&test, vd.co)) { /* For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : - vd.vert_indices[vd.i]; + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const char v_flag = data->me->mvert[v_index].flag; + const char v_flag = ss->mvert[v_index].flag; /* If the vertex is selected */ if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) { /* Get the average poly weight */ @@ -1986,12 +1975,12 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, float weight_final = 0.0f; for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; - const MPoly *mp = &data->me->mpoly[p_index]; + const MPoly *mp = &ss->mpoly[p_index]; total_hit_loops += mp->totloop; for (int k = 0; k < mp->totloop; k++) { const int l_index = mp->loopstart + k; - const MLoop *ml = &data->me->mloop[l_index]; + const MLoop *ml = &ss->mloop[l_index]; weight_final += data->wpd->precomputed_weight[ml->v]; } } @@ -2071,10 +2060,9 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, if (sculpt_brush_test_sq_fn(&test, vd.co)) { /* For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : - vd.vert_indices[vd.i]; + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const MVert *mv_curr = &data->me->mvert[v_index]; + const MVert *mv_curr = &ss->mvert[v_index]; /* If the vertex is selected */ if (!(use_face_sel || use_vert_sel) || mv_curr->flag & SELECT) { @@ -2096,12 +2084,12 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, float weight_final = 0.0; for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; - const MPoly *mp = &data->me->mpoly[p_index]; - const MLoop *ml_other = &data->me->mloop[mp->loopstart]; + const MPoly *mp = &ss->mpoly[p_index]; + const MLoop *ml_other = &ss->mloop[mp->loopstart]; for (int k = 0; k < mp->totloop; k++, ml_other++) { const uint v_other_index = ml_other->v; if (v_other_index != v_index) { - const MVert *mv_other = &data->me->mvert[v_other_index]; + const MVert *mv_other = &ss->mvert[v_other_index]; /* Get the direction from the selected vert to the neighbor. */ float other_dir[3]; @@ -2178,11 +2166,10 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata, /* NOTE: grids are 1:1 with corners (aka loops). * For multires, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : - vd.vert_indices[vd.i]; + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const char v_flag = data->me->mvert[v_index].flag; + const char v_flag = ss->mvert[v_index].flag; /* If the vertex is selected */ if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) { float brush_strength = cache->bstrength; @@ -2246,13 +2233,12 @@ static void do_wpaint_brush_calc_average_weight_cb_ex( 1.0f; if (angle_cos > 0.0 && BKE_brush_curve_strength(data->brush, sqrtf(test.dist), cache->radius) > 0.0) { - const int v_index = has_grids ? data->me->mloop[vd.grid_indices[vd.g]].v : - vd.vert_indices[vd.i]; - const char v_flag = data->me->mvert[v_index].flag; + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; + const char v_flag = ss->mvert[v_index].flag; /* If the vertex is selected. */ if (!(use_face_sel || use_vert_sel) || v_flag & SELECT) { - const MDeformVert *dv = &data->me->dvert[v_index]; + const MDeformVert *dv = &data->wpi->dvert[v_index]; accum->len += 1; accum->value += wpaint_get_active_weight(dv, data->wpi); } @@ -2524,7 +2510,11 @@ static void wpaint_stroke_update_step(bContext *C, /* load projection matrix */ mul_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat); + Mesh *mesh = static_cast<Mesh *>(ob->data); + /* *** setup WeightPaintInfo - pass onto do_weight_paint_vertex *** */ + wpi.dvert = mesh->deform_verts_for_write(); + wpi.defbase_tot = wpd->defbase_tot; wpi.defbase_sel = wpd->defbase_sel; wpi.defbase_tot_sel = wpd->defbase_tot_sel; @@ -2546,7 +2536,7 @@ static void wpaint_stroke_update_step(bContext *C, /* *** done setting up WeightPaintInfo *** */ if (wpd->precomputed_weight) { - precompute_weight_values(C, ob, brush, wpd, &wpi, (Mesh *)ob->data); + precompute_weight_values(C, ob, brush, wpd, &wpi, mesh); } wpaint_do_symmetrical_brush_actions(C, ob, wp, sd, wpd, &wpi); @@ -2559,9 +2549,9 @@ static void wpaint_stroke_update_step(bContext *C, mul_v3_m4v3(loc_world, ob->obmat, ss->cache->true_location); paint_last_stroke_update(scene, loc_world); - BKE_mesh_batch_cache_dirty_tag((Mesh *)ob->data, BKE_MESH_BATCH_DIRTY_ALL); + BKE_mesh_batch_cache_dirty_tag(mesh, BKE_MESH_BATCH_DIRTY_ALL); - DEG_id_tag_update((ID *)ob->data, 0); + DEG_id_tag_update(&mesh->id, 0); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); swap_m4m4(wpd->vc.rv3d->persmat, mat); @@ -2593,31 +2583,14 @@ static void wpaint_stroke_done(const bContext *C, PaintStroke *stroke) WPaintData *wpd = (WPaintData *)paint_stroke_mode_data(stroke); if (wpd) { - if (wpd->defbase_sel) { - MEM_freeN((void *)wpd->defbase_sel); - } - if (wpd->vgroup_validmap) { - MEM_freeN((void *)wpd->vgroup_validmap); - } - if (wpd->vgroup_locked) { - MEM_freeN((void *)wpd->vgroup_locked); - } - if (wpd->vgroup_unlocked) { - MEM_freeN((void *)wpd->vgroup_unlocked); - } - if (wpd->lock_flags) { - MEM_freeN((void *)wpd->lock_flags); - } - if (wpd->active.lock) { - MEM_freeN((void *)wpd->active.lock); - } - if (wpd->mirror.lock) { - MEM_freeN((void *)wpd->mirror.lock); - } - if (wpd->precomputed_weight) { - MEM_freeN(wpd->precomputed_weight); - } - + MEM_SAFE_FREE(wpd->defbase_sel); + MEM_SAFE_FREE(wpd->vgroup_validmap); + MEM_SAFE_FREE(wpd->vgroup_locked); + MEM_SAFE_FREE(wpd->vgroup_unlocked); + MEM_SAFE_FREE(wpd->lock_flags); + MEM_SAFE_FREE(wpd->active.lock); + MEM_SAFE_FREE(wpd->mirror.lock); + MEM_SAFE_FREE(wpd->precomputed_weight); MEM_freeN(wpd); } @@ -2838,16 +2811,6 @@ struct VPaintData : public VPaintDataBase { struct VertProjHandle *vp_handle; CoNo *vertexcosnos; - /** - * Modify #Mesh.mloopcol directly, since the derived mesh is drawing from this - * array, otherwise we need to refresh the modifier stack. - */ - bool use_fast_update; - - /* loops tagged as having been painted, to apply shared vertex color - * blending only to modified loops */ - bool *mlooptag; - bool is_texbrush; /* Special storage for smear brush, avoid feedback loop - update each step. */ @@ -2893,20 +2856,6 @@ static void *vpaint_init_vpaint(bContext *C, vpd->is_texbrush = !(brush->vertexpaint_tool == VPAINT_TOOL_BLUR) && brush->mtex.tex; - /* are we painting onto a modified mesh?, - * if not we can skip face map trickiness */ - if (vertex_paint_use_fast_update_check(ob)) { - vpd->use_fast_update = true; - } - else { - vpd->use_fast_update = false; - } - - /* to keep tracked of modified loops for shared vertex color blending */ - if (brush->vertexpaint_tool == VPAINT_TOOL_BLUR) { - vpd->mlooptag = (bool *)MEM_mallocN(sizeof(bool) * elem_num, "VPaintData mlooptag"); - } - if (brush->vertexpaint_tool == VPAINT_TOOL_SMEAR) { CustomDataLayer *layer = BKE_id_attributes_active_color_get(&me->id); @@ -3035,10 +2984,10 @@ static void do_vpaint_brush_blur_loops(bContext *C, if (sculpt_brush_test_sq_fn(&test, vd.co)) { /* For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? me->mloop[vd.grid_indices[vd.g]].v : + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const MVert *mv = &me->mvert[v_index]; + const MVert *mv = &ss->mvert[v_index]; /* If the vertex is selected for painting. */ if (!use_vert_sel || mv->flag & SELECT) { @@ -3061,7 +3010,7 @@ static void do_vpaint_brush_blur_loops(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { int p_index = gmap->vert_to_poly[v_index].indices[j]; - const MPoly *mp = &me->mpoly[p_index]; + const MPoly *mp = &ss->mpoly[p_index]; if (!use_face_sel || mp->flag & ME_FACE_SEL) { total_hit_loops += mp->totloop; for (int k = 0; k < mp->totloop; k++) { @@ -3095,8 +3044,8 @@ static void do_vpaint_brush_blur_loops(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; const int l_index = gmap->vert_to_loop[v_index].indices[j]; - BLI_assert(me->mloop[l_index].v == v_index); - const MPoly *mp = &me->mpoly[p_index]; + BLI_assert(ss->mloop[l_index].v == v_index); + const MPoly *mp = &ss->mpoly[p_index]; if (!use_face_sel || mp->flag & ME_FACE_SEL) { Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */ @@ -3177,10 +3126,10 @@ static void do_vpaint_brush_blur_verts(bContext *C, if (sculpt_brush_test_sq_fn(&test, vd.co)) { /* For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? me->mloop[vd.grid_indices[vd.g]].v : + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const MVert *mv = &me->mvert[v_index]; + const MVert *mv = &ss->mvert[v_index]; /* If the vertex is selected for painting. */ if (!use_vert_sel || mv->flag & SELECT) { @@ -3203,12 +3152,12 @@ static void do_vpaint_brush_blur_verts(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { int p_index = gmap->vert_to_poly[v_index].indices[j]; - const MPoly *mp = &me->mpoly[p_index]; + const MPoly *mp = &ss->mpoly[p_index]; if (!use_face_sel || mp->flag & ME_FACE_SEL) { total_hit_loops += mp->totloop; for (int k = 0; k < mp->totloop; k++) { const uint l_index = mp->loopstart + k; - const uint v_index = me->mloop[l_index].v; + const uint v_index = ss->mloop[l_index].v; Color *col = lcol + v_index; @@ -3239,9 +3188,9 @@ static void do_vpaint_brush_blur_verts(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; - BLI_assert(me->mloop[gmap->vert_to_loop[v_index].indices[j]].v == v_index); + BLI_assert(ss->mloop[gmap->vert_to_loop[v_index].indices[j]].v == v_index); - const MPoly *mp = &me->mpoly[p_index]; + const MPoly *mp = &ss->mpoly[p_index]; if (!use_face_sel || mp->flag & ME_FACE_SEL) { Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */ @@ -3328,10 +3277,10 @@ static void do_vpaint_brush_smear(bContext *C, if (sculpt_brush_test_sq_fn(&test, vd.co)) { /* For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? me->mloop[vd.grid_indices[vd.g]].v : + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const MVert *mv_curr = &me->mvert[v_index]; + const MVert *mv_curr = &ss->mvert[v_index]; /* if the vertex is selected for painting. */ if (!use_vert_sel || mv_curr->flag & SELECT) { @@ -3360,15 +3309,15 @@ static void do_vpaint_brush_smear(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; const int l_index = gmap->vert_to_loop[v_index].indices[j]; - BLI_assert(me->mloop[l_index].v == v_index); + BLI_assert(ss->mloop[l_index].v == v_index); UNUSED_VARS_NDEBUG(l_index); - const MPoly *mp = &me->mpoly[p_index]; + const MPoly *mp = &ss->mpoly[p_index]; if (!use_face_sel || mp->flag & ME_FACE_SEL) { - const MLoop *ml_other = &me->mloop[mp->loopstart]; + const MLoop *ml_other = &ss->mloop[mp->loopstart]; for (int k = 0; k < mp->totloop; k++, ml_other++) { const uint v_other_index = ml_other->v; if (v_other_index != v_index) { - const MVert *mv_other = &me->mvert[v_other_index]; + const MVert *mv_other = &ss->mvert[v_other_index]; /* Get the direction from the * selected vert to the neighbor. */ @@ -3414,10 +3363,10 @@ static void do_vpaint_brush_smear(bContext *C, else { const int l_index = gmap->vert_to_loop[v_index].indices[j]; elem_index = l_index; - BLI_assert(me->mloop[l_index].v == v_index); + BLI_assert(ss->mloop[l_index].v == v_index); } - const MPoly *mp = &me->mpoly[p_index]; + const MPoly *mp = &ss->mpoly[p_index]; if (!use_face_sel || mp->flag & ME_FACE_SEL) { /* Get the previous element color */ Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */ @@ -3490,11 +3439,11 @@ static void calculate_average_color(VPaintData<Color, Traits, domain> *vpd, BKE_pbvh_vertex_iter_begin (ss->pbvh, nodes[n], vd, PBVH_ITER_UNIQUE) { /* Test to see if the vertex coordinates are within the spherical brush region. */ if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const int v_index = has_grids ? me->mloop[vd.grid_indices[vd.g]].v : + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; if (BKE_brush_curve_strength(brush, 0.0, cache->radius) > 0.0) { /* If the vertex is selected for painting. */ - const MVert *mv = &me->mvert[v_index]; + const MVert *mv = &ss->mvert[v_index]; if (!use_vert_sel || mv->flag & SELECT) { accum2->len += gmap->vert_to_loop[v_index].count; /* if a vertex is within the brush region, then add its color to the blend. */ @@ -3610,10 +3559,10 @@ static void vpaint_do_draw(bContext *C, /* NOTE: Grids are 1:1 with corners (aka loops). * For grid based pbvh, take the vert whose loop corresponds to the current grid. * Otherwise, take the current vert. */ - const int v_index = has_grids ? me->mloop[vd.grid_indices[vd.g]].v : + const int v_index = has_grids ? ss->mloop[vd.grid_indices[vd.g]].v : vd.vert_indices[vd.i]; const float grid_alpha = has_grids ? 1.0f / vd.gridsize : 1.0f; - const MVert *mv = &me->mvert[v_index]; + const MVert *mv = &ss->mvert[v_index]; /* If the vertex is selected for painting. */ if (!use_vert_sel || mv->flag & SELECT) { @@ -3667,8 +3616,8 @@ static void vpaint_do_draw(bContext *C, for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { const int p_index = gmap->vert_to_poly[v_index].indices[j]; const int l_index = gmap->vert_to_loop[v_index].indices[j]; - BLI_assert(me->mloop[l_index].v == v_index); - const MPoly *mp = &me->mpoly[p_index]; + BLI_assert(ss->mloop[l_index].v == v_index); + const MPoly *mp = &ss->mpoly[p_index]; if (!use_face_sel || mp->flag & ME_FACE_SEL) { Color color_orig = Color(0, 0, 0, 0); /* unused when array is nullptr */ @@ -3901,15 +3850,7 @@ static void vpaint_stroke_update_step_intern(bContext *C, PaintStroke *stroke, P ED_region_tag_redraw(vc->region); - if (vpd->use_fast_update == false) { - /* recalculate modifier stack to get new colors, slow, - * avoid this if we can! */ - DEG_id_tag_update((ID *)ob->data, 0); - } - else { - /* Flush changes through DEG. */ - DEG_id_tag_update((ID *)ob->data, ID_RECALC_COPY_ON_WRITE); - } + DEG_id_tag_update((ID *)ob->data, ID_RECALC_GEOMETRY); } static void vpaint_stroke_update_step(bContext *C, @@ -3950,9 +3891,6 @@ static void vpaint_free_vpaintdata(Object *UNUSED(ob), void *_vpd) ED_vpaint_proj_handle_free(vpd->vp_handle); } - if (vpd->mlooptag) { - MEM_freeN(vpd->mlooptag); - } if (vpd->smear.color_prev) { MEM_freeN(vpd->smear.color_prev); } @@ -4023,7 +3961,7 @@ static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event) BKE_pbvh_ensure_node_loops(ob->sculpt->pbvh); } - SCULPT_undo_push_begin(ob, "Vertex Paint"); + SCULPT_undo_push_begin_ex(ob, "Vertex Paint"); if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) { paint_stroke_free(C, op, (PaintStroke *)op->customdata); @@ -4099,7 +4037,7 @@ void PAINT_OT_vertex_paint(wmOperatorType *ot) * \{ */ template<typename Color, typename Traits, eAttrDomain domain> -static bool vertex_color_set(Object *ob, ColorPaint4f paintcol_in, Color *color_layer) +static bool vertex_color_set(Object *ob, ColorPaint4f paintcol_in, CustomDataLayer *layer) { Mesh *me; if (((me = BKE_mesh_from_object(ob)) == nullptr) || @@ -4112,30 +4050,73 @@ static bool vertex_color_set(Object *ob, ColorPaint4f paintcol_in, Color *color_ const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; - const MPoly *mp = me->mpoly; - for (int i = 0; i < me->totpoly; i++, mp++) { - if (use_face_sel && !(mp->flag & ME_FACE_SEL)) { - continue; + if (me->edit_mesh) { + BMesh *bm = me->edit_mesh->bm; + BMFace *f; + BMIter iter; + + int cd_offset = -1; + + /* Find customdata offset inside of bmesh. */ + CustomData *cdata = domain == ATTR_DOMAIN_POINT ? &bm->vdata : &bm->ldata; + + for (int i = 0; i < cdata->totlayer; i++) { + if (STREQ(cdata->layers[i].name, layer->name)) { + cd_offset = layer->offset; + } } - int j = 0; - do { - uint vidx = me->mloop[mp->loopstart + j].v; + BLI_assert(cd_offset != -1); - if (!(use_vert_sel && !(me->mvert[vidx].flag & SELECT))) { - if constexpr (domain == ATTR_DOMAIN_CORNER) { - color_layer[mp->loopstart + j] = paintcol; - } - else { - color_layer[vidx] = paintcol; + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + Color *color; + BMLoop *l = f->l_first; + + do { + if (!(use_vert_sel && !(BM_elem_flag_test(l->v, BM_ELEM_SELECT)))) { + if constexpr (domain == ATTR_DOMAIN_CORNER) { + color = static_cast<Color *>(BM_ELEM_CD_GET_VOID_P(l, cd_offset)); + } + else { + color = static_cast<Color *>(BM_ELEM_CD_GET_VOID_P(l->v, cd_offset)); + } + + *color = paintcol; } - } - j++; - } while (j < mp->totloop); + } while ((l = l->next) != f->l_first); + } } + else { + Color *color_layer = static_cast<Color *>(layer->data); + const Span<MVert> verts = me->verts(); + const Span<MPoly> polys = me->polys(); + const Span<MLoop> loops = me->loops(); + + for (const int i : polys.index_range()) { + const MPoly &poly = polys[i]; + if (use_face_sel && !(poly.flag & ME_FACE_SEL)) { + continue; + } - /* remove stale me->mcol, will be added later */ - BKE_mesh_tessface_clear(me); + int j = 0; + do { + uint vidx = loops[poly.loopstart + j].v; + + if (!(use_vert_sel && !(verts[vidx].flag & SELECT))) { + if constexpr (domain == ATTR_DOMAIN_CORNER) { + color_layer[poly.loopstart + j] = paintcol; + } + else { + color_layer[vidx] = paintcol; + } + } + j++; + } while (j < poly.totloop); + } + + /* remove stale me->mcol, will be added later */ + BKE_mesh_tessface_clear(me); + } DEG_id_tag_update(&me->id, ID_RECALC_COPY_ON_WRITE); @@ -4160,7 +4141,7 @@ static bool paint_object_attributes_active_color_fill_ex(Object *ob, if (!layer) { return false; } - /* Store original #Mesh.editflag.*/ + /* Store original #Mesh.editflag. */ const decltype(me->editflag) editflag = me->editflag; if (!only_selected) { me->editflag &= ~ME_EDIT_PAINT_FACE_SEL; @@ -4170,22 +4151,18 @@ static bool paint_object_attributes_active_color_fill_ex(Object *ob, bool ok = false; if (domain == ATTR_DOMAIN_POINT) { if (layer->type == CD_PROP_COLOR) { - ok = vertex_color_set<ColorPaint4f, FloatTraits, ATTR_DOMAIN_POINT>( - ob, fill_color, static_cast<ColorPaint4f *>(layer->data)); + ok = vertex_color_set<ColorPaint4f, FloatTraits, ATTR_DOMAIN_POINT>(ob, fill_color, layer); } else if (layer->type == CD_PROP_BYTE_COLOR) { - ok = vertex_color_set<ColorPaint4b, ByteTraits, ATTR_DOMAIN_POINT>( - ob, fill_color, static_cast<ColorPaint4b *>(layer->data)); + ok = vertex_color_set<ColorPaint4b, ByteTraits, ATTR_DOMAIN_POINT>(ob, fill_color, layer); } } else { if (layer->type == CD_PROP_COLOR) { - ok = vertex_color_set<ColorPaint4f, FloatTraits, ATTR_DOMAIN_CORNER>( - ob, fill_color, static_cast<ColorPaint4f *>(layer->data)); + ok = vertex_color_set<ColorPaint4f, FloatTraits, ATTR_DOMAIN_CORNER>(ob, fill_color, layer); } else if (layer->type == CD_PROP_BYTE_COLOR) { - ok = vertex_color_set<ColorPaint4b, ByteTraits, ATTR_DOMAIN_CORNER>( - ob, fill_color, static_cast<ColorPaint4b *>(layer->data)); + ok = vertex_color_set<ColorPaint4b, ByteTraits, ATTR_DOMAIN_CORNER>(ob, fill_color, layer); } } /* Restore #Mesh.editflag. */ |