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.
This commit is contained in:
Joseph Eagar
2023-02-27 01:49:12 -08:00
parent 6c03339e48
commit b4ee936627
3 changed files with 130 additions and 40 deletions

View File

@@ -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;
}

View File

@@ -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 <cmath>
#include <cstdlib>
@@ -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;

View File

@@ -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)