[Bf-blender-cvs] [45d6bf48ba9] temp-T97479-3d-texturing-undo: Undo support.

Jeroen Bakker noreply at git.blender.org
Tue May 3 12:57:02 CEST 2022


Commit: 45d6bf48ba916fe19c6abb9c18f967203be6cb52
Author: Jeroen Bakker
Date:   Tue May 3 12:38:22 2022 +0200
Branches: temp-T97479-3d-texturing-undo
https://developer.blender.org/rB45d6bf48ba916fe19c6abb9c18f967203be6cb52

Undo support.

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

M	source/blender/blenkernel/BKE_pbvh_pixels.hh
M	source/blender/blenkernel/intern/pbvh_pixels.cc
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/editors/sculpt_paint/sculpt_paint_image.cc
M	source/blender/editors/space_image/image_undo.c

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

diff --git a/source/blender/blenkernel/BKE_pbvh_pixels.hh b/source/blender/blenkernel/BKE_pbvh_pixels.hh
index fdfb5fa037e..e73950e6299 100644
--- a/source/blender/blenkernel/BKE_pbvh_pixels.hh
+++ b/source/blender/blenkernel/BKE_pbvh_pixels.hh
@@ -132,12 +132,22 @@ struct UDIMTilePixels {
   }
 };
 
