From b4ee9366278a8159af5e2b97bfc18ccc29354aa3 Mon Sep 17 00:00:00 2001 From: Joseph Eagar Date: Mon, 27 Feb 2023 01:49:12 -0800 Subject: [PATCH] Sculpt: Add support for last operator panel to color filter operator * Refactored the color filter op to have an ->exec callback. * Added nullptr checks to the filter cache API to support running outside of a view3d context. * Redo panel displays the active filter type's name in the header. --- source/blender/editors/sculpt_paint/sculpt.cc | 3 +- .../sculpt_paint/sculpt_filter_color.cc | 143 ++++++++++++++---- .../sculpt_paint/sculpt_filter_mesh.cc | 24 +-- 3 files changed, 130 insertions(+), 40 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index ebe483cbd25..ff97cbf3023 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -5526,7 +5526,8 @@ void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags) SCULPT_update_object_bounding_box(ob); } - if (SCULPT_get_redraw_rect(region, CTX_wm_region_view3d(C), ob, &r)) { + RegionView3D *rv3d = CTX_wm_region_view3d(C); + if (rv3d && SCULPT_get_redraw_rect(region, rv3d, ob, &r)) { if (ss->cache) { ss->cache->current_r = r; } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.cc b/source/blender/editors/sculpt_paint/sculpt_filter_color.cc index 36d02c65605..3ef97990225 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_color.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.cc @@ -12,6 +12,7 @@ #include "BLI_task.h" #include "DNA_meshdata_types.h" +#include "DNA_userdef_types.h" #include "BKE_context.h" #include "BKE_paint.h" @@ -30,6 +31,9 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include #include @@ -258,29 +262,15 @@ static void sculpt_color_presmooth_init(SculptSession *ss) } } -static int sculpt_color_filter_modal(bContext *C, wmOperator *op, const wmEvent *event) +static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object *ob) { - Object *ob = CTX_data_active_object(C); - SculptSession *ss = ob->sculpt; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + SculptSession *ss = ob->sculpt; + const int mode = RNA_enum_get(op->ptr, "type"); float filter_strength = RNA_float_get(op->ptr, "strength"); - - if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { - SCULPT_undo_push_end(ob); - SCULPT_filter_cache_free(ss); - SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COLOR); - return OPERATOR_FINISHED; - } - - if (event->type != MOUSEMOVE) { - return OPERATOR_RUNNING_MODAL; - } - - const float len = event->prev_press_xy[0] - event->xy[0]; - filter_strength = filter_strength * -len * 0.001f; - float fill_color[3]; + RNA_float_get_array(op->ptr, "fill_color", fill_color); IMB_colormanagement_srgb_to_scene_linear_v3(fill_color, fill_color); @@ -303,31 +293,63 @@ static int sculpt_color_filter_modal(bContext *C, wmOperator *op, const wmEvent BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, color_filter_task_cb, &settings); SCULPT_flush_update_step(C, SCULPT_UPDATE_COLOR); +} + +static void sculpt_color_filter_end(bContext *C, Object *ob) +{ + SculptSession *ss = ob->sculpt; + + SCULPT_undo_push_end(ob); + SCULPT_filter_cache_free(ss); + SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COLOR); +} + +static int sculpt_color_filter_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + Object *ob = CTX_data_active_object(C); + SculptSession *ss = ob->sculpt; + + if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + sculpt_color_filter_end(C, ob); + return OPERATOR_FINISHED; + } + + if (event->type != MOUSEMOVE) { + return OPERATOR_RUNNING_MODAL; + } + + const float len = (event->prev_press_xy[0] - event->xy[0]) * 0.001f; + float filter_strength = ss->filter_cache->start_filter_strength * -len; + RNA_float_set(op->ptr, "strength", filter_strength); + + sculpt_color_filter_apply(C, op, ob); return OPERATOR_RUNNING_MODAL; } -static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static int sculpt_color_filter_init(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); Sculpt *sd = CTX_data_tool_settings(C)->sculpt; - View3D *v3d = CTX_wm_view3d(C); SculptSession *ss = ob->sculpt; PBVH *pbvh = ob->sculpt->pbvh; - if (v3d->shading.type == OB_SOLID) { - v3d->shading.color_type = V3D_SHADING_VERTEX_COLOR; - } + View3D *v3d = CTX_wm_view3d(C); + + int mval[2]; + RNA_int_get_array(op->ptr, "start_mouse", mval); const bool use_automasking = SCULPT_is_automasking_enabled(sd, ss, nullptr); if (use_automasking) { /* Increment stroke id for auto-masking system. */ SCULPT_stroke_id_next(ob); - /* Update the active face set manually as the paint cursor is not enabled when using the Mesh - * Filter Tool. */ - float mval_fl[2] = {float(event->mval[0]), float(event->mval[1])}; - SculptCursorGeometryInfo sgi; - SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false); + if (v3d) { + /* Update the active face set manually as the paint cursor is not enabled when using the Mesh + * Filter Tool. */ + float mval_fl[2] = {float(mval[0]), float(mval[1])}; + SculptCursorGeometryInfo sgi; + SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false); + } } /* Disable for multires and dyntopo for now */ @@ -351,18 +373,78 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent ob, sd, SCULPT_UNDO_COLOR, - event->mval, + mval, RNA_float_get(op->ptr, "area_normal_radius"), RNA_float_get(op->ptr, "strength")); FilterCache *filter_cache = ss->filter_cache; filter_cache->active_face_set = SCULPT_FACE_SET_NONE; filter_cache->automasking = SCULPT_automasking_cache_init(sd, nullptr, ob); + + return OPERATOR_PASS_THROUGH; +} + +static int sculpt_color_filter_exec(bContext *C, wmOperator *op) +{ + Object *ob = CTX_data_active_object(C); + + if (sculpt_color_filter_init(C, op) == OPERATOR_CANCELLED) { + return OPERATOR_CANCELLED; + } + + sculpt_color_filter_apply(C, op, ob); + sculpt_color_filter_end(C, ob); + + return OPERATOR_FINISHED; +} + +static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + Object *ob = CTX_data_active_object(C); + View3D *v3d = CTX_wm_view3d(C); + if (v3d && v3d->shading.type == OB_SOLID) { + v3d->shading.color_type = V3D_SHADING_VERTEX_COLOR; + } + + RNA_int_set_array(op->ptr, "start_mouse", event->mval); + + if (sculpt_color_filter_init(C, op) == OPERATOR_CANCELLED) { + return OPERATOR_CANCELLED; + } + ED_paint_tool_update_sticky_shading_color(C, ob); WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; } +static const char *sculpt_color_filter_get_name(wmOperatorType *ot, PointerRNA *ptr) +{ + int mode = RNA_enum_get(ptr, "type"); + EnumPropertyItem *item = prop_color_filter_types; + + while (item->identifier) { + if (item->value == mode) { + return item->name; + } + + item++; + } + + BLI_assert_unreachable(); + return "error"; +} + +static void sculpt_color_filter_ui(bContext * /*C*/, wmOperator *op) +{ + uiLayout *layout = op->layout; + + uiItemR(layout, op->ptr, "strength", 0, nullptr, ICON_NONE); + + if (RNA_enum_get(op->ptr, "type") == COLOR_FILTER_FILL) { + uiItemR(layout, op->ptr, "fill_color", 0, nullptr, ICON_NONE); + } +} + void SCULPT_OT_color_filter(wmOperatorType *ot) { /* identifiers */ @@ -372,8 +454,11 @@ void SCULPT_OT_color_filter(wmOperatorType *ot) /* api callbacks */ ot->invoke = sculpt_color_filter_invoke; + ot->exec = sculpt_color_filter_exec; ot->modal = sculpt_color_filter_modal; ot->poll = SCULPT_mode_poll; + ot->ui = sculpt_color_filter_ui; + ot->get_name = sculpt_color_filter_get_name; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc index 7ce0f822330..c7d965ceeaf 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc @@ -162,8 +162,10 @@ void SCULPT_filter_cache_init(bContext *C, ED_view3d_viewcontext_init(C, &vc, depsgraph); ss->filter_cache->vc = vc; - copy_m4_m4(ss->filter_cache->viewmat, vc.rv3d->viewmat); - copy_m4_m4(ss->filter_cache->viewmat_inv, vc.rv3d->viewinv); + if (vc.rv3d) { + copy_m4_m4(ss->filter_cache->viewmat, vc.rv3d->viewmat); + copy_m4_m4(ss->filter_cache->viewmat_inv, vc.rv3d->viewinv); + } Scene *scene = CTX_data_scene(C); UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; @@ -171,7 +173,7 @@ void SCULPT_filter_cache_init(bContext *C, float co[3]; float mval_fl[2] = {float(mval[0]), float(mval[1])}; - if (SCULPT_stroke_get_location(C, co, mval_fl, false)) { + if (vc.rv3d && SCULPT_stroke_get_location(C, co, mval_fl, false)) { PBVHNode **nodes; int totnode; @@ -229,14 +231,16 @@ void SCULPT_filter_cache_init(bContext *C, float mat[3][3]; float viewDir[3] = {0.0f, 0.0f, 1.0f}; - ED_view3d_ob_project_mat_get(vc.rv3d, ob, projection_mat); + if (vc.rv3d) { + ED_view3d_ob_project_mat_get(vc.rv3d, ob, projection_mat); - invert_m4_m4(ob->world_to_object, ob->object_to_world); - copy_m3_m4(mat, vc.rv3d->viewinv); - mul_m3_v3(mat, viewDir); - copy_m3_m4(mat, ob->world_to_object); - mul_m3_v3(mat, viewDir); - normalize_v3_v3(ss->filter_cache->view_normal, viewDir); + invert_m4_m4(ob->world_to_object, ob->object_to_world); + copy_m3_m4(mat, vc.rv3d->viewinv); + mul_m3_v3(mat, viewDir); + copy_m3_m4(mat, ob->world_to_object); + mul_m3_v3(mat, viewDir); + normalize_v3_v3(ss->filter_cache->view_normal, viewDir); + } } void SCULPT_filter_cache_free(SculptSession *ss)