Sculpt: Add Transform, Trim, and Mesh Filter operators to Sculpt menu #104718

Merged
Joseph Eagar merged 19 commits from Tarek-Yasser/blender:sculpt_mode_add_menu_operators into main 2023-03-08 01:18:34 +01:00
9 changed files with 234 additions and 49 deletions

View File

@ -226,4 +226,5 @@ _km_hierarchy = [
('Transform Modal Map', 'EMPTY', 'WINDOW', []),
('Eyedropper Modal Map', 'EMPTY', 'WINDOW', []),
('Eyedropper ColorRamp PointSampling Map', 'EMPTY', 'WINDOW', []),
('Mesh Filter Modal Map', 'EMPTY', 'WINDOW', []),
]

View File

@ -6318,6 +6318,25 @@ def km_sculpt_expand_modal(_params):
])
return keymap
def km_sculpt_mesh_filter_modal_map(_params):
items = []
keymap = (
"Mesh Filter Modal Map",
{"space_type": 'EMPTY', "region_type": 'WINDOW', "modal": True},
{"items": items},
)
items.extend([
("CONFIRM", {"type": 'LEFTMOUSE', "value": 'PRESS', "any": True}, None),
("CONFIRM", {"type": 'LEFTMOUSE', "value": 'RELEASE', "any": True}, None),
("CONFIRM", {"type": 'RET', "value": 'RELEASE', "any": True}, None),
("CONFIRM", {"type": 'NUMPAD_ENTER', "value": 'RELEASE', "any": True}, None),
("CANCEL", {"type": 'ESC', "value": 'PRESS', "any": True}, None),
("CANCEL", {"type": 'RIGHTMOUSE', "value": 'PRESS', "any": True}, None),
])
return keymap
def km_curve_pen_modal_map(_params):
items = []
@ -8126,6 +8145,7 @@ def generate_keymaps(params=None):
km_view3d_dolly_modal(params),
km_paint_stroke_modal(params),
km_sculpt_expand_modal(params),
km_sculpt_mesh_filter_modal_map(params),
km_curve_pen_modal_map(params),
km_node_link_modal_map(params),

View File

@ -3219,17 +3219,35 @@ class VIEW3D_MT_sculpt(Menu):
def draw(self, _context):
layout = self.layout
layout.operator("transform.translate")
layout.operator("transform.rotate")
layout.operator("transform.resize", text="Scale")
props = layout.operator("sculpt.mesh_filter", text="Sphere")
props.type = 'SPHERE'
layout.separator()
props = layout.operator("paint.hide_show", text="Box Hide")
props.action = 'HIDE'
props = layout.operator("paint.hide_show", text="Box Show")
props.action = 'SHOW'
layout.separator()
props = layout.operator("sculpt.face_set_change_visibility", text="Toggle Visibility")
props.mode = 'TOGGLE'
props = layout.operator("sculpt.face_set_change_visibility", text="Hide Active Face Set")
props.mode = 'HIDE_ACTIVE'
props = layout.operator("paint.hide_show", text="Show All")
props.action = 'SHOW'
props.area = 'ALL'
props = layout.operator("paint.hide_show", text="Box Show")
props.action = 'SHOW'
props.area = 'INSIDE'
props = layout.operator("paint.hide_show", text="Box Hide")
props.action = 'HIDE'
props.area = 'INSIDE'
props = layout.operator("sculpt.face_set_change_visibility", text="Invert Visible")
props.mode = 'INVERT'
props = layout.operator("paint.hide_show", text="Hide Masked")
props.action = 'HIDE'
@ -3237,10 +3255,55 @@ class VIEW3D_MT_sculpt(Menu):
layout.separator()
props = layout.operator("sculpt.trim_box_gesture", text="Box Trim")
props.trim_mode = 'DIFFERENCE'
layout.operator("sculpt.trim_lasso_gesture", text="Lasso Trim")
props.trim_mode = 'DIFFERENCE'
props = layout.operator("sculpt.trim_box_gesture", text="Box Add")
props.trim_mode = 'JOIN'
layout.operator("sculpt.trim_lasso_gesture", text="Lasso Add")
props.trim_mode = 'JOIN'
layout.operator("sculpt.project_line_gesture", text="Line Project")
layout.separator()
# Fair Positions
props = layout.operator("sculpt.face_set_edit", text="Fair Positions")
props.mode = 'FAIR_POSITIONS'
# Fair Tangency
props = layout.operator("sculpt.face_set_edit", text="Fair Tangency")
props.mode = 'FAIR_TANGENCY'
layout.separator()
sculpt_filters_types = [
('SMOOTH', "Smooth"),
('SURFACE_SMOOTH', "Surface Smooth"),
('INFLATE', "Inflate"),
('RELAX', "Relax Topology"),
('RELAX_FACE_SETS', "Relax Face Sets"),
('SHARPEN', "Sharpen"),
('ENHANCE_DETAILS', "Enhance Details"),
('ERASE_DISCPLACEMENT', "Erase Multires Displacement"),
('RANDOM', "Randomize")
]
for filter_type, ui_name in sculpt_filters_types:
props = layout.operator("sculpt.mesh_filter", text=ui_name)
props.type = filter_type
layout.separator()
layout.menu("VIEW3D_MT_sculpt_set_pivot", text="Set Pivot")
layout.separator()
# Rebuild BVH
layout.operator("sculpt.optimize")
layout.separator()