+struct UDIMTileUndo {
+  short tile_number;
+  rcti region;
+
+  UDIMTileUndo(short tile_number, rcti &region) : tile_number(tile_number), region(region)
+  {
+  }
+};
+
 struct NodeData {
   struct {
     bool dirty : 1;
   } flags;
 
   Vector<UDIMTilePixels> tiles;
+  Vector<UDIMTileUndo> undo_regions;
   Triangles triangles;
 
   NodeData()
@@ -155,6 +165,23 @@ struct NodeData {
     return nullptr;
   }
 
+  void rebuild_undo_regions()
+  {
+    undo_regions.clear();
+    for (UDIMTilePixels &tile : tiles) {
+      rcti region;
+      BLI_rcti_init_minmax(&region);
+      for (PackedPixelRow &pixel_row : tile.pixel_rows) {
+        BLI_rcti_do_minmax_v(
+            &region, int2(pixel_row.start_image_coordinate.x, pixel_row.start_image_coordinate.y));
+        BLI_rcti_do_minmax_v(&region,
+                             int2(pixel_row.start_image_coordinate.x + pixel_row.num_pixels + 1,
+                                  pixel_row.start_image_coordinate.y + 1));
+      }
+      undo_regions.append(UDIMTileUndo(tile.tile_number, region));
+    }
+  }
+
   void mark_region(Image &image, const image::ImageTileWrapper &image_tile, ImBuf &image_buffer)
   {
     UDIMTilePixels *tile = find_tile_data(image_tile);
diff --git a/source/blender/blenkernel/intern/pbvh_pixels.cc b/source/blender/blenkernel/intern/pbvh_pixels.cc
index 5623cac44ac..3a5f7dcc24c 100644
--- a/source/blender/blenkernel/intern/pbvh_pixels.cc
+++ b/source/blender/blenkernel/intern/pbvh_pixels.cc
@@ -307,6 +307,12 @@ static void update_pixels(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image
     apply_watertight_check(pbvh, image, image_user);
   }
 
+  /* Rebuild the undo regions. */
+  for (PBVHNode *node : nodes_to_update) {
+    NodeData *node_data = static_cast<NodeData *>(node->pixels.node_data);
+    node_data->rebuild_undo_regions();
+  }
+
   /* Clear the UpdatePixels flag. */
   for (PBVHNode *node : nodes_to_update) {
     node->flag = static_cast<PBVHNodeFlags>(node->flag & ~PBVH_RebuildPixels);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 87db311324b..b62b506b285 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -3248,8 +3248,8 @@ static void do_brush_action(Sculpt *sd,
     }
     nodes = sculpt_pbvh_gather_generic(ob, sd, brush, use_original, radius_scale, &totnode);
   }
-
-  if (sculpt_needs_pbvh_pixels(paint_mode_settings, brush, ob)) {
+  const bool use_pixels = sculpt_needs_pbvh_pixels(paint_mode_settings, brush, ob);
+  if (use_pixels) {
     sculpt_pbvh_update_pixels(paint_mode_settings, ss, ob);
   }
 
@@ -3302,16 +3302,18 @@ static void do_brush_action(Sculpt *sd,
   }
   float location[3];
 
-  SculptThreadedTaskData task_data = {
-      .sd = sd,
-      .ob = ob,
-      .brush = brush,
-      .nodes = nodes,
-  };
+  if (!use_pixels) {
+    SculptThreadedTaskData task_data = {
+        .sd = sd,
+        .ob = ob,
+        .brush = brush,
+        .nodes = nodes,
+    };
 
-  TaskParallelSettings settings;
-  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
-  BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings);
+    TaskParallelSettings settings;
+    BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+    BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings);
+  }
 
   if (sculpt_brush_needs_normal(ss, brush)) {
     update_sculpt_normal(sd, ob, nodes, totnode);
@@ -5297,7 +5299,7 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f
     /* This is incorrect as this crashes other areas. We should integrate the image undo into the
      * sculpt undo. (sub system?). */
     if (SCULPT_use_image_paint_brush(&tool_settings->paint_mode, ob)) {
-      ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_3D);
+      ED_image_undo_push_begin(op->type->name, PAINT_MODE_SCULPT);
     }
     else {
       SCULPT_undo_push_begin(ob, sculpt_tool_name(sd));
diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_image.cc b/source/blender/editors/sculpt_paint/sculpt_paint_image.cc
index df1ccc0fbe9..af511e24544 100644
--- a/source/blender/editors/sculpt_paint/sculpt_paint_image.cc
+++ b/source/blender/editors/sculpt_paint/sculpt_paint_image.cc
@@ -360,6 +360,88 @@ static void do_paint_pixels(void *__restrict userdata,
   node_data.flags.dirty |= pixels_updated;
 }
 
+static void undo_region_tiles(
+    ImBuf *ibuf, int x, int y, int w, int h, int *tx, int *ty, int *tw, int *th)
+{
+  int srcx = 0, srcy = 0;
+  IMB_rectclip(ibuf, nullptr, &x, &y, &srcx, &srcy, &w, &h);
+  *tw = ((x + w - 1) >> ED_IMAGE_UNDO_TILE_BITS);
+  *th = ((y + h - 1) >> ED_IMAGE_UNDO_TILE_BITS);
+  *tx = (x >> ED_IMAGE_UNDO_TILE_BITS);
+  *ty = (y >> ED_IMAGE_UNDO_TILE_BITS);
+}
+
+static void push_undo(const NodeData &node_data,
+                      Image &image,
+                      ImageUser &image_user,
+                      const image::ImageTileWrapper &image_tile,
+                      ImBuf &image_buffer,
+                      ImBuf **tmpibuf)
+{
+  for (const UDIMTileUndo &tile_undo : node_data.undo_regions) {
+    if (tile_undo.tile_number != image_tile.get_tile_number()) {
+      continue;
+    }
+    int tilex, tiley, tilew, tileh;
+    ListBase *undo_tiles = ED_image_paint_tile_list_get();
+    undo_region_tiles(&image_buffer,
+                      tile_undo.region.xmin,
+                      tile_undo.region.ymin,
+                      BLI_rcti_size_x(&tile_undo.region),
+                      BLI_rcti_size_y(&tile_undo.region),
+                      &tilex,
+                      &tiley,
+                      &tilew,
+                      &tileh);
+    /* For performance reasons we could move this to the caller now it reallocates it per node
+     * per tile. */
+    for (int ty = tiley; ty <= tileh; ty++) {
+      for (int tx = tilex; tx <= tilew; tx++) {
+        ED_image_paint_tile_push(undo_tiles,
+                                 &image,
+                                 &image_buffer,
+                                 tmpibuf,
+                                 &image_user,
+                                 tx,
+                                 ty,
+                                 nullptr,
+                                 nullptr,
+                                 true,
+                                 true);
+      }
+    }
+  }
+}
+
+static void do_push_undo_tile(void *__restrict userdata,
+                              const int n,
+                              const TaskParallelTLS *__restrict UNUSED(tls))
+{
+  TexturePaintingUserData *data = static_cast<TexturePaintingUserData *>(userdata);
+  PBVHNode *node = data->nodes[n];
+
+  NodeData &node_data = BKE_pbvh_pixels_node_data_get(*node);
+  Image *image = data->image_data.image;
+  ImageUser *image_user = data->image_data.image_user;
+
+  ImBuf *tmpibuf = nullptr;
+  ImageUser local_image_user = *image_user;
+  LISTBASE_FOREACH (ImageTile *, tile, &image->tiles) {
+    image::ImageTileWrapper image_tile(tile);
+    local_image_user.tile = image_tile.get_tile_number();
+    ImBuf *image_buffer = BKE_image_acquire_ibuf(image, &local_image_user, nullptr);
+    if (image_buffer == nullptr) {
+      continue;
+    }
+
+    push_undo(node_data, *image, *image_user, image_tile, *image_buffer, &tmpibuf);
+    BKE_image_release_ibuf(image, image_buffer, nullptr);
+  }
+  if (tmpibuf) {
+    IMB_freeImBuf(tmpibuf);
+  }
+}
+
 static void do_mark_dirty_regions(void *__restrict userdata,
                                   const int n,
                                   const TaskParallelTLS *__restrict UNUSED(tls))
@@ -421,6 +503,7 @@ void SCULPT_do_paint_brush_image(
 
   TaskParallelSettings settings;
   BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+  BLI_task_parallel_range(0, totnode, &data, do_push_undo_tile, &settings);
   BLI_task_parallel_range(0, totnode, &data, do_paint_pixels, &settings);
 
   TaskParallelSettings settings_flush;
diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c
index c3a48abcae1..1fd9fde084b 100644
--- a/source/blender/editors/space_image/image_undo.c
+++ b/source/blender/editors/space_image/image_undo.c
@@ -1040,7 +1040,7 @@ static ImageUndoStep *image_undo_push_begin(const char *name, int paint_mode)
   bContext *C = NULL; /* special case, we never read from this. */
   UndoStep *us_p = BKE_undosys_step_push_init_with_type(ustack, C, name, BKE_UNDOSYS_TYPE_IMAGE);
   ImageUndoStep *us = (ImageUndoStep *)us_p;
-  BLI_assert(ELEM(paint_mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D));
+  BLI_assert(ELEM(paint_mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D, PAINT_MODE_SCULPT));
   us->paint_mode = paint_mode;
   return us;
 }



More information about the Bf-blender-cvs mailing list