Fix: Background paint strokes may not initialize certain settings

When a paint stroke is executed instead of processed via the modal
handler, prior to this commit, the `paint_brush_update` function was
not called. This method handles initialization of some temporary stroke
data inside `UnifiedPaintSettings`, which is used by dyntopo when
performing edge collapse.

This had the result of causing a divide by 0 with certain uninitalized
settings when using a brush with dyntopo enabled and calling the
operator from the python API (e.g. from unit testing), resulting in
nonsensical deformations.

There are a number of weak points with the current design:
* This issue was only exposed because of the refactor to the
  `UnifiedPaintSettings`, indicating that despite these values being
  runtime-only, they were still persisted in some cases in .blend files
* The data stored as individual stroke steps is not sufficient to
  reconstruct a paint stroke given a list of screen-space locations, and
  this data is populated outside of the common `stroke` callbacks.

Both of the above issues are wider reaching than this PR is intended to
fix.

This commit ensures that `paint_brush_update` is called in the `exec`
codepath and updates the related test image.

Pull Request: https://projects.blender.org/blender/blender/pulls/141314
This commit is contained in:
Sean Kim
2025-07-03 23:00:28 +02:00
committed by Sean Kim
parent 2e049ba4a7
commit 6fb90e5303
2 changed files with 23 additions and 5 deletions

View File

@@ -1690,15 +1690,33 @@ wmOperatorStatus paint_stroke_exec(bContext *C, wmOperator *op, PaintStroke *str
}
}
const PaintMode mode = BKE_paintmode_get_active_from_context(C);
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") {
if (override_location) {
float2 mval;
RNA_float_get_array(&itemptr, "mouse_event", mval);
float2 mval;
RNA_float_get_array(&itemptr, "mouse_event", mval);
const float pressure = RNA_float_get(&itemptr, "pressure");
float2 dummy_mouse;
RNA_float_get_array(&itemptr, "mouse", dummy_mouse);
float3 dummy_location;
bool dummy_is_set;
paint_brush_update(C,
*stroke->brush,
mode,
stroke,
mval,
dummy_mouse,
pressure,
dummy_location,
&dummy_is_set);
if (override_location) {
float3 location;
if (stroke->get_location(C, location, mval, false)) {
RNA_float_set_array(&itemptr, "location", location);

Binary file not shown.