[Bf-blender-cvs] [afb43b881cc] master: Sculpt: Face Set Extract Operator

Pablo Dobarro noreply at git.blender.org
Thu Sep 3 17:26:58 CEST 2020


Commit: afb43b881cc3d036aba9ab7a2b1ec5e91f745eaa
Author: Pablo Dobarro
Date:   Thu Sep 3 17:25:30 2020 +0200
Branches: master
https://developer.blender.org/rBafb43b881cc3d036aba9ab7a2b1ec5e91f745eaa

Sculpt: Face Set Extract Operator

This implements a Face Set Extract operator, which is similar to mask
extract. This operator uses a picker to select and Face Set in the mesh
and extract the geometry directly to a new object.

Reviewed By: sergey

Differential Revision: https://developer.blender.org/D8599

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

M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/blenkernel/BKE_screen.h
M	source/blender/blenkernel/intern/screen.c
M	source/blender/editors/include/ED_sculpt.h
M	source/blender/editors/mesh/editmesh_mask_extract.c
M	source/blender/editors/mesh/mesh_intern.h
M	source/blender/editors/mesh/mesh_ops.c
M	source/blender/editors/sculpt_paint/sculpt_face_set.c

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

diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index c49f5b3e5d1..35b27940687 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -3112,6 +3112,10 @@ class VIEW3D_MT_face_sets(Menu):
 
         layout.separator()
 
+        op = layout.operator("mesh.face_set_extract", text='Extract Face Set')
+
+        layout.separator()
+
         op = layout.operator("sculpt.face_set_change_visibility", text='Invert Visible Face Sets')
         op.mode = 'INVERT'
 
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 1090deae93f..0eeccf71cc6 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -399,6 +399,11 @@ struct ARegion *BKE_screen_find_region_xy(struct bScreen *screen,
                                           int x,
                                           int y) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
 
+struct ARegion *BKE_screen_find_main_region_at_xy(struct bScreen *screen,
+                                                  const int space_type,
+                                                  const int x,
+                                                  const int y);
+
 struct ScrArea *BKE_screen_find_area_from_space(struct bScreen *screen,
                                                 struct SpaceLink *sl) ATTR_WARN_UNUSED_RESULT
     ATTR_NONNULL(1, 2);
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index d56658a6709..998e94ff11d 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -1057,6 +1057,18 @@ void BKE_screen_view3d_shading_init(View3DShading *shading)
   memcpy(shading, shading_default, sizeof(*shading));
 }
 
+ARegion *BKE_screen_find_main_region_at_xy(bScreen *screen,
+                                           const int space_type,
+                                           const int x,
+                                           const int y)
+{
+  ScrArea *area = BKE_screen_find_area_xy(screen, space_type, x, y);
+  if (!area) {
+    return NULL;
+  }
+  return BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, x, y);
+}
+
 /* magic zoom calculation, no idea what
  * it signifies, if you find out, tell me! -zr
  */
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h
index bfc46534b99..1175d08399e 100644
--- a/source/blender/editors/include/ED_sculpt.h
+++ b/source/blender/editors/include/ED_sculpt.h
@@ -57,6 +57,10 @@ void ED_sculpt_undo_geometry_end(struct Object *ob);
 int ED_sculpt_face_sets_find_next_available_id(struct Mesh *mesh);
 void ED_sculpt_face_sets_initialize_none_to_id(struct Mesh *mesh, const int new_id);
 
+int ED_sculpt_face_sets_active_update_and_get(struct bContext *C,
+                                              struct Object *ob,
+                                              const float mval[2]);
+
 /* Undo for changes happening on a base mesh for multires sculpting.
  * if there is no multires sculpt active regular undo is used. */
 void ED_sculpt_undo_push_multires_mesh_begin(struct bContext *C, const char *str);
diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c
index 34fcee779de..17808a6e2dd 100644
--- a/source/blender/editors/mesh/editmesh_mask_extract.c
+++ b/source/blender/editors/mesh/editmesh_mask_extract.c
@@ -27,6 +27,8 @@
 
 #include "BLI_math.h"
 
+#include "BLT_translation.h"
+
 #include "BKE_context.h"
 #include "BKE_editmesh.h"
 #include "BKE_layer.h"
@@ -35,6 +37,7 @@
 #include "BKE_modifier.h"
 #include "BKE_paint.h"
 #include "BKE_report.h"
+#include "BKE_screen.h"
 #include "BKE_shrinkwrap.h"
 
 #include "DEG_depsgraph.h"
@@ -58,12 +61,17 @@
 
 #include "mesh_intern.h" /* own include */
 
