Paint: Allow executing 3D paint operators without location

In Sculpt, Vertex Paint, and Weight Paint, the operator used while
painting (`SCULPT_OT_brush_stroke`, `PAINT_OT_vertex_paint`, and
`PAINT_OT_weight_paint`) can currently be executed in python as they
define `exec` methods. However, each of them has a implicit dependency
on the `OperatorStrokeElement` struct containing a `location`
corresponding to the object space location of the stroke daub.

This limits the usefulness of the operator in non-interactive
situations, as determining the actual location of a stroke on a 3D
object requires access to the Paint BVH to perform a raycast and project
the mouse from 2D region space into object space.

To allow users to define a stroke in region space coordinates, this
commit adds a new parameter to the associated operators,
`reproject_stroke` which indicates whether or not the current `location`
data should be discarded and replaced with newly calculated positions.

Ref: #132960

Pull Request: https://projects.blender.org/blender/blender/pulls/132974
This commit is contained in:
Sean Kim 2025-01-18 02:17:47 +01:00 committed by Sean Kim
parent 0a72db9f94
commit baffd174c8
4 changed files with 43 additions and 1 deletions

View file

@ -1672,9 +1672,24 @@ int paint_stroke_exec(bContext *C, wmOperator *op, PaintStroke *stroke)
}
}
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "override_location");
const bool override_location = prop && RNA_property_boolean_get(op->ptr, prop) &&
stroke->get_location;
if (stroke->stroke_started) {
RNA_BEGIN (op->ptr, itemptr, "stroke") {
stroke->update_step(C, op, stroke, &itemptr);
if (override_location) {
float2 mval;
RNA_float_get_array(&itemptr, "mouse_event", mval);
float3 location;
if (stroke->get_location(C, location, mval, false)) {
RNA_float_set_array(&itemptr, "location", location);
stroke->update_step(C, op, stroke, &itemptr);
}
}
else {
stroke->update_step(C, op, stroke, &itemptr);
}
}
RNA_END;
}

View file

@ -2108,6 +2108,14 @@ void PAINT_OT_vertex_paint(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
paint_stroke_operator_properties(ot);
PropertyRNA *prop = RNA_def_boolean(
ot->srna,
"override_location",
false,
"Override Location",
"Override the given `location` array by recalculating object space positions from the "
"provided `mouse_event` positions");
RNA_def_property_flag(prop, PropertyFlag(PROP_HIDDEN | PROP_SKIP_SAVE));
}
/** \} */

View file

@ -67,6 +67,8 @@
#include "BKE_ccg.hh"
#include "bmesh.hh"
#include "RNA_define.hh"
#include "mesh_brush_common.hh"
#include "paint_intern.hh" /* own include */
#include "sculpt_automask.hh"
@ -1991,6 +1993,14 @@ void PAINT_OT_weight_paint(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
paint_stroke_operator_properties(ot);
PropertyRNA *prop = RNA_def_boolean(
ot->srna,
"override_location",
false,
"Override Location",
"Override the given `location` array by recalculating object space positions from the "
"provided `mouse_event` positions");
RNA_def_property_flag(prop, PropertyFlag(PROP_HIDDEN | PROP_SKIP_SAVE));
}
/** \} */

View file

@ -5542,6 +5542,15 @@ void SCULPT_OT_brush_stroke(wmOperatorType *ot)
paint_stroke_operator_properties(ot);
PropertyRNA *prop = RNA_def_boolean(
ot->srna,
"override_location",
false,
"Override Location",
"Override the given `location` array by recalculating object space positions from the "
"provided `mouse_event` positions");
RNA_def_property_flag(prop, PropertyFlag(PROP_HIDDEN | PROP_SKIP_SAVE));
RNA_def_boolean(ot->srna,
"ignore_background_click",
false,