diff options
6 files changed, 201 insertions, 7 deletions
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index c3c6e77067e..050d7879e58 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -6319,6 +6319,27 @@ def km_3d_view_tool_sculpt_lasso_mask(params): ]}, ) +def km_3d_view_tool_sculpt_box_face_set(params): + return ( + "3D View Tool: Sculpt, Box Face Set", + {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, + {"items": [ + ("sculpt.face_set_box_gesture", {"type": params.tool_tweak, "value": 'ANY'}, + None), + ]}, + ) + + +def km_3d_view_tool_sculpt_lasso_face_set(params): + return ( + "3D View Tool: Sculpt, Lasso Face Set", + {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, + {"items": [ + ("sculpt.face_set_lasso_gesture", {"type": params.tool_tweak, "value": 'ANY'}, + None), + ]}, + ) + def km_3d_view_tool_sculpt_mesh_filter(params): return ( "3D View Tool: Sculpt, Mesh Filter", @@ -6912,6 +6933,8 @@ def generate_keymaps(params=None): km_3d_view_tool_sculpt_box_hide(params), km_3d_view_tool_sculpt_box_mask(params), km_3d_view_tool_sculpt_lasso_mask(params), + km_3d_view_tool_sculpt_box_face_set(params), + km_3d_view_tool_sculpt_lasso_face_set(params), km_3d_view_tool_sculpt_mesh_filter(params), km_3d_view_tool_sculpt_cloth_filter(params), km_3d_view_tool_sculpt_color_filter(params), diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index e336635a4ee..c17b981a6b8 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -1255,6 +1255,37 @@ class _defs_sculpt: ) @ToolDef.from_fn + def face_set_box(): + def draw_settings(_context, layout, tool): + props = tool.operator_properties("sculpt.face_set_box_gesture") + layout.prop(props, "use_front_faces_only", expand=False) + + return dict( + idname="builtin.box_face_set", + label="Box Face Set", + icon="ops.sculpt.border_face_set", + widget=None, + keymap=(), + draw_settings=draw_settings, + ) + + @ToolDef.from_fn + def face_set_lasso(): + def draw_settings(_context, layout, tool): + props = tool.operator_properties("sculpt.face_set_lasso_gesture") + layout.prop(props, "use_front_faces_only", expand=False) + + return dict( + idname="builtin.lasso_face_set", + label="Lasso Face Set", + icon="ops.sculpt.lasso_face_set", + widget=None, + keymap=(), + draw_settings=draw_settings, + ) + + + @ToolDef.from_fn def mesh_filter(): def draw_settings(_context, layout, tool): props = tool.operator_properties("sculpt.mesh_filter") @@ -2596,6 +2627,10 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): _defs_sculpt.mask_border, _defs_sculpt.mask_lasso, ), + ( + _defs_sculpt.face_set_box, + _defs_sculpt.face_set_lasso, + ), _defs_sculpt.hide_border, None, _defs_sculpt.mesh_filter, diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index ab8b81a8155..a8726482ccc 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -37,6 +37,7 @@ #include "BKE_ccg.h" #include "BKE_context.h" +#include "BKE_mesh.h" #include "BKE_multires.h" #include "BKE_paint.h" #include "BKE_pbvh.h" @@ -229,6 +230,11 @@ typedef enum eSculptGestureShapeType { SCULPT_GESTURE_SHAPE_LASSO, } eMaskGesturesShapeType; +typedef enum eSculptGestureOperationType { + SCULPT_GESTURE_MASK, + SCULPT_GESTURE_FACE_SET, +} eSculptGestureOperationType; + typedef struct LassoGestureData { float projviewobjmat[4][4]; @@ -249,12 +255,16 @@ typedef struct SculptGestureContext { /* Operation parameters. */ eMaskGesturesShapeType shape_type; + eSculptGestureOperationType operation; bool front_faces_only; /* Mask operation parameters. */ PaintMaskFloodMode mask_mode; float mask_value; + /* Face Set operation parameters. */ + int new_face_set_id; + /* View parameters. */ float true_view_normal[3]; float view_normal[3]; @@ -523,13 +533,46 @@ static void mask_gesture_apply_task_cb(void *__restrict userdata, } } +static void face_set_gesture_apply_task_cb(void *__restrict userdata, + const int i, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + SculptGestureContext *sgcontext = userdata; + PBVHNode *node = sgcontext->nodes[i]; + PBVHVertexIter vd; + bool any_updated = false; + + BKE_pbvh_vertex_iter_begin(sgcontext->ss->pbvh, node, vd, PBVH_ITER_UNIQUE) + { + if (sculpt_gesture_is_vertex_effected(sgcontext, &vd)) { + SCULPT_vertex_face_set_set(sgcontext->ss, vd.index, sgcontext->new_face_set_id); + any_updated = true; + } + } + BKE_pbvh_vertex_iter_end; + + if (any_updated) { + BKE_pbvh_node_mark_update_visibility(node); + } +} + static void sculpt_gesture_apply(bContext *C, SculptGestureContext *mcontext) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - BKE_sculpt_update_object_for_edit(depsgraph, mcontext->vc.obact, false, true, false); + + const bool needs_mask = mcontext->operation == SCULPT_GESTURE_MASK; + const bool needs_connectivity = mcontext->operation == SCULPT_GESTURE_FACE_SET; + + BKE_sculpt_update_object_for_edit( + depsgraph, mcontext->vc.obact, needs_connectivity, needs_mask, false); SCULPT_undo_push_begin("Sculpt Gesture Apply"); + if (mcontext->operation == SCULPT_GESTURE_FACE_SET) { + /* Face Sets modifications do a single undo push. */ + SCULPT_undo_push_node(mcontext->vc.obact, NULL, SCULPT_UNDO_FACE_SETS); + } + for (ePaintSymmetryFlags symmpass = 0; symmpass <= mcontext->symm; symmpass++) { if (SCULPT_is_symmetry_iteration_valid(symmpass, mcontext->symm)) { sculpt_gesture_flip_for_symmetry_pass(mcontext, symmpass); @@ -537,18 +580,33 @@ static void sculpt_gesture_apply(bContext *C, SculptGestureContext *mcontext) TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, mcontext->totnode); - BLI_task_parallel_range( - 0, mcontext->totnode, mcontext, mask_gesture_apply_task_cb, &settings); + switch (mcontext->operation) { + case SCULPT_GESTURE_MASK: + BLI_task_parallel_range( + 0, mcontext->totnode, mcontext, mask_gesture_apply_task_cb, &settings); + break; + case SCULPT_GESTURE_FACE_SET: + BLI_task_parallel_range( + 0, mcontext->totnode, mcontext, face_set_gesture_apply_task_cb, &settings); + break; + } MEM_SAFE_FREE(mcontext->nodes); } } - if (BKE_pbvh_type(mcontext->ss->pbvh) == PBVH_GRIDS) { - multires_mark_as_modified(depsgraph, mcontext->vc.obact, MULTIRES_COORDS_MODIFIED); - } + switch (mcontext->operation) { + case SCULPT_GESTURE_MASK: + if (BKE_pbvh_type(mcontext->ss->pbvh) == PBVH_GRIDS) { + multires_mark_as_modified(depsgraph, mcontext->vc.obact, MULTIRES_COORDS_MODIFIED); + } + BKE_pbvh_update_vertex_data(mcontext->ss->pbvh, PBVH_UpdateMask); + break; - BKE_pbvh_update_vertex_data(mcontext->ss->pbvh, PBVH_UpdateMask); + case SCULPT_GESTURE_FACE_SET: + BKE_pbvh_update_vertex_data(mcontext->ss->pbvh, PBVH_UpdateVisibility); + break; + } SCULPT_undo_push_end(); @@ -556,8 +614,17 @@ static void sculpt_gesture_apply(bContext *C, SculptGestureContext *mcontext) WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, mcontext->vc.obact); } +static void sculpt_gesture_init_face_set_properties(SculptGestureContext *sgcontext, + wmOperator *UNUSED(op)) +{ + sgcontext->operation = SCULPT_GESTURE_FACE_SET; + struct Mesh *mesh = BKE_mesh_from_object(sgcontext->vc.obact); + sgcontext->new_face_set_id = ED_sculpt_face_sets_find_next_available_id(mesh); +} + static void sculpt_gesture_init_mask_properties(SculptGestureContext *sgcontext, wmOperator *op) { + sgcontext->operation = SCULPT_GESTURE_MASK; sgcontext->mask_mode = RNA_enum_get(op->ptr, "mode"); sgcontext->mask_value = RNA_float_get(op->ptr, "value"); } @@ -601,6 +668,30 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int face_set_gesture_box_exec(bContext *C, wmOperator *op) +{ + SculptGestureContext *sgcontext = sculpt_gesture_init_from_box(C, op); + if (!sgcontext) { + return OPERATOR_CANCELLED; + } + sculpt_gesture_init_face_set_properties(sgcontext, op); + sculpt_gesture_apply(C, sgcontext); + sculpt_gesture_context_free(sgcontext); + return OPERATOR_FINISHED; +} + +static int face_set_gesture_lasso_exec(bContext *C, wmOperator *op) +{ + SculptGestureContext *sgcontext = sculpt_gesture_init_from_lasso(C, op); + if (!sgcontext) { + return OPERATOR_CANCELLED; + } + sculpt_gesture_init_face_set_properties(sgcontext, op); + sculpt_gesture_apply(C, sgcontext); + sculpt_gesture_context_free(sgcontext); + return OPERATOR_FINISHED; +} + void PAINT_OT_mask_lasso_gesture(wmOperatorType *ot) { ot->name = "Mask Lasso Gesture"; @@ -642,3 +733,41 @@ void PAINT_OT_mask_box_gesture(wmOperatorType *ot) paint_mask_gesture_operator_properties(ot); } + +void SCULPT_OT_face_set_lasso_gesture(wmOperatorType *ot) +{ + ot->name = "Face Set Lasso Gesture"; + ot->idname = "SCULPT_OT_face_set_lasso_gesture"; + ot->description = "Add face set within the lasso as you move the brush"; + + ot->invoke = WM_gesture_lasso_invoke; + ot->modal = WM_gesture_lasso_modal; + ot->exec = face_set_gesture_lasso_exec; + + ot->poll = SCULPT_mode_poll; + + ot->flag = OPTYPE_REGISTER; + + /* Properties. */ + WM_operator_properties_gesture_lasso(ot); + sculpt_gesture_operator_properties(ot); +} + +void SCULPT_OT_face_set_box_gesture(wmOperatorType *ot) +{ + ot->name = "Face Set Box Gesture"; + ot->idname = "SCULPT_OT_face_set_box_gesture"; + ot->description = "Add face set within the box as you move the brush"; + + ot->invoke = WM_gesture_box_invoke; + ot->modal = WM_gesture_box_modal; + ot->exec = face_set_gesture_box_exec; + + ot->poll = SCULPT_mode_poll; + + ot->flag = OPTYPE_REGISTER; + + /* Properties. */ + WM_operator_properties_border(ot); + sculpt_gesture_operator_properties(ot); +} diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 1078e97e7cf..1601bae628e 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -9156,6 +9156,8 @@ void ED_operatortypes_sculpt(void) WM_operatortype_append(SCULPT_OT_face_sets_init); WM_operatortype_append(SCULPT_OT_cloth_filter); WM_operatortype_append(SCULPT_OT_face_sets_edit); + WM_operatortype_append(SCULPT_OT_face_set_lasso_gesture); + WM_operatortype_append(SCULPT_OT_face_set_box_gesture); WM_operatortype_append(SCULPT_OT_sample_color); WM_operatortype_append(SCULPT_OT_loop_to_vertex_colors); diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 47a375a2318..d7497a6cd4c 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -1050,6 +1050,10 @@ bool SCULPT_get_redraw_rect(struct ARegion *region, /* Operators. */ +/* Gestures. */ +void SCULPT_OT_face_set_lasso_gesture(struct wmOperatorType *ot); +void SCULPT_OT_face_set_box_gesture(struct wmOperatorType *ot); + /* Face Sets. */ void SCULPT_OT_face_sets_randomize_colors(struct wmOperatorType *ot); void SCULPT_OT_face_sets_change_visibility(struct wmOperatorType *ot); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 9b25d660ff6..db8a1511da3 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3904,6 +3904,7 @@ static void gesture_box_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "CLIP_OT_graph_select_box"); WM_modalkeymap_assign(keymap, "MASK_OT_select_box"); WM_modalkeymap_assign(keymap, "PAINT_OT_mask_box_gesture"); + WM_modalkeymap_assign(keymap, "SCULPT_OT_face_set_box_gesture"); WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border"); WM_modalkeymap_assign(keymap, "VIEW3D_OT_clip_border"); WM_modalkeymap_assign(keymap, "VIEW3D_OT_render_border"); |