From 6fb90e5303c0509c098afd55e4e4eccf1ca6409b Mon Sep 17 00:00:00 2001 From: Sean Kim Date: Thu, 3 Jul 2025 23:00:28 +0200 Subject: [PATCH] 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 --- .../editors/sculpt_paint/paint_stroke.cc | 24 ++++++++++++++++--- .../brushes/reference/dyntopo_draw.png | 4 ++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_stroke.cc b/source/blender/editors/sculpt_paint/paint_stroke.cc index 5312d5f53a6..c5002ae86b4 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.cc +++ b/source/blender/editors/sculpt_paint/paint_stroke.cc @@ -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); diff --git a/tests/files/sculpting/brushes/reference/dyntopo_draw.png b/tests/files/sculpting/brushes/reference/dyntopo_draw.png index 84f8a5b1ea5..2cd6761ff80 100644 --- a/tests/files/sculpting/brushes/reference/dyntopo_draw.png +++ b/tests/files/sculpting/brushes/reference/dyntopo_draw.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3a08374e4cf501316fa9af085c1fce1b83b1ce477b69cc76e190d776a22518e5 -size 54195 +oid sha256:7e73250c2d99be05dc51e6e839d4f423e57b03cf36c7048a7312da31a958e825 +size 56169