Paint: decouple op->customdata from PaintStroke
Previously, all operators using `PaintStroke` would have to store the stroke in `op->customdata`. That made it impossible to store other operator specific data in `op->customdata` that was unrelated to the stroke. This patch changes it so that the `PaintStroke` is passed to api functions as a separate argument, which allows storing the stroke as a subfield of some other struct in `op->customdata`.
This commit is contained in:
parent
5be74160c0
commit
141d5851d7
Notes:
blender-bot
2023-02-14 09:36:46 +01:00
Referenced by issue #96957, Creating 'Paint' Curve in Blender 3.2 April 1 build crashes Blender
|
@ -59,9 +59,14 @@ static int sculpt_curves_stroke_invoke(bContext *C, wmOperator *op, const wmEven
|
|||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
static int sculpt_curves_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
return paint_stroke_modal(C, op, event, static_cast<PaintStroke *>(op->customdata));
|
||||
}
|
||||
|
||||
static void sculpt_curves_stroke_cancel(bContext *C, wmOperator *op)
|
||||
{
|
||||
paint_stroke_cancel(C, op);
|
||||
paint_stroke_cancel(C, op, static_cast<PaintStroke *>(op->customdata));
|
||||
}
|
||||
|
||||
static void SCULPT_CURVES_OT_brush_stroke(struct wmOperatorType *ot)
|
||||
|
@ -71,7 +76,7 @@ static void SCULPT_CURVES_OT_brush_stroke(struct wmOperatorType *ot)
|
|||
ot->description = "Sculpt curves using a brush";
|
||||
|
||||
ot->invoke = sculpt_curves_stroke_invoke;
|
||||
ot->modal = paint_stroke_modal;
|
||||
ot->modal = sculpt_curves_stroke_modal;
|
||||
ot->cancel = sculpt_curves_stroke_cancel;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
|
|
@ -685,7 +685,7 @@ static int paint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
event->type);
|
||||
|
||||
if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
|
||||
paint_stroke_free(C, op);
|
||||
paint_stroke_free(C, op, op->customdata);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
/* add modal handler */
|
||||
|
@ -720,7 +720,17 @@ static int paint_exec(bContext *C, wmOperator *op)
|
|||
paint_stroke_done,
|
||||
0);
|
||||
/* frees op->customdata */
|
||||
return paint_stroke_exec(C, op);
|
||||
return paint_stroke_exec(C, op, op->customdata);
|
||||
}
|
||||
|
||||
static int paint_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
return paint_stroke_modal(C, op, event, op->customdata);
|
||||
}
|
||||
|
||||
static void paint_cancel(bContext *C, wmOperator *op)
|
||||
{
|
||||
paint_stroke_cancel(C, op, op->customdata);
|
||||
}
|
||||
|
||||
void PAINT_OT_image_paint(wmOperatorType *ot)
|
||||
|
@ -732,10 +742,10 @@ void PAINT_OT_image_paint(wmOperatorType *ot)
|
|||
|
||||
/* api callbacks */
|
||||
ot->invoke = paint_invoke;
|
||||
ot->modal = paint_stroke_modal;
|
||||
ot->modal = paint_modal;
|
||||
ot->exec = paint_exec;
|
||||
ot->poll = image_paint_poll;
|
||||
ot->cancel = paint_stroke_cancel;
|
||||
ot->cancel = paint_cancel;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_BLOCKING;
|
||||
|
|
|
@ -62,7 +62,7 @@ struct PaintStroke *paint_stroke_new(struct bContext *C,
|
|||
StrokeRedraw redraw,
|
||||
StrokeDone done,
|
||||
int event_type);
|
||||
void paint_stroke_free(struct bContext *C, struct wmOperator *op);
|
||||
void paint_stroke_free(struct bContext *C, struct wmOperator *op, struct PaintStroke *stroke);
|
||||
|
||||
/**
|
||||
* Returns zero if the stroke dots should not be spaced, non-zero otherwise.
|
||||
|
@ -84,9 +84,12 @@ bool paint_supports_jitter(enum ePaintMode mode);
|
|||
* Called in paint_ops.c, on each regeneration of key-maps.
|
||||
*/
|
||||
struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf);
|
||||
int paint_stroke_modal(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
|
||||
int paint_stroke_exec(struct bContext *C, struct wmOperator *op);
|
||||
void paint_stroke_cancel(struct bContext *C, struct wmOperator *op);
|
||||
int paint_stroke_modal(struct bContext *C,
|
||||
struct wmOperator *op,
|
||||
const struct wmEvent *event,
|
||||
struct PaintStroke *stroke);
|
||||
int paint_stroke_exec(struct bContext *C, struct wmOperator *op, struct PaintStroke *stroke);
|
||||
void paint_stroke_cancel(struct bContext *C, struct wmOperator *op, struct PaintStroke *stroke);
|
||||
bool paint_stroke_flipped(struct PaintStroke *stroke);
|
||||
bool paint_stroke_inverted(struct PaintStroke *stroke);
|
||||
struct ViewContext *paint_stroke_view_context(struct PaintStroke *stroke);
|
||||
|
|
|
@ -505,16 +505,13 @@ static bool paint_stroke_use_jitter(ePaintMode mode, Brush *brush, bool invert)
|
|||
}
|
||||
|
||||
/* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */
|
||||
static void paint_brush_stroke_add_step(bContext *C,
|
||||
wmOperator *op,
|
||||
const float mouse_in[2],
|
||||
float pressure)
|
||||
static void paint_brush_stroke_add_step(
|
||||
bContext *C, wmOperator *op, PaintStroke *stroke, const float mouse_in[2], float pressure)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Paint *paint = BKE_paint_get_active_from_context(C);
|
||||
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
|
||||
Brush *brush = BKE_paint_brush(paint);
|
||||
PaintStroke *stroke = op->customdata;
|
||||
UnifiedPaintSettings *ups = stroke->ups;
|
||||
float mouse_out[2];
|
||||
PointerRNA itemptr;
|
||||
|
@ -785,12 +782,12 @@ static float paint_space_stroke_spacing_variable(bContext *C,
|
|||
* towards the final mouse location. */
|
||||
static int paint_space_stroke(bContext *C,
|
||||
wmOperator *op,
|
||||
PaintStroke *stroke,
|
||||
const float final_mouse[2],
|
||||
float final_pressure)
|
||||
{
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
PaintStroke *stroke = op->customdata;
|
||||
UnifiedPaintSettings *ups = stroke->ups;
|
||||
Paint *paint = BKE_paint_get_active_from_context(C);
|
||||
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
|
||||
|
@ -852,7 +849,7 @@ static int paint_space_stroke(bContext *C,
|
|||
spacing / no_pressure_spacing);
|
||||
|
||||
stroke->stroke_distance += spacing / stroke->zoom_2d;
|
||||
paint_brush_stroke_add_step(C, op, mouse, pressure);
|
||||
paint_brush_stroke_add_step(C, op, stroke, mouse, pressure);
|
||||
|
||||
length -= spacing;
|
||||
pressure = stroke->last_pressure;
|
||||
|
@ -929,7 +926,7 @@ PaintStroke *paint_stroke_new(bContext *C,
|
|||
return stroke;
|
||||
}
|
||||
|
||||
void paint_stroke_free(bContext *C, wmOperator *op)
|
||||
void paint_stroke_free(bContext *C, wmOperator *UNUSED(op), PaintStroke *stroke)
|
||||
{
|
||||
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
||||
if (rv3d) {
|
||||
|
@ -938,7 +935,6 @@ void paint_stroke_free(bContext *C, wmOperator *op)
|
|||
|
||||
BKE_paint_set_overlay_override(0);
|
||||
|
||||
PaintStroke *stroke = op->customdata;
|
||||
if (stroke == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -961,12 +957,11 @@ void paint_stroke_free(bContext *C, wmOperator *op)
|
|||
|
||||
BLI_freelistN(&stroke->line);
|
||||
|
||||
MEM_SAFE_FREE(op->customdata);
|
||||
MEM_SAFE_FREE(stroke);
|
||||
}
|
||||
|
||||
static void stroke_done(bContext *C, wmOperator *op)
|
||||
static void stroke_done(bContext *C, wmOperator *op, PaintStroke *stroke)
|
||||
{
|
||||
PaintStroke *stroke = op->customdata;
|
||||
UnifiedPaintSettings *ups = stroke->ups;
|
||||
|
||||
/* reset rotation here to avoid doing so in cursor display */
|
||||
|
@ -988,7 +983,7 @@ static void stroke_done(bContext *C, wmOperator *op)
|
|||
}
|
||||
}
|
||||
|
||||
paint_stroke_free(C, op);
|
||||
paint_stroke_free(C, op, stroke);
|
||||
}
|
||||
|
||||
bool paint_space_stroke_enabled(Brush *br, ePaintMode mode)
|
||||
|
@ -1230,7 +1225,7 @@ static void paint_line_strokes_spacing(bContext *C,
|
|||
ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, 1.0);
|
||||
|
||||
stroke->stroke_distance += spacing / stroke->zoom_2d;
|
||||
paint_brush_stroke_add_step(C, op, mouse, 1.0);
|
||||
paint_brush_stroke_add_step(C, op, stroke, mouse, 1.0);
|
||||
|
||||
length -= spacing;
|
||||
spacing_final = spacing;
|
||||
|
@ -1252,8 +1247,8 @@ static void paint_stroke_line_end(bContext *C,
|
|||
if (stroke->stroke_started && (br->flag & BRUSH_LINE)) {
|
||||
stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
|
||||
|
||||
paint_brush_stroke_add_step(C, op, stroke->last_mouse_position, 1.0);
|
||||
paint_space_stroke(C, op, mouse, 1.0);
|
||||
paint_brush_stroke_add_step(C, op, stroke, stroke->last_mouse_position, 1.0);
|
||||
paint_space_stroke(C, op, stroke, mouse, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1331,7 +1326,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
|
|||
stroke->stroke_started = stroke->test_start(C, op, stroke->last_mouse_position);
|
||||
|
||||
if (stroke->stroke_started) {
|
||||
paint_brush_stroke_add_step(C, op, data + 2 * j, 1.0);
|
||||
paint_brush_stroke_add_step(C, op, stroke, data + 2 * j, 1.0);
|
||||
paint_line_strokes_spacing(
|
||||
C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
|
||||
}
|
||||
|
@ -1343,7 +1338,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
|
|||
}
|
||||
}
|
||||
|
||||
stroke_done(C, op);
|
||||
stroke_done(C, op, stroke);
|
||||
|
||||
#ifdef DEBUG_TIME
|
||||
TIMEIT_END_AVERAGED(whole_stroke);
|
||||
|
@ -1384,11 +1379,10 @@ static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2])
|
|||
}
|
||||
}
|
||||
|
||||
int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintStroke *stroke)
|
||||
{
|
||||
Paint *p = BKE_paint_get_active_from_context(C);
|
||||
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
|
||||
PaintStroke *stroke = op->customdata;
|
||||
Brush *br = stroke->brush = BKE_paint_brush(p);
|
||||
PaintSample sample_average;
|
||||
float mouse[2];
|
||||
|
@ -1482,7 +1476,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
op->type->cancel(C, op);
|
||||
}
|
||||
else {
|
||||
paint_stroke_cancel(C, op);
|
||||
paint_stroke_cancel(C, op, stroke);
|
||||
}
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
@ -1492,13 +1486,13 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
|
||||
paint_stroke_line_constrain(stroke, mouse);
|
||||
paint_stroke_line_end(C, op, stroke, mouse);
|
||||
stroke_done(C, op);
|
||||
stroke_done(C, op, stroke);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
}
|
||||
else if (ELEM(event->type, EVT_RETKEY, EVT_SPACEKEY)) {
|
||||
paint_stroke_line_end(C, op, stroke, sample_average.mouse);
|
||||
stroke_done(C, op);
|
||||
stroke_done(C, op, stroke);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
else if (br->flag & BRUSH_LINE) {
|
||||
|
@ -1530,7 +1524,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
if (paint_smooth_stroke(stroke, &sample_average, mode, mouse, &pressure)) {
|
||||
if (stroke->stroke_started) {
|
||||
if (paint_space_stroke_enabled(br, mode)) {
|
||||
if (paint_space_stroke(C, op, mouse, pressure)) {
|
||||
if (paint_space_stroke(C, op, stroke, mouse, pressure)) {
|
||||
redraw = true;
|
||||
}
|
||||
}
|
||||
|
@ -1538,7 +1532,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
float dmouse[2];
|
||||
sub_v2_v2v2(dmouse, mouse, stroke->last_mouse_position);
|
||||
stroke->stroke_distance += len_v2(dmouse);
|
||||
paint_brush_stroke_add_step(C, op, mouse, pressure);
|
||||
paint_brush_stroke_add_step(C, op, stroke, mouse, pressure);
|
||||
redraw = true;
|
||||
}
|
||||
}
|
||||
|
@ -1549,7 +1543,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
* instead of waiting till we have moved the space distance */
|
||||
if (first_dab && paint_space_stroke_enabled(br, mode) && !(br->flag & BRUSH_SMOOTH_STROKE)) {
|
||||
stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
|
||||
paint_brush_stroke_add_step(C, op, sample_average.mouse, sample_average.pressure);
|
||||
paint_brush_stroke_add_step(C, op, stroke, sample_average.mouse, sample_average.pressure);
|
||||
redraw = true;
|
||||
}
|
||||
|
||||
|
@ -1572,10 +1566,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
int paint_stroke_exec(bContext *C, wmOperator *op)
|
||||
int paint_stroke_exec(bContext *C, wmOperator *op, PaintStroke *stroke)
|
||||
{
|
||||
PaintStroke *stroke = op->customdata;
|
||||
|
||||
/* only when executed for the first time */
|
||||
if (stroke->stroke_started == 0) {
|
||||
PropertyRNA *strokeprop;
|
||||
|
@ -1599,14 +1591,14 @@ int paint_stroke_exec(bContext *C, wmOperator *op)
|
|||
|
||||
bool ok = (stroke->stroke_started != 0);
|
||||
|
||||
stroke_done(C, op);
|
||||
stroke_done(C, op, stroke);
|
||||
|
||||
return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void paint_stroke_cancel(bContext *C, wmOperator *op)
|
||||
void paint_stroke_cancel(bContext *C, wmOperator *op, PaintStroke *stroke)
|
||||
{
|
||||
stroke_done(C, op);
|
||||
stroke_done(C, op, stroke);
|
||||
}
|
||||
|
||||
ViewContext *paint_stroke_view_context(PaintStroke *stroke)
|
||||
|
|
|
@ -2551,7 +2551,7 @@ static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
event->type);
|
||||
|
||||
if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
|
||||
paint_stroke_free(C, op);
|
||||
paint_stroke_free(C, op, op->customdata);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
/* add modal handler */
|
||||
|
@ -2575,7 +2575,7 @@ static int wpaint_exec(bContext *C, wmOperator *op)
|
|||
0);
|
||||
|
||||
/* frees op->customdata */
|
||||
paint_stroke_exec(C, op);
|
||||
paint_stroke_exec(C, op, op->customdata);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
@ -2588,7 +2588,12 @@ static void wpaint_cancel(bContext *C, wmOperator *op)
|
|||
ob->sculpt->cache = NULL;
|
||||
}
|
||||
|
||||
paint_stroke_cancel(C, op);
|
||||
paint_stroke_cancel(C, op, op->customdata);
|
||||
}
|
||||
|
||||
static int wpaint_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
return paint_stroke_modal(C, op, event, op->customdata);
|
||||
}
|
||||
|
||||
void PAINT_OT_weight_paint(wmOperatorType *ot)
|
||||
|
@ -2600,7 +2605,7 @@ void PAINT_OT_weight_paint(wmOperatorType *ot)
|
|||
|
||||
/* api callbacks */
|
||||
ot->invoke = wpaint_invoke;
|
||||
ot->modal = paint_stroke_modal;
|
||||
ot->modal = wpaint_modal;
|
||||
ot->exec = wpaint_exec;
|
||||
ot->poll = weight_paint_poll;
|
||||
ot->cancel = wpaint_cancel;
|
||||
|
@ -3497,7 +3502,7 @@ static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
event->type);
|
||||
|
||||
if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
|
||||
paint_stroke_free(C, op);
|
||||
paint_stroke_free(C, op, op->customdata);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
|
@ -3522,7 +3527,7 @@ static int vpaint_exec(bContext *C, wmOperator *op)
|
|||
0);
|
||||
|
||||
/* frees op->customdata */
|
||||
paint_stroke_exec(C, op);
|
||||
paint_stroke_exec(C, op, op->customdata);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
@ -3535,7 +3540,12 @@ static void vpaint_cancel(bContext *C, wmOperator *op)
|
|||
ob->sculpt->cache = NULL;
|
||||
}
|
||||
|
||||
paint_stroke_cancel(C, op);
|
||||
paint_stroke_cancel(C, op, op->customdata);
|
||||
}
|
||||
|
||||
static int vpaint_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
return paint_stroke_modal(C, op, event, op->customdata);
|
||||
}
|
||||
|
||||
void PAINT_OT_vertex_paint(wmOperatorType *ot)
|
||||
|
@ -3547,7 +3557,7 @@ void PAINT_OT_vertex_paint(wmOperatorType *ot)
|
|||
|
||||
/* api callbacks */
|
||||
ot->invoke = vpaint_invoke;
|
||||
ot->modal = paint_stroke_modal;
|
||||
ot->modal = vpaint_modal;
|
||||
ot->exec = vpaint_exec;
|
||||
ot->poll = vertex_paint_poll;
|
||||
ot->cancel = vpaint_cancel;
|
||||
|
|
|
@ -5333,12 +5333,12 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
|
|||
ignore_background_click = RNA_boolean_get(op->ptr, "ignore_background_click");
|
||||
|
||||
if (ignore_background_click && !over_mesh(C, op, event->xy[0], event->xy[1])) {
|
||||
paint_stroke_free(C, op);
|
||||
paint_stroke_free(C, op, op->customdata);
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
|
||||
paint_stroke_free(C, op);
|
||||
paint_stroke_free(C, op, op->customdata);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
/* Add modal handler. */
|
||||
|
@ -5364,7 +5364,7 @@ static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op)
|
|||
0);
|
||||
|
||||
/* Frees op->customdata. */
|
||||
paint_stroke_exec(C, op);
|
||||
paint_stroke_exec(C, op, op->customdata);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
@ -5382,7 +5382,7 @@ static void sculpt_brush_stroke_cancel(bContext *C, wmOperator *op)
|
|||
paint_mesh_restore_co(sd, ob);
|
||||
}
|
||||
|
||||
paint_stroke_cancel(C, op);
|
||||
paint_stroke_cancel(C, op, op->customdata);
|
||||
|
||||
if (ss->cache) {
|
||||
SCULPT_cache_free(ss->cache);
|
||||
|
@ -5392,6 +5392,11 @@ static void sculpt_brush_stroke_cancel(bContext *C, wmOperator *op)
|
|||
sculpt_brush_exit_tex(sd);
|
||||
}
|
||||
|
||||
static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
return paint_stroke_modal(C, op, event, op->customdata);
|
||||
}
|
||||
|
||||
void SCULPT_OT_brush_stroke(wmOperatorType *ot)
|
||||
{
|
||||
/* Identifiers. */
|
||||
|
@ -5401,7 +5406,7 @@ void SCULPT_OT_brush_stroke(wmOperatorType *ot)
|
|||
|
||||
/* API callbacks. */
|
||||
ot->invoke = sculpt_brush_stroke_invoke;
|
||||
ot->modal = paint_stroke_modal;
|
||||
ot->modal = sculpt_brush_stroke_modal;
|
||||
ot->exec = sculpt_brush_stroke_exec;
|
||||
ot->poll = SCULPT_poll;
|
||||
ot->cancel = sculpt_brush_stroke_cancel;
|
||||
|
|
Loading…
Reference in New Issue