View File

@ -18,6 +18,7 @@ struct ViewContext;
struct bContext;
struct rcti;
struct wmOperator;
struct wmKeyConfig;
/* sculpt.cc */
@ -28,6 +29,7 @@ bool ED_sculpt_mask_box_select(struct bContext *C,
const struct rcti *rect,
bool select);
void ED_keymap_sculpt(wmKeyConfig *keyconf);
/* sculpt_transform.cc */
void ED_sculpt_update_modal_transform(struct bContext *C, struct Object *ob);

View File

@ -982,7 +982,7 @@ void SCULPT_OT_face_sets_change_visibility(wmOperatorType *ot)
ot->invoke = sculpt_face_sets_change_visibility_invoke;
ot->poll = SCULPT_mode_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_DEPENDS_ON_CURSOR;
RNA_def_enum(ot->srna,
"mode",

View File

@ -5,6 +5,8 @@
* \ingroup edsculpt
*/
#include "DNA_modifier_types.h"
#include "DNA_windowmanager_types.h"
#include "MEM_guardedalloc.h"
#include "BLI_hash.h"
@ -13,12 +15,15 @@
#include "BLI_math_vector_types.hh"
#include "BLI_task.h"
#include "BLT_translation.h"
#include "DNA_meshdata_types.h"
#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_paint.h"
#include "BKE_pbvh.h"
#include "BKE_modifier.h"
#include "DEG_depsgraph.h"
@ -27,6 +32,8 @@
#include "ED_screen.h"
#include "ED_view3d.h"
#include "ED_util.h"
#include "ED_screen.h"
#include "paint_intern.h"
#include "sculpt_intern.hh"
@ -705,6 +712,57 @@ static void mesh_filter_surface_smooth_displace_task_cb(void *__restrict userdat
BKE_pbvh_vertex_iter_end;
}
enum {
FILTER_MESH_MODAL_CANCEL = 1,
FILTER_MESH_MODAL_CONFIRM,
};
wmKeyMap *filter_mesh_modal_keymap(wmKeyConfig *keyconf)
Review

NULL -> nullptr

NULL -> nullptr
{
static const EnumPropertyItem modal_items[] = {
{FILTER_MESH_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
{FILTER_MESH_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
{0, nullptr, 0, nullptr, nullptr},
};
wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Mesh Filter Modal Map");
/* This function is called for each space-type, only needs to add map once. */
if (keymap && keymap->modal_items) {
return nullptr;
}
keymap = WM_modalkeymap_ensure(keyconf, "Mesh Filter Modal Map", modal_items);
WM_modalkeymap_assign(keymap, "SCULPT_OT_mesh_filter");
return keymap;
}
static void sculpt_mesh_update_status_bar(bContext* C, wmOperator* op) {
char header[UI_MAX_DRAW_STR];
char buf[UI_MAX_DRAW_STR];
int available_len = sizeof(buf);
char* p = buf;
#define WM_MODALKEY(_id) \
WM_modalkeymap_operator_items_to_string_buf( \
op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
BLI_snprintf(
header,
sizeof(header),
TIP_("%s: Confirm, %s: Cancel"),
WM_MODALKEY(FILTER_MESH_MODAL_CONFIRM),
WM_MODALKEY(FILTER_MESH_MODAL_CANCEL)
);
#undef WM_MODALKEY
ED_workspace_status_text(C, TIP_(header));
}
static void sculpt_mesh_filter_apply(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
@ -790,17 +848,27 @@ static void sculpt_mesh_filter_apply_with_history(bContext *C, wmOperator *op)
RNA_float_set(op->ptr, "strength", initial_strength);
}
static void sculpt_mesh_filter_end(bContext *C, wmOperator * /*op*/)
static void sculpt_mesh_filter_end(bContext *C)
{
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
SCULPT_filter_cache_free(ss);
SCULPT_undo_push_end(ob);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
}
static void UNUSED_FUNCTION(sculpt_mesh_filter_cancel)(bContext *C, wmOperator * /*op*/)
static int sculpt_mesh_filter_confirm(SculptSession *ss, wmOperator* op, const eSculptMeshFilterType filter_type) {
float initial_strength = ss->filter_cache->start_filter_strength;
/* Don't update strength property if we're storing an event history. */
if (sculpt_mesh_filter_is_continuous(filter_type)) {
RNA_float_set(op->ptr, "strength", initial_strength);
}
return OPERATOR_FINISHED;
}
static void sculpt_mesh_filter_cancel(bContext *C, wmOperator * /*op*/)
{
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
@ -831,6 +899,7 @@ static void UNUSED_FUNCTION(sculpt_mesh_filter_cancel)(bContext *C, wmOperator *
BKE_pbvh_node_mark_update(node);
}
MEM_SAFE_FREE(nodes);
BKE_pbvh_update_bounds(ss->pbvh, PBVH_UpdateBB);
}
@ -841,16 +910,29 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *
SculptSession *ss = ob->sculpt;
const eSculptMeshFilterType filter_type = eSculptMeshFilterType(RNA_enum_get(op->ptr, "type"));
if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
float initial_strength = ss->filter_cache->start_filter_strength;
sculpt_mesh_filter_end(C, op);
WM_cursor_modal_set(CTX_wm_window(C), WM_CURSOR_EW_SCROLL);
sculpt_mesh_update_status_bar(C, op);
if (event->type == EVT_MODAL_MAP) {
int ret = OPERATOR_FINISHED;
switch (event->val) {
case FILTER_MESH_MODAL_CANCEL:
sculpt_mesh_filter_cancel(C, op);
SCULPT_undo_push_end_ex(ob, true);
ret = OPERATOR_CANCELLED;
break;
/* Don't update strength property if we're storing an event history. */
if (sculpt_mesh_filter_is_continuous(filter_type)) {
RNA_float_set(op->ptr, "strength", initial_strength);
case FILTER_MESH_MODAL_CONFIRM:
ret = sculpt_mesh_filter_confirm(ss, op, filter_type);
SCULPT_undo_push_end_ex(ob, false);
break;
}
return OPERATOR_FINISHED;
sculpt_mesh_filter_end(C);
ED_workspace_status_text(C, nullptr); /* Clear status bar */
WM_cursor_modal_restore(CTX_wm_window(C));
return ret;
}
if (event->type != MOUSEMOVE) {
@ -892,6 +974,39 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *
return OPERATOR_RUNNING_MODAL;
}
static void sculpt_filter_specific_init(const eSculptMeshFilterType filter_type, wmOperator* op, SculptSession* ss)
{
switch (filter_type) {
case MESH_FILTER_SURFACE_SMOOTH: {
const float shape_preservation = RNA_float_get(op->ptr, "surface_smooth_shape_preservation");
const float current_vertex_displacement = RNA_float_get(op->ptr,
"surface_smooth_current_vertex");
mesh_filter_surface_smooth_init(ss, shape_preservation, current_vertex_displacement);
break;
}
case MESH_FILTER_SHARPEN: {
const float smooth_ratio = RNA_float_get(op->ptr, "sharpen_smooth_ratio");
const float intensify_detail_strength = RNA_float_get(op->ptr,
"sharpen_intensify_detail_strength");
const int curvature_smooth_iterations = RNA_int_get(op->ptr,
"sharpen_curvature_smooth_iterations");
mesh_filter_sharpen_init(
ss, smooth_ratio, intensify_detail_strength, curvature_smooth_iterations);
break;
}
case MESH_FILTER_ENHANCE_DETAILS: {
mesh_filter_enhance_details_init_directions(ss);
break;
}
case MESH_FILTER_ERASE_DISPLACEMENT: {
mesh_filter_init_limit_surface_co(ss);
break;
}
default:
break;
}
}
/* Returns OPERATOR_PASS_THROUGH on success. */
static int sculpt_mesh_filter_start(bContext *C, wmOperator *op)
{
@ -946,35 +1061,7 @@ static int sculpt_mesh_filter_start(bContext *C, wmOperator *op)
filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
filter_cache->automasking = SCULPT_automasking_cache_init(sd, nullptr, ob);
switch (filter_type) {
case MESH_FILTER_SURFACE_SMOOTH: {
const float shape_preservation = RNA_float_get(op->ptr, "surface_smooth_shape_preservation");
const float current_vertex_displacement = RNA_float_get(op->ptr,
"surface_smooth_current_vertex");
mesh_filter_surface_smooth_init(ss, shape_preservation, current_vertex_displacement);
break;
}
case MESH_FILTER_SHARPEN: {
const float smooth_ratio = RNA_float_get(op->ptr, "sharpen_smooth_ratio");
const float intensify_detail_strength = RNA_float_get(op->ptr,
"sharpen_intensify_detail_strength");
const int curvature_smooth_iterations = RNA_int_get(op->ptr,
"sharpen_curvature_smooth_iterations");
mesh_filter_sharpen_init(
ss, smooth_ratio, intensify_detail_strength, curvature_smooth_iterations);
break;
}
case MESH_FILTER_ENHANCE_DETAILS: {
mesh_filter_enhance_details_init_directions(ss);
break;
}
case MESH_FILTER_ERASE_DISPLACEMENT: {
mesh_filter_init_limit_surface_co(ss);
break;
}
default:
break;
}
sculpt_filter_specific_init(filter_type, op, ss);
ss->filter_cache->enabled_axis[0] = deform_axis & MESH_FILTER_DEFORM_X;
ss->filter_cache->enabled_axis[1] = deform_axis & MESH_FILTER_DEFORM_Y;
@ -1021,7 +1108,7 @@ static int sculpt_mesh_filter_exec(bContext *C, wmOperator *op)
ss->filter_cache->no_orig_co = true;
}
sculpt_mesh_filter_end(C, op);
sculpt_mesh_filter_end(C);
return OPERATOR_FINISHED;
}
@ -1087,7 +1174,11 @@ void SCULPT_OT_mesh_filter(wmOperatorType *ot)
ot->exec = sculpt_mesh_filter_exec;
Review

Don't use // comments.

Don't use // comments.
ot->ui = sculpt_mesh_ui_exec;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* Doesn't seem to actually be called?
Check `sculpt_mesh_filter_modal` to see where it's really called. */
ot->cancel = sculpt_mesh_filter_cancel;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR_X | OPTYPE_BLOCKING | OPTYPE_DEPENDS_ON_CURSOR;
/* RNA. */
SCULPT_mesh_filter_properties(ot);

View File

@ -1683,6 +1683,7 @@ void SCULPT_OT_set_pivot_position(wmOperatorType *ot);
/* Mesh Filter. */
void SCULPT_OT_mesh_filter(wmOperatorType *ot);
struct wmKeyMap *filter_mesh_modal_keymap(struct wmKeyConfig *keyconf);
/* Cloth Filter. */

View File

@ -1427,3 +1427,9 @@ void ED_operatortypes_sculpt(void)
WM_operatortype_append(SCULPT_OT_mask_from_cavity);
WM_operatortype_append(SCULPT_OT_reveal_all);
}
void ED_keymap_sculpt(wmKeyConfig *keyconf)
{
filter_mesh_modal_keymap(keyconf);
}

View File

@ -193,6 +193,7 @@ void ED_spacetypes_keymap(wmKeyConfig *keyconf)
ED_keymap_paint(keyconf);
ED_keymap_mask(keyconf);
ED_keymap_marker(keyconf);
ED_keymap_sculpt(keyconf);
ED_keymap_view2d(keyconf);
ED_keymap_ui(keyconf);