[Bf-blender-cvs] [c5767a24b9e] master: Fix T71995: Texture Paint workspace crash with new scene

Julian Eisel noreply at git.blender.org
Tue Dec 10 16:00:51 CET 2019


Commit: c5767a24b9eeb167995c425cc76597c103caf7db
Author: Julian Eisel
Date:   Tue Dec 10 15:45:55 2019 +0100
Branches: master
https://developer.blender.org/rBc5767a24b9eeb167995c425cc76597c103caf7db

Fix T71995: Texture Paint workspace crash with new scene

Issue likely caused by 8b31f6fb2169.

With this, initializing the toolsystem (e.g. for a new workspace-scene
combination) would skip the entire create->initialize routine for
image/texture painting settings. Reason being that these are not
allocated, unlike other paint settings. So while correctly skipping the
create part, it also skipped the initialization, which was still needed.

This does further changes in related code to avoid NULL pointer
accesses.

===================================================================

M	source/blender/blenkernel/BKE_paint.h
M	source/blender/blenkernel/intern/paint.c
M	source/blender/blenkernel/intern/paint_toolslots.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 48f9e1fd95e..536268c067e 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -134,7 +134,7 @@ void BKE_paint_curve_copy_data(struct Main *bmain,
 struct PaintCurve *BKE_paint_curve_copy(struct Main *bmain, const struct PaintCurve *pc);
 void BKE_paint_curve_make_local(struct Main *bmain, struct PaintCurve *pc, const bool lib_local);
 
-bool BKE_paint_ensure(const struct ToolSettings *ts, struct Paint **r_paint);
+bool BKE_paint_ensure(struct ToolSettings *ts, struct Paint **r_paint);
 void BKE_paint_init(struct Main *bmain, struct Scene *sce, ePaintMode mode, const char col[3]);
 void BKE_paint_free(struct Paint *p);
 void BKE_paint_copy(struct Paint *src, struct Paint *tar, const int flag);
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index e7c20ca4fb2..584f1ab1b0c 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -152,6 +152,9 @@ bool BKE_paint_ensure_from_paintmode(Scene *sce, ePaintMode mode)
 {
   ToolSettings *ts = sce->toolsettings;
   Paint **paint_ptr = NULL;
+  /* Some paint modes don't store paint settings as pointer, for these this can be set and
+   * referenced by paint_ptr. */
+  Paint *paint_tmp = NULL;
 
   switch (mode) {
     case PAINT_MODE_SCULPT:
@@ -165,6 +168,8 @@ bool BKE_paint_ensure_from_paintmode(Scene *sce, ePaintMode mode)
       break;
     case PAINT_MODE_TEXTURE_2D:
     case PAINT_MODE_TEXTURE_3D:
+      paint_tmp = (Paint *)&ts->imapaint;
+      paint_ptr = &paint_tmp;
       break;
     case PAINT_MODE_SCULPT_UV:
       paint_ptr = (Paint **)&ts->uvsculpt;
@@ -175,7 +180,7 @@ bool BKE_paint_ensure_from_paintmode(Scene *sce, ePaintMode mode)
     case PAINT_MODE_INVALID:
       break;
   }
-  if (paint_ptr && (*paint_ptr == NULL)) {
+  if (paint_ptr) {
     BKE_paint_ensure(ts, paint_ptr);
     return true;
   }
@@ -693,26 +698,36 @@ eObjectMode BKE_paint_object_mode_from_paintmode(ePaintMode mode)
 /**
  * Call when entering each respective paint mode.
  */
-bool BKE_paint_ensure(const ToolSettings *ts, struct Paint **r_paint)
+bool BKE_paint_ensure(ToolSettings *ts, struct Paint **r_paint)
 {
   Paint *paint = NULL;
   if (*r_paint) {
-    /* Note: 'ts->imapaint' is ignored, it's not allocated. */
-    BLI_assert(ELEM(*r_paint,
-                    &ts->gp_paint->paint,
-                    &ts->sculpt->paint,
-                    &ts->vpaint->paint,
-                    &ts->wpaint->paint,
-                    &ts->uvsculpt->paint));
+    /* Tool offset should never be 0 for initialized paint settings, so it's a reliable way to
+     * check if already initialized. */
+    if ((*r_paint)->runtime.tool_offset == 0) {
+      /* Currently only image painting is initialized this way, others have to be allocated. */
+      BLI_assert(ELEM(*r_paint, (Paint *)&ts->imapaint));
 
+      BKE_paint_runtime_init(ts, *r_paint);
+    }
+    else {
+      BLI_assert(ELEM(*r_paint,
+                      /* Cast is annoying, but prevent NULL-pointer access. */
+                      (Paint *)ts->gp_paint,
+                      (Paint *)ts->sculpt,
+                      (Paint *)ts->vpaint,
+                      (Paint *)ts->wpaint,
+                      (Paint *)ts->uvsculpt,
+                      (Paint *)&ts->imapaint));
 #ifdef DEBUG
-    struct Paint paint_test = **r_paint;
-    BKE_paint_runtime_init(ts, *r_paint);
-    /* Swap so debug doesn't hide errors when release fails. */
-    SWAP(Paint, **r_paint, paint_test);
-    BLI_assert(paint_test.runtime.ob_mode == (*r_paint)->runtime.ob_mode);
-    BLI_assert(paint_test.runtime.tool_offset == (*r_paint)->runtime.tool_offset);
+      struct Paint paint_test = **r_paint;
+      BKE_paint_runtime_init(ts, *r_paint);
+      /* Swap so debug doesn't hide errors when release fails. */
+      SWAP(Paint, **r_paint, paint_test);
+      BLI_assert(paint_test.runtime.ob_mode == (*r_paint)->runtime.ob_mode);
+      BLI_assert(paint_test.runtime.tool_offset == (*r_paint)->runtime.tool_offset);
 #endif
+    }
     return true;
   }
 
@@ -738,6 +753,9 @@ bool BKE_paint_ensure(const ToolSettings *ts, struct Paint **r_paint)
     UvSculpt *data = MEM_callocN(sizeof(*data), __func__);
     paint = &data->paint;
   }
+  else if (*r_paint == &ts->imapaint.paint) {
+    paint = &ts->imapaint.paint;
+  }
 
   paint->flags |= PAINT_SHOW_BRUSH;
 
diff --git a/source/blender/blenkernel/intern/paint_toolslots.c b/source/blender/blenkernel/intern/paint_toolslots.c
index a252329b635..1d10db06139 100644
--- a/source/blender/blenkernel/intern/paint_toolslots.c
+++ b/source/blender/blenkernel/intern/paint_toolslots.c
@@ -94,7 +94,9 @@ void BKE_paint_toolslots_brush_update_ex(Paint *paint, Brush *brush)
   BKE_paint_toolslots_len_ensure(paint, slot_index + 1);
   PaintToolSlot *tslot = &paint->tool_slots[slot_index];
   id_us_plus(&brush->id);
-  id_us_min(&tslot->brush->id);
+  if (tslot->brush) {
+    id_us_min(&tslot->brush->id);
+  }
   tslot->brush = brush;
 }



More information about the Bf-blender-cvs mailing list