diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint')
6 files changed, 150 insertions, 121 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 8a9d1bba92c..4e15728b081 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2506,7 +2506,7 @@ float SCULPT_brush_strength_factor(SculptSession *ss, avg *= 1.0f - mask; /* Auto-masking. */ - avg *= SCULPT_automasking_factor_get(ss, vertex_index); + avg *= SCULPT_automasking_factor_get(cache->automasking, ss, vertex_index); return avg; } @@ -3908,7 +3908,7 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata, mul_v3_fl(final_disp, 1.0f - *vd.mask); } - mul_v3_fl(final_disp, SCULPT_automasking_factor_get(ss, vd.index)); + mul_v3_fl(final_disp, SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index)); copy_v3_v3(proxy[vd.i], final_disp); @@ -5760,7 +5760,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe if (SCULPT_stroke_is_first_brush_step(ss->cache)) { if (SCULPT_is_automasking_enabled(sd, ss, brush)) { - SCULPT_automasking_init(sd, ob); + ss->cache->automasking = SCULPT_automasking_cache_init(sd, brush, ob); } } @@ -7764,7 +7764,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str } if (SCULPT_is_automasking_enabled(sd, ss, brush)) { - SCULPT_automasking_end(ob); + SCULPT_automasking_cache_free(ss->cache->automasking); } BKE_pbvh_node_color_buffer_free(ss->pbvh); diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c index 241f1167316..f2fc1bcb3c9 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.c +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c @@ -62,16 +62,30 @@ #include <math.h> #include <stdlib.h> +AutomaskingCache *SCULPT_automasking_active_cache_get(SculptSession *ss) +{ + if (ss->cache) { + return ss->cache->automasking; + } + else if (ss->filter_cache) { + return ss->filter_cache->automasking; + } + return NULL; +} + bool SCULPT_is_automasking_mode_enabled(const Sculpt *sd, const Brush *br, const eAutomasking_flag mode) { - return br->automasking_flags & mode || sd->automasking_flags & mode; + if (br) { + return br->automasking_flags & mode || sd->automasking_flags & mode; + } + return sd->automasking_flags & mode; } bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, const Brush *br) { - if (SCULPT_stroke_is_dynamic_topology(ss, br)) { + if (br && SCULPT_stroke_is_dynamic_topology(ss, br)) { return false; } if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_TOPOLOGY)) { @@ -91,10 +105,13 @@ bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, co static int sculpt_automasking_mode_effective_bits(const Sculpt *sculpt, const Brush *brush) { - return sculpt->automasking_flags | brush->automasking_flags; + if (brush) { + return sculpt->automasking_flags | brush->automasking_flags; + } + return sculpt->automasking_flags; } -static bool SCULPT_automasking_needs_cache(const Sculpt *sd, const Brush *brush) +static bool SCULPT_automasking_needs_factors_cache(const Sculpt *sd, const Brush *brush) { const int automasking_flags = sculpt_automasking_mode_effective_bits(sd, brush); @@ -102,39 +119,39 @@ static bool SCULPT_automasking_needs_cache(const Sculpt *sd, const Brush *brush) return true; } if (automasking_flags & BRUSH_AUTOMASKING_BOUNDARY_EDGES) { - return brush->automasking_boundary_edges_propagation_steps != 1; + return brush && brush->automasking_boundary_edges_propagation_steps != 1; } if (automasking_flags & BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS) { - return brush->automasking_boundary_edges_propagation_steps != 1; + return brush && brush->automasking_boundary_edges_propagation_steps != 1; } return false; } -float SCULPT_automasking_factor_get(SculptSession *ss, int vert) +float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession *ss, int vert) { - if (!ss->cache) { + if (!automasking) { return 1.0f; } /* If the cache is initialized with valid info, use the cache. This is used when the * automasking information can't be computed in real time per vertex and needs to be * initialized for the whole mesh when the stroke starts. */ - if (ss->cache->automask_factor) { - return ss->cache->automask_factor[vert]; + if (automasking->factor) { + return automasking->factor[vert]; } - if (ss->cache->automask_settings.flags & BRUSH_AUTOMASKING_FACE_SETS) { - if (!SCULPT_vertex_has_face_set(ss, vert, ss->cache->automask_settings.initial_face_set)) { + if (automasking->settings.flags & BRUSH_AUTOMASKING_FACE_SETS) { + if (!SCULPT_vertex_has_face_set(ss, vert, automasking->settings.initial_face_set)) { return 0.0f; } } - if (ss->cache->automask_settings.flags & BRUSH_AUTOMASKING_BOUNDARY_EDGES) { + if (automasking->settings.flags & BRUSH_AUTOMASKING_BOUNDARY_EDGES) { if (SCULPT_vertex_is_boundary(ss, vert)) { return 0.0f; } } - if (ss->cache->automask_settings.flags & BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS) { + if (automasking->settings.flags & BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS) { if (!SCULPT_vertex_has_unique_face_set(ss, vert)) { return 0.0f; } @@ -143,12 +160,14 @@ float SCULPT_automasking_factor_get(SculptSession *ss, int vert) return 1.0f; } -void SCULPT_automasking_end(Object *ob) +void SCULPT_automasking_cache_free(AutomaskingCache *automasking) { - SculptSession *ss = ob->sculpt; - if (ss->cache && ss->cache->automask_factor) { - MEM_freeN(ss->cache->automask_factor); + if (!automasking) { + return; } + + MEM_SAFE_FREE(automasking->factor); + MEM_SAFE_FREE(automasking); } static bool sculpt_automasking_is_constrained_by_radius(Brush *br) @@ -189,10 +208,6 @@ static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *au SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); - if (!SCULPT_is_automasking_enabled(sd, ss, brush)) { - return NULL; - } - if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) { BLI_assert(!"Topology masking: pmap missing"); return NULL; @@ -200,19 +215,20 @@ static float *SCULPT_topology_automasking_init(Sculpt *sd, Object *ob, float *au const int totvert = SCULPT_vertex_count_get(ss); for (int i = 0; i < totvert; i++) { - ss->cache->automask_factor[i] = 0.0f; + automask_factor[i] = 0.0f; } /* Flood fill automask to connected vertices. Limited to vertices inside * the brush radius if the tool requires it. */ SculptFloodFill flood; SCULPT_floodfill_init(ss, &flood); - SCULPT_floodfill_add_active(sd, ob, ss, &flood, ss->cache->radius); + const float radius = ss->cache ? ss->cache->radius : FLT_MAX; + SCULPT_floodfill_add_active(sd, ob, ss, &flood, radius); AutomaskFloodFillData fdata = { .automask_factor = automask_factor, - .radius = ss->cache->radius, - .use_radius = sculpt_automasking_is_constrained_by_radius(brush), + .radius = radius, + .use_radius = ss->cache && sculpt_automasking_is_constrained_by_radius(brush), .symm = SCULPT_mesh_symmetry_xyz_get(ob), }; copy_v3_v3(fdata.location, SCULPT_active_vertex_co_get(ss)); @@ -306,58 +322,60 @@ float *SCULPT_boundary_automasking_init(Object *ob, return automask_factor; } -static void SCULPT_stroke_automasking_settings_update(SculptSession *ss, Sculpt *sd, Brush *brush) +static void SCULPT_automasking_cache_settings_update(AutomaskingCache *automasking, + SculptSession *ss, + Sculpt *sd, + Brush *brush) { - BLI_assert(ss->cache); - - ss->cache->automask_settings.flags = sculpt_automasking_mode_effective_bits(sd, brush); - ss->cache->automask_settings.initial_face_set = SCULPT_active_face_set_get(ss); + automasking->settings.flags = sculpt_automasking_mode_effective_bits(sd, brush); + automasking->settings.initial_face_set = SCULPT_active_face_set_get(ss); } -void SCULPT_automasking_init(Sculpt *sd, Object *ob) +AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object *ob) { SculptSession *ss = ob->sculpt; - Brush *brush = BKE_paint_brush(&sd->paint); const int totvert = SCULPT_vertex_count_get(ss); if (!SCULPT_is_automasking_enabled(sd, ss, brush)) { - return; + return NULL; } - SCULPT_stroke_automasking_settings_update(ss, sd, brush); + AutomaskingCache *automasking = MEM_callocN(sizeof(AutomaskingCache), "automasking cache"); + SCULPT_automasking_cache_settings_update(automasking, ss, sd, brush); SCULPT_boundary_info_ensure(ob); - if (!SCULPT_automasking_needs_cache(sd, brush)) { - return; + if (!SCULPT_automasking_needs_factors_cache(sd, brush)) { + return automasking; } - ss->cache->automask_factor = MEM_malloc_arrayN(totvert, sizeof(float), "automask_factor"); - + automasking->factor = MEM_malloc_arrayN(totvert, sizeof(float), "automask_factor"); for (int i = 0; i < totvert; i++) { - ss->cache->automask_factor[i] = 1.0f; + automasking->factor[i] = 1.0f; } + const int boundary_propagation_steps = brush ? + brush->automasking_boundary_edges_propagation_steps : + 1; + if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_TOPOLOGY)) { SCULPT_vertex_random_access_ensure(ss); - SCULPT_topology_automasking_init(sd, ob, ss->cache->automask_factor); + SCULPT_topology_automasking_init(sd, ob, automasking->factor); } if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_FACE_SETS)) { SCULPT_vertex_random_access_ensure(ss); - sculpt_face_sets_automasking_init(sd, ob, ss->cache->automask_factor); + sculpt_face_sets_automasking_init(sd, ob, automasking->factor); } if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) { SCULPT_vertex_random_access_ensure(ss); - SCULPT_boundary_automasking_init(ob, - AUTOMASK_INIT_BOUNDARY_EDGES, - brush->automasking_boundary_edges_propagation_steps, - ss->cache->automask_factor); + SCULPT_boundary_automasking_init( + ob, AUTOMASK_INIT_BOUNDARY_EDGES, boundary_propagation_steps, automasking->factor); } if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) { SCULPT_vertex_random_access_ensure(ss); - SCULPT_boundary_automasking_init(ob, - AUTOMASK_INIT_BOUNDARY_FACE_SETS, - brush->automasking_boundary_edges_propagation_steps, - ss->cache->automask_factor); + SCULPT_boundary_automasking_init( + ob, AUTOMASK_INIT_BOUNDARY_FACE_SETS, boundary_propagation_steps, automasking->factor); } + + return automasking; } diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index 84d156122f3..efd80eef0cb 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -723,6 +723,8 @@ static void do_cloth_brush_solve_simulation_task_cb_ex( return; } + AutomaskingCache *automasking = SCULPT_automasking_active_cache_get(ss); + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { float sim_location[3]; @@ -743,7 +745,7 @@ static void do_cloth_brush_solve_simulation_task_cb_ex( mul_v3_fl(pos_diff, (1.0f - cloth_sim->damping) * sim_factor); const float mask_v = (1.0f - (vd.mask ? *vd.mask : 0.0f)) * - SCULPT_automasking_factor_get(ss, vd.index); + SCULPT_automasking_factor_get(automasking, ss, vd.index); madd_v3_v3fl(cloth_sim->pos[i], pos_diff, mask_v); madd_v3_v3fl(cloth_sim->pos[i], cloth_sim->acceleration[i], mask_v); @@ -775,6 +777,9 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss, Brush *brush, SculptClothSimulation *cloth_sim) { + + AutomaskingCache *automasking = SCULPT_automasking_active_cache_get(ss); + for (int constraint_it = 0; constraint_it < CLOTH_SIMULATION_ITERATIONS; constraint_it++) { for (int i = 0; i < cloth_sim->tot_length_constraints; i++) { const SculptClothLengthConstraint *constraint = &cloth_sim->length_constraints[i]; @@ -807,9 +812,9 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss, mul_v3_v3fl(correction_vector_half, correction_vector, 0.5f); const float mask_v1 = (1.0f - SCULPT_vertex_mask_get(ss, v1)) * - SCULPT_automasking_factor_get(ss, v1); + SCULPT_automasking_factor_get(automasking, ss, v1); const float mask_v2 = (1.0f - SCULPT_vertex_mask_get(ss, v2)) * - SCULPT_automasking_factor_get(ss, v2); + SCULPT_automasking_factor_get(automasking, ss, v2); float sim_location[3]; cloth_brush_simulation_location_get(ss, brush, sim_location); @@ -1354,6 +1359,7 @@ static void cloth_filter_apply_forces_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { float fade = vd.mask ? *vd.mask : 0.0f; + fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.index); fade = 1.0f - fade; float force[3] = {0.0f, 0.0f, 0.0f}; float disp[3], temp[3], transform[3][3]; @@ -1498,6 +1504,8 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent SCULPT_undo_push_begin("Cloth filter"); SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS); + ss->filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob); + const float cloth_mass = RNA_float_get(op->ptr, "cloth_mass"); const float cloth_damping = RNA_float_get(op->ptr, "cloth_damping"); const bool use_collisions = RNA_boolean_get(op->ptr, "use_collisions"); diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c index 89af836d095..07986bbb032 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c @@ -119,6 +119,10 @@ static void color_filter_task_cb(void *__restrict userdata, float fade = vd.mask ? *vd.mask : 0.0f; fade = 1.0f - fade; fade *= data->filter_strength; + fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.index); + if (fade == 0.0f) { + continue; + } copy_v3_v3(orig_color, orig_data.col); @@ -255,7 +259,7 @@ static int sculpt_color_filter_modal(bContext *C, wmOperator *op, const wmEvent return OPERATOR_RUNNING_MODAL; } -static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *ob = CTX_data_active_object(C); Sculpt *sd = CTX_data_tool_settings(C)->sculpt; @@ -263,6 +267,17 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent int mode = RNA_enum_get(op->ptr, "type"); PBVH *pbvh = ob->sculpt->pbvh; + const bool use_automasking = SCULPT_is_automasking_enabled(sd, ss, NULL); + if (use_automasking) { + /* Update the active face set manually as the paint cursor is not enabled when using the Mesh + * Filter Tool. */ + float mouse[2]; + SculptCursorGeometryInfo sgi; + mouse[0] = event->mval[0]; + mouse[1] = event->mval[1]; + SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); + } + /* Disable for multires and dyntopo for now */ if (!ss->pbvh) { return OPERATOR_CANCELLED; @@ -282,14 +297,17 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent /* CTX_data_ensure_evaluated_depsgraph should be used at the end to include the updates of * earlier steps modifying the data. */ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - bool needs_pmap = mode == COLOR_FILTER_SMOOTH; - BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false, true); + const bool needs_topology_info = mode == COLOR_FILTER_SMOOTH || use_automasking; + BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_topology_info, false, true); - if (BKE_pbvh_type(pbvh) == PBVH_FACES && needs_pmap && !ob->sculpt->pmap) { + if (BKE_pbvh_type(pbvh) == PBVH_FACES && needs_topology_info && !ob->sculpt->pmap) { return OPERATOR_CANCELLED; } SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COLOR); + FilterCache *filter_cache = ss->filter_cache; + filter_cache->active_face_set = SCULPT_FACE_SET_NONE; + filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob); WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index c2e90638994..349e492a496 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -179,12 +179,14 @@ void SCULPT_filter_cache_free(SculptSession *ss) if (ss->filter_cache->cloth_sim) { SCULPT_cloth_simulation_free(ss->filter_cache->cloth_sim); } + if (ss->filter_cache->automasking) { + SCULPT_automasking_cache_free(ss->filter_cache->automasking); + } MEM_SAFE_FREE(ss->filter_cache->nodes); MEM_SAFE_FREE(ss->filter_cache->mask_update_it); MEM_SAFE_FREE(ss->filter_cache->prev_mask); MEM_SAFE_FREE(ss->filter_cache->normal_factor); MEM_SAFE_FREE(ss->filter_cache->prev_face_set); - MEM_SAFE_FREE(ss->filter_cache->automask); MEM_SAFE_FREE(ss->filter_cache->surface_smooth_laplacian_disp); MEM_SAFE_FREE(ss->filter_cache->sharpen_factor); MEM_SAFE_FREE(ss->filter_cache->detail_directions); @@ -269,15 +271,15 @@ static EnumPropertyItem prop_mesh_filter_orientation_items[] = { {0, NULL, 0, NULL, NULL}, }; -static bool sculpt_mesh_filter_needs_pmap(eSculptMeshFilterType filter_type, bool use_face_sets) +static bool sculpt_mesh_filter_needs_pmap(eSculptMeshFilterType filter_type) { - return use_face_sets || ELEM(filter_type, - MESH_FILTER_SMOOTH, - MESH_FILTER_RELAX, - MESH_FILTER_RELAX_FACE_SETS, - MESH_FILTER_SURFACE_SMOOTH, - MESH_FILTER_ENHANCE_DETAILS, - MESH_FILTER_SHARPEN); + return ELEM(filter_type, + MESH_FILTER_SMOOTH, + MESH_FILTER_RELAX, + MESH_FILTER_RELAX_FACE_SETS, + MESH_FILTER_SURFACE_SMOOTH, + MESH_FILTER_ENHANCE_DETAILS, + MESH_FILTER_SHARPEN); } static void mesh_filter_task_cb(void *__restrict userdata, @@ -307,33 +309,16 @@ static void mesh_filter_task_cb(void *__restrict userdata, float fade = vd.mask ? *vd.mask : 0.0f; fade = 1.0f - fade; fade *= data->filter_strength; + fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.index); - if (fade == 0.0f) { + if (fade == 0.0f && filter_type != MESH_FILTER_SURFACE_SMOOTH) { + /* Surface Smooth can't skip the loop for this vertex as it needs to calculate its + * laplacian_disp. This value is accessed from the vertex neighbors when deforming the + * vertices, so it is needed for all vertices even if they are not going to be displaced. + */ continue; } - if (ss->filter_cache->active_face_set != SCULPT_FACE_SET_NONE) { - if (!SCULPT_vertex_has_face_set(ss, vd.index, ss->filter_cache->active_face_set)) { - /* Surface Smooth can't skip the loop for this vertex as it needs to calculate its - * laplacian_disp. This value is accessed from the vertex neighbors when deforming the - * vertices, so it is needed for all vertices even if they are not going to be displaced. - */ - if (filter_type == MESH_FILTER_SURFACE_SMOOTH) { - fade = 0.0f; - } - else { - continue; - } - } - /* Skip the edges of the face set when relaxing or smoothing. - * There is a relax face set option to relax the boundaries independently. */ - if (filter_type == MESH_FILTER_RELAX) { - if (!SCULPT_vertex_has_unique_face_set(ss, vd.index)) { - continue; - } - } - } - if (ELEM(filter_type, MESH_FILTER_RELAX, MESH_FILTER_RELAX_FACE_SETS)) { copy_v3_v3(orig_co, vd.co); } @@ -606,16 +591,11 @@ static void mesh_filter_surface_smooth_displace_task_cb( float fade = vd.mask ? *vd.mask : 0.0f; fade = 1.0f - fade; fade *= data->filter_strength; + fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.index); if (fade == 0.0f) { continue; } - if (ss->filter_cache->active_face_set != SCULPT_FACE_SET_NONE) { - if (!SCULPT_vertex_has_face_set(ss, vd.index, ss->filter_cache->active_face_set)) { - continue; - } - } - SCULPT_surface_smooth_displace_step(ss, vd.co, ss->filter_cache->surface_smooth_laplacian_disp, @@ -634,7 +614,6 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent * Sculpt *sd = CTX_data_tool_settings(C)->sculpt; eSculptMeshFilterType filter_type = RNA_enum_get(op->ptr, "type"); float filter_strength = RNA_float_get(op->ptr, "strength"); - const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets"); if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { SCULPT_filter_cache_free(ss); @@ -652,7 +631,7 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent * SCULPT_vertex_random_access_ensure(ss); - bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets); + bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type); BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false, false); SculptThreadedTaskData data = { @@ -700,15 +679,15 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent const eMeshFilterDeformAxis deform_axis = RNA_enum_get(op->ptr, "deform_axis"); const eSculptMeshFilterType filter_type = RNA_enum_get(op->ptr, "type"); - const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets"); - const bool needs_topology_info = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets); + const bool use_automasking = SCULPT_is_automasking_enabled(sd, ss, NULL); + const bool needs_topology_info = sculpt_mesh_filter_needs_pmap(filter_type) || use_automasking; if (deform_axis == 0) { /* All axis are disabled, so the filter is not going to produce any deformation. */ return OPERATOR_CANCELLED; } - if (use_face_sets) { + if (use_automasking) { /* Update the active face set manually as the paint cursor is not enabled when using the Mesh * Filter Tool. */ float mouse[2]; @@ -729,8 +708,8 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS); FilterCache *filter_cache = ss->filter_cache; - filter_cache->active_face_set = use_face_sets ? SCULPT_active_face_set_get(ss) : - SCULPT_FACE_SET_NONE; + filter_cache->active_face_set = SCULPT_FACE_SET_NONE; + filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob); switch (filter_type) { case MESH_FILTER_SURFACE_SMOOTH: { @@ -808,11 +787,6 @@ void SCULPT_OT_mesh_filter(struct wmOperatorType *ot) SCULPT_FILTER_ORIENTATION_LOCAL, "Orientation", "Orientation of the axis to limit the filter displacement"); - ot->prop = RNA_def_boolean(ot->srna, - "use_face_sets", - false, - "Use Face Sets", - "Apply the filter only to the Face Mask under the cursor"); /* Surface Smooth Mesh Filter properties. */ RNA_def_float(ot->srna, diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 6cdaafb548c..1fddfc7d6db 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -36,6 +36,7 @@ #include "BKE_paint.h" #include "BKE_pbvh.h" +struct AutomaskingCache; struct KeyBlock; struct Object; struct SculptPoseIKChainSegment; @@ -329,10 +330,16 @@ enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob); void SCULPT_pbvh_clear(Object *ob); /* Automasking. */ -float SCULPT_automasking_factor_get(SculptSession *ss, int vert); +float SCULPT_automasking_factor_get(struct AutomaskingCache *automasking, + SculptSession *ss, + int vert); -void SCULPT_automasking_init(Sculpt *sd, Object *ob); -void SCULPT_automasking_end(Object *ob); +/* Returns the automasking cache depending on the active tool. Used for code that can run both for + * brushes and filter. */ +struct AutomaskingCache *SCULPT_automasking_active_cache_get(SculptSession *ss); + +struct AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, Brush *brush, Object *ob); +void SCULPT_automasking_cache_free(struct AutomaskingCache *automasking); bool SCULPT_is_automasking_mode_enabled(const Sculpt *sd, const Brush *br, @@ -826,6 +833,13 @@ typedef struct AutomaskingSettings { int initial_face_set; } AutomaskingSettings; +typedef struct AutomaskingCache { + AutomaskingSettings settings; + /* Precomputed automask factor indexed by vertex, owned by the automasking system and initialized + * in SCULPT_automasking_cache_init when needed. */ + float *factor; +} AutomaskingCache; + typedef struct StrokeCache { /* Invariants */ float initial_radius; @@ -966,10 +980,7 @@ typedef struct StrokeCache { float gravity_direction[3]; /* Automasking. */ - AutomaskingSettings automask_settings; - /* Precomputed automask factor indexed by vertex, owned by the automasking system and initialized - * in SCULPT_automasking_init when needed. */ - float *automask_factor; + AutomaskingCache *automasking; float stroke_local_mat[4][4]; float multiplane_scrape_angle; @@ -1041,13 +1052,13 @@ typedef struct FilterCache { float *prev_mask; float mask_expand_initial_co[3]; - /* Used to prevent undesired results on certain mesh filters. */ - float *automask; - int new_face_set; int *prev_face_set; int active_face_set; + + /* Automasking. */ + AutomaskingCache *automasking; } FilterCache; void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache, |