diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index 24cf65cdd91..9dbf9d12cf7 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -78,7 +78,6 @@ set(SRC sculpt_filter_mask.cc sculpt_filter_mesh.cc sculpt_geodesic.cc - sculpt_mask_expand.cc sculpt_mask_init.cc sculpt_multiplane_scrape.cc sculpt_ops.cc diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.hh b/source/blender/editors/sculpt_paint/sculpt_intern.hh index b2ff4f161a3..04f99e86e3c 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.hh +++ b/source/blender/editors/sculpt_paint/sculpt_intern.hh @@ -1596,10 +1596,6 @@ void SCULPT_OT_color_filter(wmOperatorType *ot); void SCULPT_OT_mask_filter(wmOperatorType *ot); -/* Mask and Face Sets Expand. */ - -void SCULPT_OT_mask_expand(wmOperatorType *ot); - /* Mask Init. */ void SCULPT_OT_mask_init(wmOperatorType *ot); diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_expand.cc b/source/blender/editors/sculpt_paint/sculpt_mask_expand.cc deleted file mode 100644 index a6d7454cbfb..00000000000 --- a/source/blender/editors/sculpt_paint/sculpt_mask_expand.cc +++ /dev/null @@ -1,523 +0,0 @@ -/* SPDX-FileCopyrightText: 2020 Blender Authors - * - * SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup edsculpt - */ - -#include "MEM_guardedalloc.h" - -#include "BLI_math_vector.h" -#include "BLI_task.h" - -#include "BLT_translation.h" - -#include "DNA_brush_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_modifier_types.h" -#include "DNA_object_types.h" - -#include "BKE_ccg.h" -#include "BKE_context.h" -#include "BKE_paint.hh" -#include "BKE_pbvh_api.hh" - -#include "DEG_depsgraph.hh" - -#include "WM_api.hh" -#include "WM_types.hh" - -#include "RNA_access.hh" -#include "RNA_define.hh" - -#include "ED_screen.hh" -#include "sculpt_intern.hh" - -#include "bmesh.h" - -#include -#include - -static void sculpt_mask_expand_cancel(bContext *C, wmOperator *op) -{ - Object *ob = CTX_data_active_object(C); - SculptSession *ss = ob->sculpt; - const bool create_face_set = RNA_boolean_get(op->ptr, "create_face_set"); - - MEM_freeN(op->customdata); - - for (int n = 0; n < ss->filter_cache->nodes.size(); n++) { - PBVHNode *node = ss->filter_cache->nodes[n]; - if (create_face_set) { - for (int i = 0; i < ss->totfaces; i++) { - ss->face_sets[i] = ss->filter_cache->prev_face_set[i]; - } - } - else { - PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { - *vd.mask = ss->filter_cache->prev_mask[vd.index]; - } - BKE_pbvh_vertex_iter_end; - } - - BKE_pbvh_node_mark_redraw(node); - } - - if (!create_face_set) { - SCULPT_flush_update_step(C, SCULPT_UPDATE_MASK); - } - SCULPT_filter_cache_free(ss); - SCULPT_undo_push_end(ob); - SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK); - ED_workspace_status_text(C, nullptr); -} - -static void sculpt_expand_task(Object *ob, - const int update_it, - const bool mask_expand_use_normals, - const bool mask_expand_create_face_set, - const bool mask_expand_keep_prev_mask, - const bool mask_expand_invert_mask, - PBVHNode *node) -{ - SculptSession *ss = ob->sculpt; - PBVHVertexIter vd; - - PBVHVertRef active_vertex = SCULPT_active_vertex_get(ss); - int active_vertex_i = BKE_pbvh_vertex_to_index(ss->pbvh, active_vertex); - - bool face_sets_changed = false; - - BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_ALL) { - int vi = vd.index; - float final_mask = *vd.mask; - if (mask_expand_use_normals) { - if (ss->filter_cache->normal_factor[active_vertex_i] < - ss->filter_cache->normal_factor[vd.index]) { - final_mask = 1.0f; - } - else { - final_mask = 0.0f; - } - } - else { - if (ss->filter_cache->mask_update_it[vi] <= update_it && - ss->filter_cache->mask_update_it[vi] != 0) { - final_mask = 1.0f; - } - else { - final_mask = 0.0f; - } - } - - if (mask_expand_create_face_set) { - if (final_mask == 1.0f) { - SCULPT_vertex_face_set_set(ss, vd.vertex, ss->filter_cache->new_face_set); - face_sets_changed = true; - } - BKE_pbvh_node_mark_redraw(node); - } - else { - - if (mask_expand_keep_prev_mask) { - final_mask = MAX2(ss->filter_cache->prev_mask[vd.index], final_mask); - } - - if (mask_expand_invert_mask) { - final_mask = 1.0f - final_mask; - } - - if (*vd.mask != final_mask) { - *vd.mask = final_mask; - BKE_pbvh_node_mark_update_mask(node); - } - } - } - BKE_pbvh_vertex_iter_end; - - if (face_sets_changed) { - SCULPT_undo_push_node(ob, node, SCULPT_UNDO_FACE_SETS); - } -} - -static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *event) -{ - using namespace blender; - Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - Object *ob = CTX_data_active_object(C); - SculptSession *ss = ob->sculpt; - Sculpt *sd = CTX_data_tool_settings(C)->sculpt; - ARegion *region = CTX_wm_region(C); - float prev_click_f[2]; - copy_v2_v2(prev_click_f, static_cast(op->customdata)); - const int prev_click[2] = {int(prev_click_f[0]), int(prev_click_f[1])}; - int len = int(len_v2v2_int(prev_click, event->mval)); - len = abs(len); - int mask_speed = RNA_int_get(op->ptr, "mask_speed"); - int mask_expand_update_it = len / mask_speed; - mask_expand_update_it = mask_expand_update_it + 1; - - const bool create_face_set = RNA_boolean_get(op->ptr, "create_face_set"); - - if (RNA_boolean_get(op->ptr, "use_cursor")) { - SculptCursorGeometryInfo sgi; - - const float mval_fl[2] = {float(event->mval[0]), float(event->mval[1])}; - if (SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false)) { - int active_vertex_i = BKE_pbvh_vertex_to_index(ss->pbvh, SCULPT_active_vertex_get(ss)); - - /* The cursor is over the mesh, get the update iteration from the updated active vertex. */ - mask_expand_update_it = ss->filter_cache->mask_update_it[active_vertex_i]; - } - else { - /* When the cursor is outside the mesh, affect the entire connected component. */ - mask_expand_update_it = ss->filter_cache->mask_update_last_it - 1; - } - } - - if ((event->type == EVT_ESCKEY && event->val == KM_PRESS) || - (event->type == RIGHTMOUSE && event->val == KM_PRESS)) - { - /* Returning OPERATOR_CANCELLED will leak memory due to not finishing - * undo. Better solution could be to make paint_mesh_restore_co work - * for this case. */ - sculpt_mask_expand_cancel(C, op); - return OPERATOR_FINISHED; - } - - if ((event->type == LEFTMOUSE && event->val == KM_RELEASE) || - (event->type == EVT_RETKEY && event->val == KM_PRESS) || - (event->type == EVT_PADENTER && event->val == KM_PRESS)) - { - - /* Smooth iterations. */ - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false); - const int smooth_iterations = RNA_int_get(op->ptr, "smooth_iterations"); - SCULPT_mask_filter_smooth_apply(sd, ob, ss->filter_cache->nodes, smooth_iterations); - - /* Pivot position. */ - if (RNA_boolean_get(op->ptr, "update_pivot")) { - const char symm = SCULPT_mesh_symmetry_xyz_get(ob); - const float threshold = 0.2f; - float avg[3]; - int total = 0; - zero_v3(avg); - - for (PBVHNode *node : ss->filter_cache->nodes) { - PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { - const float mask = (vd.mask) ? *vd.mask : 0.0f; - if (mask < (0.5f + threshold) && mask > (0.5f - threshold)) { - if (SCULPT_check_vertex_pivot_symmetry( - vd.co, ss->filter_cache->mask_expand_initial_co, symm)) { - add_v3_v3(avg, vd.co); - total++; - } - } - } - BKE_pbvh_vertex_iter_end; - } - - if (total > 0) { - mul_v3_fl(avg, 1.0f / total); - copy_v3_v3(ss->pivot_pos, avg); - } - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); - } - - MEM_freeN(op->customdata); - - for (PBVHNode *node : ss->filter_cache->nodes) { - BKE_pbvh_node_mark_redraw(node); - } - - SCULPT_filter_cache_free(ss); - - SCULPT_undo_push_end(ob); - SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK); - ED_workspace_status_text(C, nullptr); - return OPERATOR_FINISHED; - } - - /* When pressing Ctrl, expand directly to the max number of iterations. This allows to flood fill - * mask and face sets by connectivity directly. */ - if (event->modifier & KM_CTRL) { - mask_expand_update_it = ss->filter_cache->mask_update_last_it - 1; - } - - if (!ELEM(event->type, MOUSEMOVE, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY)) { - return OPERATOR_RUNNING_MODAL; - } - - if (mask_expand_update_it == ss->filter_cache->mask_update_current_it) { - ED_region_tag_redraw(region); - return OPERATOR_RUNNING_MODAL; - } - - if (mask_expand_update_it < ss->filter_cache->mask_update_last_it) { - - if (create_face_set) { - for (int i = 0; i < ss->totfaces; i++) { - ss->face_sets[i] = ss->filter_cache->prev_face_set[i]; - } - } - - const bool use_normals = RNA_boolean_get(op->ptr, "use_normals"); - const bool invert_mask = RNA_boolean_get(op->ptr, "invert"); - const bool keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"); - const bool create_face_set = RNA_boolean_get(op->ptr, "create_face_set"); - - threading::parallel_for(ss->filter_cache->nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - sculpt_expand_task(ob, - mask_expand_update_it, - use_normals, - create_face_set, - keep_prev_mask, - invert_mask, - ss->filter_cache->nodes[i]); - } - }); - - ss->filter_cache->mask_update_current_it = mask_expand_update_it; - } - - SCULPT_flush_update_step(C, SCULPT_UPDATE_MASK); - - return OPERATOR_RUNNING_MODAL; -} - -struct MaskExpandFloodFillData { - float original_normal[3]; - float edge_sensitivity; - bool use_normals; -}; - -static bool mask_expand_floodfill_cb( - SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate, void *userdata) -{ - MaskExpandFloodFillData *data = static_cast(userdata); - - int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v); - int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v); - - if (!is_duplicate) { - int to_it = ss->filter_cache->mask_update_it[from_v_i] + 1; - ss->filter_cache->mask_update_it[to_v_i] = to_it; - if (to_it > ss->filter_cache->mask_update_last_it) { - ss->filter_cache->mask_update_last_it = to_it; - } - - if (data->use_normals) { - float current_normal[3], prev_normal[3]; - SCULPT_vertex_normal_get(ss, to_v, current_normal); - SCULPT_vertex_normal_get(ss, from_v, prev_normal); - const float from_edge_factor = ss->filter_cache->edge_factor[from_v_i]; - ss->filter_cache->edge_factor[to_v_i] = dot_v3v3(current_normal, prev_normal) * - from_edge_factor; - ss->filter_cache->normal_factor[to_v_i] = dot_v3v3(data->original_normal, current_normal) * - powf(from_edge_factor, data->edge_sensitivity); - CLAMP(ss->filter_cache->normal_factor[to_v_i], 0.0f, 1.0f); - } - } - else { - /* PBVH_GRIDS duplicate handling. */ - ss->filter_cache->mask_update_it[to_v_i] = ss->filter_cache->mask_update_it[from_v_i]; - if (data->use_normals) { - ss->filter_cache->edge_factor[to_v_i] = ss->filter_cache->edge_factor[from_v_i]; - ss->filter_cache->normal_factor[to_v_i] = ss->filter_cache->normal_factor[from_v_i]; - } - } - - return true; -} - -static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - using namespace blender; - Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - Object *ob = CTX_data_active_object(C); - SculptSession *ss = ob->sculpt; - Sculpt *sd = CTX_data_tool_settings(C)->sculpt; - PBVH *pbvh = ob->sculpt->pbvh; - - const bool use_normals = RNA_boolean_get(op->ptr, "use_normals"); - const bool create_face_set = RNA_boolean_get(op->ptr, "create_face_set"); - - SculptCursorGeometryInfo sgi; - const float mval_fl[2] = {float(event->mval[0]), float(event->mval[1])}; - - MultiresModifierData *mmd = BKE_sculpt_multires_active(CTX_data_scene(C), ob); - BKE_sculpt_mask_layers_ensure(depsgraph, CTX_data_main(C), ob, mmd); - - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); - - SCULPT_vertex_random_access_ensure(ss); - - op->customdata = MEM_mallocN(sizeof(float[2]), "initial mouse position"); - copy_v2_v2(static_cast(op->customdata), mval_fl); - - SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false); - - int vertex_count = SCULPT_vertex_count_get(ss); - - ss->filter_cache = MEM_new(__func__); - - ss->filter_cache->nodes = blender::bke::pbvh::search_gather(pbvh, {}); - - SCULPT_undo_push_begin(ob, op); - - if (create_face_set) { - for (PBVHNode *node : ss->filter_cache->nodes) { - BKE_pbvh_node_mark_redraw(node); - SCULPT_undo_push_node(ob, node, SCULPT_UNDO_FACE_SETS); - } - } - else { - for (PBVHNode *node : ss->filter_cache->nodes) { - SCULPT_undo_push_node(ob, node, SCULPT_UNDO_MASK); - BKE_pbvh_node_mark_redraw(node); - } - } - - ss->filter_cache->mask_update_it = MEM_cnew_array(vertex_count, __func__); - if (use_normals) { - ss->filter_cache->normal_factor = MEM_cnew_array(vertex_count, __func__); - ss->filter_cache->edge_factor = MEM_cnew_array(vertex_count, __func__); - for (int i = 0; i < vertex_count; i++) { - ss->filter_cache->edge_factor[i] = 1.0f; - } - } - - if (create_face_set) { - ss->filter_cache->prev_face_set = MEM_cnew_array(ss->totfaces, __func__); - for (int i = 0; i < ss->totfaces; i++) { - ss->filter_cache->prev_face_set[i] = ss->face_sets ? ss->face_sets[i] : 0; - } - ss->filter_cache->new_face_set = SCULPT_face_set_next_available_get(ss); - } - else { - ss->filter_cache->prev_mask = MEM_cnew_array(vertex_count, __func__); - for (int i = 0; i < vertex_count; i++) { - PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i); - - ss->filter_cache->prev_mask[i] = SCULPT_vertex_mask_get(ss, vertex); - } - } - - int active_vertex_i = BKE_pbvh_vertex_to_index(ss->pbvh, SCULPT_active_vertex_get(ss)); - - ss->filter_cache->mask_update_last_it = 1; - ss->filter_cache->mask_update_current_it = 1; - ss->filter_cache->mask_update_it[active_vertex_i] = 0; - - copy_v3_v3(ss->filter_cache->mask_expand_initial_co, SCULPT_active_vertex_co_get(ss)); - - SculptFloodFill flood; - SCULPT_floodfill_init(ss, &flood); - SCULPT_floodfill_add_active(sd, ob, ss, &flood, FLT_MAX); - - MaskExpandFloodFillData fdata{}; - fdata.use_normals = use_normals; - fdata.edge_sensitivity = RNA_int_get(op->ptr, "edge_sensitivity"); - - SCULPT_active_vertex_normal_get(ss, fdata.original_normal); - SCULPT_floodfill_execute(ss, &flood, mask_expand_floodfill_cb, &fdata); - SCULPT_floodfill_free(&flood); - - if (use_normals) { - for (int repeat = 0; repeat < 2; repeat++) { - for (int i = 0; i < vertex_count; i++) { - PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i); - - float avg = 0.0f; - SculptVertexNeighborIter ni; - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) { - avg += ss->filter_cache->normal_factor[ni.index]; - } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); - ss->filter_cache->normal_factor[i] = avg / ni.size; - } - } - - MEM_SAFE_FREE(ss->filter_cache->edge_factor); - } - - const bool invert_mask = RNA_boolean_get(op->ptr, "invert"); - const bool keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"); - - threading::parallel_for(ss->filter_cache->nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - sculpt_expand_task(ob, - 0, - use_normals, - create_face_set, - keep_prev_mask, - invert_mask, - ss->filter_cache->nodes[i]); - } - }); - - const char *status_str = TIP_( - "Move the mouse to expand the mask from the active vertex. LMB: confirm mask, ESC/RMB: " - "cancel"); - ED_workspace_status_text(C, status_str); - - SCULPT_flush_update_step(C, SCULPT_UPDATE_MASK); - WM_event_add_modal_handler(C, op); - return OPERATOR_RUNNING_MODAL; -} - -void SCULPT_OT_mask_expand(wmOperatorType *ot) -{ - /* Identifiers. */ - ot->name = "Mask Expand"; - ot->idname = "SCULPT_OT_mask_expand"; - ot->description = "Expands a mask from the initial active vertex under the cursor"; - - /* API callbacks. */ - ot->invoke = sculpt_mask_expand_invoke; - ot->modal = sculpt_mask_expand_modal; - ot->cancel = sculpt_mask_expand_cancel; - ot->poll = SCULPT_mode_poll; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - ot->prop = RNA_def_boolean(ot->srna, "invert", true, "Invert", "Invert the new mask"); - ot->prop = RNA_def_boolean( - ot->srna, "use_cursor", true, "Use Cursor", "Expand the mask to the cursor position"); - ot->prop = RNA_def_boolean(ot->srna, - "update_pivot", - true, - "Update Pivot Position", - "Set the pivot position to the mask border after creating the mask"); - ot->prop = RNA_def_int(ot->srna, "smooth_iterations", 2, 0, 10, "Smooth Iterations", "", 0, 10); - ot->prop = RNA_def_int(ot->srna, "mask_speed", 5, 1, 10, "Mask Speed", "", 1, 10); - - ot->prop = RNA_def_boolean(ot->srna, - "use_normals", - true, - "Use Normals", - "Generate the mask using the normals and curvature of the model"); - ot->prop = RNA_def_boolean(ot->srna, - "keep_previous_mask", - false, - "Keep Previous Mask", - "Generate the new mask on top of the current one"); - ot->prop = RNA_def_int(ot->srna, - "edge_sensitivity", - 300, - 0, - 2000, - "Edge Detection Sensitivity", - "Sensitivity for expanding the mask across sculpted sharp edges when " - "using normals to generate the mask", - 0, - 2000); - ot->prop = RNA_def_boolean(ot->srna, - "create_face_set", - false, - "Expand Face Mask", - "Expand a new Face Mask instead of the sculpt mask"); -} diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.cc b/source/blender/editors/sculpt_paint/sculpt_ops.cc index 514b999dbed..6e1e55b18c2 100644 --- a/source/blender/editors/sculpt_paint/sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/sculpt_ops.cc @@ -1358,7 +1358,6 @@ void ED_operatortypes_sculpt() WM_operatortype_append(SCULPT_OT_set_detail_size); WM_operatortype_append(SCULPT_OT_mesh_filter); WM_operatortype_append(SCULPT_OT_mask_filter); - WM_operatortype_append(SCULPT_OT_mask_expand); WM_operatortype_append(SCULPT_OT_set_pivot_position); WM_operatortype_append(SCULPT_OT_face_sets_create); WM_operatortype_append(SCULPT_OT_face_set_change_visibility);