-static bool paint_mask_extract_poll(bContext *C)
+typedef enum eGeometryExtractModeType {
+  GEOMETRY_EXTRACT_MASK = 0,
+  GEOMETRY_EXTRACT_FACE_SET = 1,
+} eGeometryExtractModeType;
+
+static bool geometry_extract_poll(bContext *C)
 {
   Object *ob = CTX_data_active_object(C);
   if (ob != NULL && ob->mode == OB_MODE_SCULPT) {
     if (ob->sculpt->bm) {
-      CTX_wm_operator_poll_msg_set(C, "The mask can not be extracted with dyntopo activated");
+      CTX_wm_operator_poll_msg_set(C, "The geometry can not be extracted with dyntopo activated");
       return false;
     }
     return ED_operator_object_active_editable_mesh(C);
@@ -71,14 +79,66 @@ static bool paint_mask_extract_poll(bContext *C)
   return false;
 }
 
-static int paint_mask_extract_exec(bContext *C, wmOperator *op)
+static void geometry_extract_tag_masked_faces(BMesh *bm, const float threshold)
+{
+  BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+  const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
+
+  BMFace *f;
+  BMIter iter;
+  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+    bool keep_face = true;
+    BMVert *v;
+    BMIter face_iter;
+    BM_ITER_ELEM (v, &face_iter, f, BM_VERTS_OF_FACE) {
+      const float mask = BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
+      if (mask < threshold) {
+        keep_face = false;
+        break;
+      }
+    }
+    BM_elem_flag_set(f, BM_ELEM_TAG, !keep_face);
+  }
+}
+
+static void geometry_extract_tag_face_set(BMesh *bm, const int tag_face_set_id)
+{
+  BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+  const int cd_face_sets_offset = CustomData_get_offset(&bm->pdata, CD_SCULPT_FACE_SETS);
+
+  BMFace *f;
+  BMIter iter;
+  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+    const int face_set_id = abs(BM_ELEM_CD_GET_INT(f, cd_face_sets_offset));
+    BM_elem_flag_set(f, BM_ELEM_TAG, face_set_id != tag_face_set_id);
+  }
+}
+
+typedef struct GeometryExtactParams {
+  /* For extracting Face Sets. */
+  int active_face_set;
+
+  /* For extracting Mask. */
+  float mask_threshold;
+
+  /* Common paramenters. */
+  bool add_boundary_loop;
+  int num_smooth_iterations;
+  bool apply_shrinkwrap;
+  bool add_solidify;
+} GeometryExtractParams;
+
+static int geometry_extract_apply(bContext *C,
+                                  wmOperator *op,
+                                  eGeometryExtractModeType mode,
+                                  GeometryExtractParams *params)
 {
   struct Main *bmain = CTX_data_main(C);
   Object *ob = CTX_data_active_object(C);
   View3D *v3d = CTX_wm_view3d(C);
   Scene *scene = CTX_data_scene(C);
-
   Depsgraph *depsgraph = CTX_data_depsgraph_on_load(C);
+
   ED_object_sculptmode_exit(C, depsgraph);
 
   BKE_sculpt_mask_layers_ensure(ob, NULL);
@@ -102,27 +162,20 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
   BMEditMesh *em = BKE_editmesh_create(bm, false);
   BMVert *v;
   BMEdge *ed;
-  BMFace *f;
   BMIter iter;
-  BMIter face_iter;
-
-  /* Delete all unmasked faces */
-  BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
-  const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
 
-  float mask_threshold = RNA_float_get(op->ptr, "mask_threshold");
-  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
-    bool keep_face = true;
-    BM_ITER_ELEM (v, &face_iter, f, BM_VERTS_OF_FACE) {
-      const float mask = BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
-      if (mask < mask_threshold) {
-        keep_face = false;
-        break;
-      }
+  switch (mode) {
+    case GEOMETRY_EXTRACT_MASK: {
+      geometry_extract_tag_masked_faces(bm, params->mask_threshold);
+      break;
+    }
+    case GEOMETRY_EXTRACT_FACE_SET: {
+      geometry_extract_tag_face_set(bm, params->active_face_set);
+      break;
     }
-    BM_elem_flag_set(f, BM_ELEM_TAG, !keep_face);
   }
 
+  /* Delete all tagged faces. */
   BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES);
   BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
 
@@ -130,14 +183,13 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
     mul_v3_v3(v->co, ob->scale);
   }
 
-  if (RNA_boolean_get(op->ptr, "add_boundary_loop")) {
+  if (params->add_boundary_loop) {
     BM_ITER_MESH (ed, &iter, bm, BM_EDGES_OF_MESH) {
       BM_elem_flag_set(ed, BM_ELEM_TAG, BM_edge_is_boundary(ed));
     }
     edbm_extrude_edges_indiv(em, op, BM_ELEM_TAG, false);
 
-    int smooth_iterations = RNA_int_get(op->ptr, "smooth_iterations");
-    for (int repeat = 0; repeat < smooth_iterations; repeat++) {
+    for (int repeat = 0; repeat < params->num_smooth_iterations; repeat++) {
       BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
       BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
         BM_elem_flag_set(v, BM_ELEM_TAG, !BM_vert_is_boundary(v));
@@ -215,13 +267,13 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
   Mesh *new_ob_mesh = new_ob->data;
   CustomData_free_layers(&new_ob_mesh->pdata, CD_SCULPT_FACE_SETS, new_ob_mesh->totpoly);
 
-  if (RNA_boolean_get(op->ptr, "apply_shrinkwrap")) {
+  if (params->apply_shrinkwrap) {
     BKE_shrinkwrap_mesh_nearest_surface_deform(C, new_ob, ob);
   }
 
-  if (RNA_boolean_get(op->ptr, "add_solidify")) {
+  if (params->add_solidify) {
     ED_object_modifier_add(
-        op->reports, bmain, scene, new_ob, "mask_extract_solidify", eModifierType_Solidify);
+        op->reports, bmain, scene, new_ob, "geometry_extract_solidify", eModifierType_Solidify);
     SolidifyModifierData *sfmd = (SolidifyModifierData *)BKE_modifiers_findby_name(
         new_ob, "mask_extract_solidify");
     if (sfmd) {
@@ -240,37 +292,31 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op)
   return OPERATOR_FINISHED;
 }
 
-void MESH_OT_paint_mask_extract(wmOperatorType *ot)
+static int paint_mask_extract_exec(bContext *C, wmOperator *op)
 {
-  /* identifiers */
-  ot->name = "Mask Extract";
-  ot->description = "Create a new mesh object from the current paint mask";
-  ot->idname = "MESH_OT_paint_mask_extract";
-
-  /* api callbacks */
-  ot->poll = paint_m

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list