[Bf-blender-cvs] [df9a5825e16] sculpt-dev: Initial commit for new generic sculpt expand operator

Pablo Dobarro noreply at git.blender.org
Wed Jan 13 23:00:31 CET 2021


Commit: df9a5825e16df9f3a6e375e592d6c8d3a2f677ee
Author: Pablo Dobarro
Date:   Wed Jan 13 22:59:59 2021 +0100
Branches: sculpt-dev
https://developer.blender.org/rBdf9a5825e16df9f3a6e375e592d6c8d3a2f677ee

Initial commit for new generic sculpt expand operator

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

M	source/blender/blenkernel/BKE_paint.h
M	source/blender/editors/sculpt_paint/CMakeLists.txt
A	source/blender/editors/sculpt_paint/sculpt_expand.c
M	source/blender/editors/sculpt_paint/sculpt_intern.h

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

diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index bf478e44f97..ecabda9e207 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -515,6 +515,7 @@ typedef struct SculptSession {
 
   struct StrokeCache *cache;
   struct FilterCache *filter_cache;
+  struct ExpandCache *expand_cache;
 
   /* Cursor data and active vertex for tools */
   int active_vertex_index;
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index e6b0b6431fc..025fa6b0697 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -61,6 +61,7 @@ set(SRC
   sculpt_cloth.c
   sculpt_detail.c
   sculpt_dyntopo.c
+  sculpt_expand.c
   sculpt_face_set.c
   sculpt_filter_color.c
   sculpt_filter_mask.c
diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.c b/source/blender/editors/sculpt_paint/sculpt_expand.c
new file mode 100644
index 00000000000..2c53e320522
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_expand.c
@@ -0,0 +1,689 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_brush_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_ccg.h"
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_mesh.h"
+#include "BKE_multires.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_pbvh.h"
+#include "BKE_scene.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_api.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_sculpt.h"
+#include "ED_view3d.h"
+#include "paint_intern.h"
+#include "sculpt_intern.h"
+
+#include "bmesh.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+
+static EnumPropertyItem prop_sculpt_expand_faloff_type_items[] = {
+    {SCULPT_EXPAND_FALLOFF_GEODESICS, "GEODESICS", 0, "Surface", ""},
+    {SCULPT_EXPAND_FALLOFF_TOPOLOGY, "TOPOLOGY", 0, "Topology", ""},
+    {SCULPT_EXPAND_FALLOFF_NORMALS, "NORMALS", 0, "Normals", ""},
+    {SCULPT_EXPAND_FALLOFF_SPHERICAL, "SPHERICAL", 0, "Spherical", ""},
+    {0, NULL, 0, NULL, NULL},
+};
+
+
+
+static float *sculpt_expand_geodesic_falloff_create(Sculpt *sd, Object *ob, const int vertex) {
+    return SCULPT_geodesic_from_vertex_and_symm(sd, ob, vertex, FLT_MAX);
+}
+
+static float *sculpt_expand_topology_falloff_create() {
+    return NULL;
+}
+
+static float *sculpt_expand_spherical_falloff_create() {
+    return NULL;
+}
+
+static float *sculpt_expand_normal_falloff_create() {
+    return NULL;
+}
+
+static void sculpt_expand_update_max_falloff_factor(SculptSession *ss, ExpandCache *expand_cache) {
+    const int totvert = SCULPT_vertex_count_get(ss);
+    expand_cache->max_falloff_factor = -FLT_MAX;
+    for (int i = 0; i < totvert; i++) {
+        expand_cache->max_falloff_factor = max_ff(expand_cache->max_falloff_factor, expand_cache->falloff_factor[i]);
+    }
+}
+
+
+static void sculpt_expand_falloff_factors_from_vertex_and_symm_create(ExpandCache *expand_cache, Sculpt *sd, Object *ob, const int vertex, eSculptExpandFalloffType falloff_type) {
+    if (expand_cache->falloff_factor && expand_cache->falloff_factor_type == falloff_type) {
+        /* Falloffs are already initialize with the current falloff type, nothing to do. */
+        return;
+    }
+
+
+    switch (falloff_type) {
+    case SCULPT_EXPAND_FALLOFF_GEODESICS:
+        expand_cache->falloff_factor = sculpt_expand_geodesic_falloff_create(sd, ob, vertex);
+        break;
+    case SCULPT_EXPAND_FALLOFF_TOPOLOGY:
+
+        break;
+    case SCULPT_EXPAND_FALLOFF_NORMALS:
+
+        break;
+    case SCULPT_EXPAND_FALLOFF_SPHERICAL:
+
+        break;
+    case SCULPT_EXPAND_FALLOFF_BOUNDARY_TOPOLOGY:
+
+        break;
+    }
+
+    expand_cache->falloff_factor_type = falloff_type;
+
+    SculptSession *ss = ob->sculpt;
+    sculpt_expand_update_max_falloff_factor(ss, expand_cache);
+}
+
+
+float *sculpt_expand_falloff_factors_update() {
+    return NULL;
+}
+
+
+void sculpt_expand_cache_free(ExpandCache *expand_cache) {
+
+
+    MEM_SAFE_FREE(expand_cache);
+}
+
+
+
+static void sculpt_mask_expand_cancel(bContext *C, wmOperator *op)
+{
+  Object *ob = CTX_data_active_object(C);
+  SculptSession *ss = ob->sculpt;
+  const bool create_face_set = RNA_boolean_get(op->ptr, "create_face_set");
+
+  MEM_freeN(op->customdata);
+
+  for (int n = 0; n < ss->filter_cache->totnode; n++) {
+    PBVHNode *node = ss->filter_cache->nodes[n];
+    if (create_face_set) {
+      for (int i = 0; i < ss->totfaces; i++) {
+        ss->face_sets[i] = ss->filter_cache->prev_face_set[i];
+      }
+    }
+    else {
+      PBVHVertexIter vd;
+      BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+      {
+        *vd.mask = ss->filter_cache->prev_mask[vd.index];
+      }
+      BKE_pbvh_vertex_iter_end;
+    }
+
+    BKE_pbvh_node_mark_redraw(node);
+  }
+
+  if (!create_face_set) {
+    SCULPT_flush_update_step(C, SCULPT_UPDATE_MASK);
+  }
+  SCULPT_filter_cache_free(ss);
+  SCULPT_undo_push_end();
+  SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
+  ED_workspace_status_text(C, NULL);
+}
+
+
+static void sculpt_expand_cancel(bContext *C, wmOperator *op) {
+
+  ED_workspace_status_text(C, NULL);
+}
+
+
+static void sculpt_expand_task_cb(void *__restrict userdata,
+                                  const int i,
+                                  const TaskParallelTLS *__restrict UNUSED(tls))
+{
+  SculptThreadedTaskData *data = userdata;
+  SculptSession *ss = data->ob->sculpt;
+  PBVHNode *node = data->nodes[i];
+  PBVHVertexIter vd;
+  int update_it = data->mask_expand_update_it;
+
+  BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL)
+  {
+    int vi = vd.index;
+    float final_mask = *vd.mask;
+    if (data->mask_expand_use_normals) {
+      if (ss->filter_cache->normal_factor[SCULPT_active_vertex_get(ss)] <
+          ss->filter_cache->normal_factor[vd.index]) {
+        final_mask = 1.0f;
+      }
+      else {
+        final_mask = 0.0f;
+      }
+    }
+    else {
+      if (ss->filter_cache->mask_update_it[vi] <= update_it &&
+          ss->filter_cache->mask_update_it[vi] != 0) {
+        final_mask = 1.0f;
+      }
+      else {
+        final_mask = 0.0f;
+      }
+    }
+
+    if (data->mask_expand_create_face_set) {
+      if (final_mask == 1.0f) {
+        SCULPT_vertex_face_set_set(ss, vd.index, ss->filter_cache->new_face_set);
+      }
+      BKE_pbvh_node_mark_redraw(node);
+    }
+    else {
+
+      if (data->mask_expand_keep_prev_mask) {
+        final_mask = MAX2(ss->filter_cache->prev_mask[vd.index], final_mask);
+      }
+
+      if (data->mask_expand_invert_mask) {
+        final_mask = 1.0f - final_mask;
+      }
+
+      if (*vd.mask != final_mask) {
+        if (vd.mvert) {
+          vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+        }
+        *vd.mask = final_mask;
+        BKE_pbvh_node_mark_update_mask(node);
+      }
+    }
+  }
+  BKE_pbvh_vertex_iter_end;
+}
+
+static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+  Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+  Object *ob = CTX_data_active_object(C);
+  SculptSession *ss = ob->sculpt;
+  Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+  ARegion *region = CTX_wm_region(C);
+  float prevclick_f[2];
+  copy_v2_v2(prevclick_f, op->customdata);
+  const int prevclick[2] = {(int)prevclick_f[0], (int)prevclick_f[1]};
+  int len = (int)len_v2v2_int(prevclick, event->mval);
+  len = abs(len);
+  int mask_speed = RNA_int_get(op->ptr, "mask_speed");
+  int mask_expand_update_it = len / mask_speed;
+  mask_expand_update_it = mask_expand_update_it + 1;
+
+  const bool create_face_set = RNA_boolean_get(op->ptr, "create_face_set");
+
+  if (RNA_boolean_get(op->ptr, "use_cursor")) {
+    SculptCursorGeometryInfo sgi;
+    float mouse[2];
+    mouse[0] = event->mval[0];
+    mouse[1] = event->mval[1];
+    if (SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false)) {
+      /* The cursor is over the mesh, get the update iteration from the updated active vertex. */
+      mask_expand_update_it = ss->filter_cache->mask_update_it[(int)SCULPT_active_vertex_get(ss)];
+    }
+    else {
+      /* When the cursor is outside the mesh, affect the entire connected component. */
+      mask_expand_update_it = ss->filter_cache->mask_update_last_it - 1;
+    }
+  }
+
+  if ((event->type == EVT_ESCKEY && event->val == KM_PRESS) ||
+      (event->type == RIGHTMOUSE && event->val == KM_PRESS)) {
+    /* Returning OPERATOR_CANCELLED will leak memory due to not finishing
+     * undo. Better solution could be to make paint_mesh_restore_co work
+     * for this case. */
+    sculpt_mask_expand_cancel(C, op);
+    return OPERATOR_FINISHED;
+  }
+
+  if ((event->type == LEFTMOUSE && event->val == KM_RELEASE) ||
+      (event->type == EVT_RETKEY && event->val == KM_PRESS) ||
+      (event->type == EVT_PADENTER && event->val == KM_PRESS)) {
+
+    /* Smooth iterations. */
+ 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list