1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2020 Blender Foundation.
17  * All rights reserved.
18  */
19 
20 /** \file
21  * \ingroup edsculpt
22  */
23 
24 #include "MEM_guardedalloc.h"
25 
26 #include "BLI_blenlib.h"
27 #include "BLI_hash.h"
28 #include "BLI_math.h"
29 #include "BLI_task.h"
30 
31 #include "DNA_brush_types.h"
32 #include "DNA_customdata_types.h"
33 #include "DNA_mesh_types.h"
34 #include "DNA_meshdata_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_scene_types.h"
37 
38 #include "BKE_brush.h"
39 #include "BKE_ccg.h"
40 #include "BKE_colortools.h"
41 #include "BKE_context.h"
42 #include "BKE_customdata.h"
43 #include "BKE_mesh.h"
44 #include "BKE_mesh_mapping.h"
45 #include "BKE_multires.h"
46 #include "BKE_node.h"
47 #include "BKE_object.h"
48 #include "BKE_paint.h"
49 #include "BKE_pbvh.h"
50 #include "BKE_scene.h"
51 
52 #include "DEG_depsgraph.h"
53 
54 #include "WM_api.h"
55 #include "WM_message.h"
56 #include "WM_toolsystem.h"
57 #include "WM_types.h"
58 
59 #include "ED_object.h"
60 #include "ED_screen.h"
61 #include "ED_sculpt.h"
62 #include "ED_view3d.h"
63 #include "paint_intern.h"
64 #include "sculpt_intern.h"
65 
66 #include "RNA_access.h"
67 #include "RNA_define.h"
68 
69 #include "bmesh.h"
70 
71 #include <math.h>
72 #include <stdlib.h>
73 
74 /* Utils. */
ED_sculpt_face_sets_find_next_available_id(struct Mesh * mesh)75 int ED_sculpt_face_sets_find_next_available_id(struct Mesh *mesh)
76 {
77   int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
78   if (!face_sets) {
79     return SCULPT_FACE_SET_NONE;
80   }
81 
82   int next_face_set_id = 0;
83   for (int i = 0; i < mesh->totpoly; i++) {
84     next_face_set_id = max_ii(next_face_set_id, abs(face_sets[i]));
85   }
86   next_face_set_id++;
87 
88   return next_face_set_id;
89 }
90 
ED_sculpt_face_sets_initialize_none_to_id(struct Mesh * mesh,const int new_id)91 void ED_sculpt_face_sets_initialize_none_to_id(struct Mesh *mesh, const int new_id)
92 {
93   int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
94   if (!face_sets) {
95     return;
96   }
97 
98   for (int i = 0; i < mesh->totpoly; i++) {
99     if (face_sets[i] == SCULPT_FACE_SET_NONE) {
100       face_sets[i] = new_id;
101     }
102   }
103 }
104 
ED_sculpt_face_sets_active_update_and_get(bContext * C,Object * ob,const float mval[2])105 int ED_sculpt_face_sets_active_update_and_get(bContext *C, Object *ob, const float mval[2])
106 {
107   SculptSession *ss = ob->sculpt;
108   if (!ss) {
109     return SCULPT_FACE_SET_NONE;
110   }
111 
112   SculptCursorGeometryInfo gi;
113   if (!SCULPT_cursor_geometry_info_update(C, &gi, mval, false)) {
114     return SCULPT_FACE_SET_NONE;
115   }
116 
117   return SCULPT_active_face_set_get(ss);
118 }
119 
120 /* Draw Face Sets Brush. */
121 
do_draw_face_sets_brush_task_cb_ex(void * __restrict userdata,const int n,const TaskParallelTLS * __restrict tls)122 static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
123                                                const int n,
124                                                const TaskParallelTLS *__restrict tls)
125 {
126   SculptThreadedTaskData *data = userdata;
127   SculptSession *ss = data->ob->sculpt;
128   const Brush *brush = data->brush;
129   const float bstrength = ss->cache->bstrength;
130 
131   PBVHVertexIter vd;
132 
133   SculptBrushTest test;
134   SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
135       ss, &test, data->brush->falloff_shape);
136   const int thread_id = BLI_task_parallel_thread_id(tls);
137 
138   MVert *mvert = SCULPT_mesh_deformed_mverts_get(ss);
139 
140   BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
141   {
142     if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
143       MeshElemMap *vert_map = &ss->pmap[vd.index];
144       for (int j = 0; j < ss->pmap[vd.index].count; j++) {
145         const MPoly *p = &ss->mpoly[vert_map->indices[j]];
146 
147         float poly_center[3];
148         BKE_mesh_calc_poly_center(p, &ss->mloop[p->loopstart], mvert, poly_center);
149 
150         if (sculpt_brush_test_sq_fn(&test, poly_center)) {
151           const float fade = bstrength * SCULPT_brush_strength_factor(ss,
152                                                                       brush,
153                                                                       vd.co,
154                                                                       sqrtf(test.dist),
155                                                                       vd.no,
156                                                                       vd.fno,
157                                                                       vd.mask ? *vd.mask : 0.0f,
158                                                                       vd.index,
159                                                                       thread_id);
160 
161           if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) {
162             ss->face_sets[vert_map->indices[j]] = abs(ss->cache->paint_face_set);
163           }
164         }
165       }
166     }
167 
168     else if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
169       {
170         if (sculpt_brush_test_sq_fn(&test, vd.co)) {
171           const float fade = bstrength * SCULPT_brush_strength_factor(ss,
172                                                                       brush,
173                                                                       vd.co,
174                                                                       sqrtf(test.dist),
175                                                                       vd.no,
176                                                                       vd.fno,
177                                                                       vd.mask ? *vd.mask : 0.0f,
178                                                                       vd.index,
179                                                                       thread_id);
180 
181           if (fade > 0.05f) {
182             SCULPT_vertex_face_set_set(ss, vd.index, ss->cache->paint_face_set);
183           }
184         }
185       }
186     }
187   }
188   BKE_pbvh_vertex_iter_end;
189 }
190 
do_relax_face_sets_brush_task_cb_ex(void * __restrict userdata,const int n,const TaskParallelTLS * __restrict tls)191 static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata,
192                                                 const int n,
193                                                 const TaskParallelTLS *__restrict tls)
194 {
195   SculptThreadedTaskData *data = userdata;
196   SculptSession *ss = data->ob->sculpt;
197   const Brush *brush = data->brush;
198   float bstrength = ss->cache->bstrength;
199 
200   PBVHVertexIter vd;
201 
202   SculptBrushTest test;
203   SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
204       ss, &test, data->brush->falloff_shape);
205 
206   const bool relax_face_sets = !(ss->cache->iteration_count % 3 == 0);
207   /* This operations needs a stregth tweak as the relax deformation is too weak by default. */
208   if (relax_face_sets) {
209     bstrength *= 2.0f;
210   }
211 
212   const int thread_id = BLI_task_parallel_thread_id(tls);
213 
214   BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
215   {
216     if (sculpt_brush_test_sq_fn(&test, vd.co)) {
217       if (relax_face_sets != SCULPT_vertex_has_unique_face_set(ss, vd.index)) {
218         const float fade = bstrength * SCULPT_brush_strength_factor(ss,
219                                                                     brush,
220                                                                     vd.co,
221                                                                     sqrtf(test.dist),
222                                                                     vd.no,
223                                                                     vd.fno,
224                                                                     vd.mask ? *vd.mask : 0.0f,
225                                                                     vd.index,
226                                                                     thread_id);
227 
228         SCULPT_relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co);
229         if (vd.mvert) {
230           vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
231         }
232       }
233     }
234   }
235   BKE_pbvh_vertex_iter_end;
236 }
237 
SCULPT_do_draw_face_sets_brush(Sculpt * sd,Object * ob,PBVHNode ** nodes,int totnode)238 void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
239 {
240   SculptSession *ss = ob->sculpt;
241   Brush *brush = BKE_paint_brush(&sd->paint);
242 
243   BKE_curvemapping_init(brush->curve);
244 
245   /* Threaded loop over nodes. */
246   SculptThreadedTaskData data = {
247       .sd = sd,
248       .ob = ob,
249       .brush = brush,
250       .nodes = nodes,
251   };
252 
253   TaskParallelSettings settings;
254   BKE_pbvh_parallel_range_settings(&settings, true, totnode);
255   if (ss->cache->alt_smooth) {
256     SCULPT_boundary_info_ensure(ob);
257     for (int i = 0; i < 4; i++) {
258       BLI_task_parallel_range(0, totnode, &data, do_relax_face_sets_brush_task_cb_ex, &settings);
259     }
260   }
261   else {
262     BLI_task_parallel_range(0, totnode, &data, do_draw_face_sets_brush_task_cb_ex, &settings);
263   }
264 }
265 
266 /* Face Sets Operators */
267 
268 typedef enum eSculptFaceGroupsCreateModes {
269   SCULPT_FACE_SET_MASKED = 0,
270   SCULPT_FACE_SET_VISIBLE = 1,
271   SCULPT_FACE_SET_ALL = 2,
272   SCULPT_FACE_SET_SELECTION = 3,
273 } eSculptFaceGroupsCreateModes;
274 
275 static EnumPropertyItem prop_sculpt_face_set_create_types[] = {
276     {
277         SCULPT_FACE_SET_MASKED,
278         "MASKED",
279         0,
280         "Face Set from Masked",
281         "Create a new Face Set from the masked faces",
282     },
283     {
284         SCULPT_FACE_SET_VISIBLE,
285         "VISIBLE",
286         0,
287         "Face Set from Visible",
288         "Create a new Face Set from the visible vertices",
289     },
290     {
291         SCULPT_FACE_SET_ALL,
292         "ALL",
293         0,
294         "Face Set Full Mesh",
295         "Create an unique Face Set with all faces in the sculpt",
296     },
297     {
298         SCULPT_FACE_SET_SELECTION,
299         "SELECTION",
300         0,
301         "Face Set from Edit Mode Selection",
302         "Create an Face Set corresponding to the Edit Mode face selection",
303     },
304     {0, NULL, 0, NULL, NULL},
305 };
306 
sculpt_face_set_create_exec(bContext * C,wmOperator * op)307 static int sculpt_face_set_create_exec(bContext *C, wmOperator *op)
308 {
309   Object *ob = CTX_data_active_object(C);
310   SculptSession *ss = ob->sculpt;
311   Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
312 
313   const int mode = RNA_enum_get(op->ptr, "mode");
314 
315   /* Dyntopo not suported. */
316   if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
317     return OPERATOR_CANCELLED;
318   }
319 
320   BKE_sculpt_update_object_for_edit(depsgraph, ob, true, mode == SCULPT_FACE_SET_MASKED, false);
321 
322   const int tot_vert = SCULPT_vertex_count_get(ss);
323   float threshold = 0.5f;
324 
325   PBVH *pbvh = ob->sculpt->pbvh;
326   PBVHNode **nodes;
327   int totnode;
328   BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
329 
330   if (!nodes) {
331     return OPERATOR_CANCELLED;
332   }
333 
334   SCULPT_undo_push_begin("face set change");
335   SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS);
336 
337   const int next_face_set = SCULPT_face_set_next_available_get(ss);
338 
339   if (mode == SCULPT_FACE_SET_MASKED) {
340     for (int i = 0; i < tot_vert; i++) {
341       if (SCULPT_vertex_mask_get(ss, i) >= threshold && SCULPT_vertex_visible_get(ss, i)) {
342         SCULPT_vertex_face_set_set(ss, i, next_face_set);
343       }
344     }
345   }
346 
347   if (mode == SCULPT_FACE_SET_VISIBLE) {
348 
349     /* If all vertices in the sculpt are visible, create the new face set and update the default
350      * color. This way the new face set will be white, which is a quick way of disabling all face
351      * sets and the performance hit of rendering the overlay. */
352     bool all_visible = true;
353     for (int i = 0; i < tot_vert; i++) {
354       if (!SCULPT_vertex_visible_get(ss, i)) {
355         all_visible = false;
356         break;
357       }
358     }
359 
360     if (all_visible) {
361       Mesh *mesh = ob->data;
362       mesh->face_sets_color_default = next_face_set;
363       BKE_pbvh_face_sets_color_set(
364           ss->pbvh, mesh->face_sets_color_seed, mesh->face_sets_color_default);
365     }
366 
367     for (int i = 0; i < tot_vert; i++) {
368       if (SCULPT_vertex_visible_get(ss, i)) {
369         SCULPT_vertex_face_set_set(ss, i, next_face_set);
370       }
371     }
372   }
373 
374   if (mode == SCULPT_FACE_SET_ALL) {
375     for (int i = 0; i < tot_vert; i++) {
376       SCULPT_vertex_face_set_set(ss, i, next_face_set);
377     }
378   }
379 
380   if (mode == SCULPT_FACE_SET_SELECTION) {
381     Mesh *mesh = ob->data;
382     BMesh *bm;
383     const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
384     bm = BM_mesh_create(&allocsize,
385                         &((struct BMeshCreateParams){
386                             .use_toolflags = true,
387                         }));
388 
389     BM_mesh_bm_from_me(bm,
390                        mesh,
391                        (&(struct BMeshFromMeshParams){
392                            .calc_face_normal = true,
393                        }));
394 
395     BMIter iter;
396     BMFace *f;
397     BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
398       if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
399         ss->face_sets[BM_elem_index_get(f)] = next_face_set;
400       }
401     }
402     BM_mesh_free(bm);
403   }
404 
405   for (int i = 0; i < totnode; i++) {
406     BKE_pbvh_node_mark_redraw(nodes[i]);
407   }
408 
409   MEM_SAFE_FREE(nodes);
410 
411   SCULPT_undo_push_end();
412 
413   SCULPT_tag_update_overlays(C);
414 
415   return OPERATOR_FINISHED;
416 }
417 
SCULPT_OT_face_sets_create(wmOperatorType * ot)418 void SCULPT_OT_face_sets_create(wmOperatorType *ot)
419 {
420   /* identifiers */
421   ot->name = "Create Face Set";
422   ot->idname = "SCULPT_OT_face_sets_create";
423   ot->description = "Create a new Face Set";
424 
425   /* api callbacks */
426   ot->exec = sculpt_face_set_create_exec;
427   ot->poll = SCULPT_mode_poll;
428 
429   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
430 
431   RNA_def_enum(
432       ot->srna, "mode", prop_sculpt_face_set_create_types, SCULPT_FACE_SET_MASKED, "Mode", "");
433 }
434 
435 typedef enum eSculptFaceSetsInitMode {
436   SCULPT_FACE_SETS_FROM_LOOSE_PARTS = 0,
437   SCULPT_FACE_SETS_FROM_MATERIALS = 1,
438   SCULPT_FACE_SETS_FROM_NORMALS = 2,
439   SCULPT_FACE_SETS_FROM_UV_SEAMS = 3,
440   SCULPT_FACE_SETS_FROM_CREASES = 4,
441   SCULPT_FACE_SETS_FROM_SHARP_EDGES = 5,
442   SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT = 6,
443   SCULPT_FACE_SETS_FROM_FACE_MAPS = 7,
444 } eSculptFaceSetsInitMode;
445 
446 static EnumPropertyItem prop_sculpt_face_sets_init_types[] = {
447     {
448         SCULPT_FACE_SETS_FROM_LOOSE_PARTS,
449         "LOOSE_PARTS",
450         0,
451         "Face Sets from Loose Parts",
452         "Create a Face Set per loose part in the mesh",
453     },
454     {
455         SCULPT_FACE_SETS_FROM_MATERIALS,
456         "MATERIALS",
457         0,
458         "Face Sets from Material Slots",
459         "Create a Face Set per Material Slot",
460     },
461     {
462         SCULPT_FACE_SETS_FROM_NORMALS,
463         "NORMALS",
464         0,
465         "Face Sets from Mesh Normals",
466         "Create Face Sets for Faces that have similar normal",
467     },
468     {
469         SCULPT_FACE_SETS_FROM_UV_SEAMS,
470         "UV_SEAMS",
471         0,
472         "Face Sets from UV Seams",
473         "Create Face Sets using UV Seams as boundaries",
474     },
475     {
476         SCULPT_FACE_SETS_FROM_CREASES,
477         "CREASES",
478         0,
479         "Face Sets from Edge Creases",
480         "Create Face Sets using Edge Creases as boundaries",
481     },
482     {
483         SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT,
484         "BEVEL_WEIGHT",
485         0,
486         "Face Sets from Bevel Weight",
487         "Create Face Sets using Bevel Weights as boundaries",
488     },
489     {
490         SCULPT_FACE_SETS_FROM_SHARP_EDGES,
491         "SHARP_EDGES",
492         0,
493         "Face Sets from Sharp Edges",
494         "Create Face Sets using Sharp Edges as boundaries",
495     },
496     {
497         SCULPT_FACE_SETS_FROM_FACE_MAPS,
498         "FACE_MAPS",
499         0,
500         "Face Sets from Face Maps",
501         "Create a Face Set per Face Map",
502     },
503     {0, NULL, 0, NULL, NULL},
504 };
505 
506 typedef bool (*face_sets_flood_fill_test)(
507     BMesh *bm, BMFace *from_f, BMEdge *from_e, BMFace *to_f, const float threshold);
508 
sculpt_face_sets_init_loose_parts_test(BMesh * UNUSED (bm),BMFace * UNUSED (from_f),BMEdge * UNUSED (from_e),BMFace * UNUSED (to_f),const float UNUSED (threshold))509 static bool sculpt_face_sets_init_loose_parts_test(BMesh *UNUSED(bm),
510                                                    BMFace *UNUSED(from_f),
511                                                    BMEdge *UNUSED(from_e),
512                                                    BMFace *UNUSED(to_f),
513                                                    const float UNUSED(threshold))
514 {
515   return true;
516 }
517 
sculpt_face_sets_init_normals_test(BMesh * UNUSED (bm),BMFace * from_f,BMEdge * UNUSED (from_e),BMFace * to_f,const float threshold)518 static bool sculpt_face_sets_init_normals_test(
519     BMesh *UNUSED(bm), BMFace *from_f, BMEdge *UNUSED(from_e), BMFace *to_f, const float threshold)
520 {
521   return fabsf(dot_v3v3(from_f->no, to_f->no)) > threshold;
522 }
523 
sculpt_face_sets_init_uv_seams_test(BMesh * UNUSED (bm),BMFace * UNUSED (from_f),BMEdge * from_e,BMFace * UNUSED (to_f),const float UNUSED (threshold))524 static bool sculpt_face_sets_init_uv_seams_test(BMesh *UNUSED(bm),
525                                                 BMFace *UNUSED(from_f),
526                                                 BMEdge *from_e,
527                                                 BMFace *UNUSED(to_f),
528                                                 const float UNUSED(threshold))
529 {
530   return !BM_elem_flag_test(from_e, BM_ELEM_SEAM);
531 }
532 
sculpt_face_sets_init_crease_test(BMesh * bm,BMFace * UNUSED (from_f),BMEdge * from_e,BMFace * UNUSED (to_f),const float threshold)533 static bool sculpt_face_sets_init_crease_test(
534     BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold)
535 {
536   return BM_elem_float_data_get(&bm->edata, from_e, CD_CREASE) < threshold;
537 }
538 
sculpt_face_sets_init_bevel_weight_test(BMesh * bm,BMFace * UNUSED (from_f),BMEdge * from_e,BMFace * UNUSED (to_f),const float threshold)539 static bool sculpt_face_sets_init_bevel_weight_test(
540     BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold)
541 {
542   return BM_elem_float_data_get(&bm->edata, from_e, CD_BWEIGHT) < threshold;
543 }
544 
sculpt_face_sets_init_sharp_edges_test(BMesh * UNUSED (bm),BMFace * UNUSED (from_f),BMEdge * from_e,BMFace * UNUSED (to_f),const float UNUSED (threshold))545 static bool sculpt_face_sets_init_sharp_edges_test(BMesh *UNUSED(bm),
546                                                    BMFace *UNUSED(from_f),
547                                                    BMEdge *from_e,
548                                                    BMFace *UNUSED(to_f),
549                                                    const float UNUSED(threshold))
550 {
551   return BM_elem_flag_test(from_e, BM_ELEM_SMOOTH);
552 }
553 
sculpt_face_sets_init_flood_fill(Object * ob,face_sets_flood_fill_test test,const float threshold)554 static void sculpt_face_sets_init_flood_fill(Object *ob,
555                                              face_sets_flood_fill_test test,
556                                              const float threshold)
557 {
558   SculptSession *ss = ob->sculpt;
559   Mesh *mesh = ob->data;
560   BMesh *bm;
561   const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
562   bm = BM_mesh_create(&allocsize,
563                       &((struct BMeshCreateParams){
564                           .use_toolflags = true,
565                       }));
566 
567   BM_mesh_bm_from_me(bm,
568                      mesh,
569                      (&(struct BMeshFromMeshParams){
570                          .calc_face_normal = true,
571                      }));
572 
573   BLI_bitmap *visited_faces = BLI_BITMAP_NEW(mesh->totpoly, "visited faces");
574   const int totfaces = mesh->totpoly;
575 
576   int *face_sets = ss->face_sets;
577 
578   BM_mesh_elem_table_init(bm, BM_FACE);
579   BM_mesh_elem_table_ensure(bm, BM_FACE);
580 
581   int next_face_set = 1;
582 
583   for (int i = 0; i < totfaces; i++) {
584     if (!BLI_BITMAP_TEST(visited_faces, i)) {
585       GSQueue *queue;
586       queue = BLI_gsqueue_new(sizeof(int));
587 
588       face_sets[i] = next_face_set;
589       BLI_BITMAP_ENABLE(visited_faces, i);
590       BLI_gsqueue_push(queue, &i);
591 
592       while (!BLI_gsqueue_is_empty(queue)) {
593         int from_f;
594         BLI_gsqueue_pop(queue, &from_f);
595 
596         BMFace *f, *f_neighbor;
597         BMEdge *ed;
598         BMIter iter_a, iter_b;
599 
600         f = BM_face_at_index(bm, from_f);
601 
602         BM_ITER_ELEM (ed, &iter_a, f, BM_EDGES_OF_FACE) {
603           BM_ITER_ELEM (f_neighbor, &iter_b, ed, BM_FACES_OF_EDGE) {
604             if (f_neighbor != f) {
605               int neighbor_face_index = BM_elem_index_get(f_neighbor);
606               if (!BLI_BITMAP_TEST(visited_faces, neighbor_face_index)) {
607                 if (test(bm, f, ed, f_neighbor, threshold)) {
608                   face_sets[neighbor_face_index] = next_face_set;
609                   BLI_BITMAP_ENABLE(visited_faces, neighbor_face_index);
610                   BLI_gsqueue_push(queue, &neighbor_face_index);
611                 }
612               }
613             }
614           }
615         }
616       }
617 
618       next_face_set += 1;
619 
620       BLI_gsqueue_free(queue);
621     }
622   }
623 
624   MEM_SAFE_FREE(visited_faces);
625 
626   BM_mesh_free(bm);
627 }
628 
sculpt_face_sets_init_loop(Object * ob,const int mode)629 static void sculpt_face_sets_init_loop(Object *ob, const int mode)
630 {
631   Mesh *mesh = ob->data;
632   SculptSession *ss = ob->sculpt;
633   BMesh *bm;
634   const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
635   bm = BM_mesh_create(&allocsize,
636                       &((struct BMeshCreateParams){
637                           .use_toolflags = true,
638                       }));
639 
640   BM_mesh_bm_from_me(bm,
641                      mesh,
642                      (&(struct BMeshFromMeshParams){
643                          .calc_face_normal = true,
644                      }));
645   BMIter iter;
646   BMFace *f;
647 
648   const int cd_fmaps_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP);
649 
650   BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
651     if (mode == SCULPT_FACE_SETS_FROM_MATERIALS) {
652       ss->face_sets[BM_elem_index_get(f)] = (int)(f->mat_nr + 1);
653     }
654     else if (mode == SCULPT_FACE_SETS_FROM_FACE_MAPS) {
655       if (cd_fmaps_offset != -1) {
656         ss->face_sets[BM_elem_index_get(f)] = BM_ELEM_CD_GET_INT(f, cd_fmaps_offset) + 2;
657       }
658       else {
659         ss->face_sets[BM_elem_index_get(f)] = 1;
660       }
661     }
662   }
663   BM_mesh_free(bm);
664 }
665 
sculpt_face_set_init_exec(bContext * C,wmOperator * op)666 static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
667 {
668   Object *ob = CTX_data_active_object(C);
669   SculptSession *ss = ob->sculpt;
670   Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
671 
672   const int mode = RNA_enum_get(op->ptr, "mode");
673 
674   /* Dyntopo not supported. */
675   if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
676     return OPERATOR_CANCELLED;
677   }
678 
679   BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
680 
681   PBVH *pbvh = ob->sculpt->pbvh;
682   PBVHNode **nodes;
683   int totnode;
684   BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
685 
686   if (!nodes) {
687     return OPERATOR_CANCELLED;
688   }
689 
690   SCULPT_undo_push_begin("face set change");
691   SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS);
692 
693   const float threshold = RNA_float_get(op->ptr, "threshold");
694 
695   switch (mode) {
696     case SCULPT_FACE_SETS_FROM_LOOSE_PARTS:
697       sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_loose_parts_test, threshold);
698       break;
699     case SCULPT_FACE_SETS_FROM_MATERIALS:
700       sculpt_face_sets_init_loop(ob, SCULPT_FACE_SETS_FROM_MATERIALS);
701       break;
702     case SCULPT_FACE_SETS_FROM_NORMALS:
703       sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_normals_test, threshold);
704       break;
705     case SCULPT_FACE_SETS_FROM_UV_SEAMS:
706       sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_uv_seams_test, threshold);
707       break;
708     case SCULPT_FACE_SETS_FROM_CREASES:
709       sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_crease_test, threshold);
710       break;
711     case SCULPT_FACE_SETS_FROM_SHARP_EDGES:
712       sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_sharp_edges_test, threshold);
713       break;
714     case SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT:
715       sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_bevel_weight_test, threshold);
716       break;
717     case SCULPT_FACE_SETS_FROM_FACE_MAPS:
718       sculpt_face_sets_init_loop(ob, SCULPT_FACE_SETS_FROM_FACE_MAPS);
719       break;
720   }
721 
722   SCULPT_undo_push_end();
723 
724   /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */
725   SCULPT_visibility_sync_all_face_sets_to_vertices(ob);
726 
727   for (int i = 0; i < totnode; i++) {
728     BKE_pbvh_node_mark_update_visibility(nodes[i]);
729   }
730 
731   BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility);
732 
733   MEM_SAFE_FREE(nodes);
734 
735   if (BKE_pbvh_type(pbvh) == PBVH_FACES) {
736     BKE_mesh_flush_hidden_from_verts(ob->data);
737   }
738 
739   SCULPT_tag_update_overlays(C);
740 
741   return OPERATOR_FINISHED;
742 }
743 
SCULPT_OT_face_sets_init(wmOperatorType * ot)744 void SCULPT_OT_face_sets_init(wmOperatorType *ot)
745 {
746   /* identifiers */
747   ot->name = "Init Face Sets";
748   ot->idname = "SCULPT_OT_face_sets_init";
749   ot->description = "Initializes all Face Sets in the mesh";
750 
751   /* api callbacks */
752   ot->exec = sculpt_face_set_init_exec;
753   ot->poll = SCULPT_mode_poll;
754 
755   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
756 
757   RNA_def_enum(
758       ot->srna, "mode", prop_sculpt_face_sets_init_types, SCULPT_FACE_SET_MASKED, "Mode", "");
759   RNA_def_float(
760       ot->srna,
761       "threshold",
762       0.5f,
763       0.0f,
764       1.0f,
765       "Threshold",
766       "Minimum value to consider a certain attribute a boundary when creating the Face Sets",
767       0.0f,
768       1.0f);
769 }
770 
771 typedef enum eSculptFaceGroupVisibilityModes {
772   SCULPT_FACE_SET_VISIBILITY_TOGGLE = 0,
773   SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE = 1,
774   SCULPT_FACE_SET_VISIBILITY_HIDE_ACTIVE = 2,
775   SCULPT_FACE_SET_VISIBILITY_INVERT = 3,
776   SCULPT_FACE_SET_VISIBILITY_SHOW_ALL = 4,
777 } eSculptFaceGroupVisibilityModes;
778 
779 static EnumPropertyItem prop_sculpt_face_sets_change_visibility_types[] = {
780     {
781         SCULPT_FACE_SET_VISIBILITY_TOGGLE,
782         "TOGGLE",
783         0,
784         "Toggle Visibility",
785         "Hide all Face Sets except for the active one",
786     },
787     {
788         SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE,
789         "SHOW_ACTIVE",
790         0,
791         "Show Active Face Set",
792         "Show Active Face Set",
793     },
794     {
795         SCULPT_FACE_SET_VISIBILITY_HIDE_ACTIVE,
796         "HIDE_ACTIVE",
797         0,
798         "Hide Active Face Sets",
799         "Hide Active Face Sets",
800     },
801     {
802         SCULPT_FACE_SET_VISIBILITY_INVERT,
803         "INVERT",
804         0,
805         "Invert Face Set Visibility",
806         "Invert Face Set Visibility",
807     },
808     {
809         SCULPT_FACE_SET_VISIBILITY_SHOW_ALL,
810         "SHOW_ALL",
811         0,
812         "Show All Face Sets",
813         "Show All Face Sets",
814     },
815     {0, NULL, 0, NULL, NULL},
816 };
817 
sculpt_face_sets_change_visibility_exec(bContext * C,wmOperator * op)818 static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
819 {
820   Object *ob = CTX_data_active_object(C);
821   SculptSession *ss = ob->sculpt;
822   Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
823 
824   /* Dyntopo not supported. */
825   if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
826     return OPERATOR_CANCELLED;
827   }
828 
829   BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
830 
831   const int tot_vert = SCULPT_vertex_count_get(ss);
832   const int mode = RNA_enum_get(op->ptr, "mode");
833   const int active_face_set = SCULPT_active_face_set_get(ss);
834 
835   SCULPT_undo_push_begin("Hide area");
836 
837   PBVH *pbvh = ob->sculpt->pbvh;
838   PBVHNode **nodes;
839   int totnode;
840 
841   BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
842 
843   if (totnode == 0) {
844     MEM_SAFE_FREE(nodes);
845     return OPERATOR_CANCELLED;
846   }
847 
848   SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS);
849 
850   if (mode == SCULPT_FACE_SET_VISIBILITY_TOGGLE) {
851     bool hidden_vertex = false;
852 
853     /* This can fail with regular meshes with non-manifold geometry as the visibility state can't
854      * be synced from face sets to non-manifold vertices. */
855     if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
856       for (int i = 0; i < tot_vert; i++) {
857         if (!SCULPT_vertex_visible_get(ss, i)) {
858           hidden_vertex = true;
859           break;
860         }
861       }
862     }
863 
864     for (int i = 0; i < ss->totfaces; i++) {
865       if (ss->face_sets[i] <= 0) {
866         hidden_vertex = true;
867         break;
868       }
869     }
870 
871     if (hidden_vertex) {
872       SCULPT_face_sets_visibility_all_set(ss, true);
873     }
874     else {
875       SCULPT_face_sets_visibility_all_set(ss, false);
876       SCULPT_face_set_visibility_set(ss, active_face_set, true);
877     }
878   }
879 
880   if (mode == SCULPT_FACE_SET_VISIBILITY_SHOW_ALL) {
881     SCULPT_face_sets_visibility_all_set(ss, true);
882   }
883 
884   if (mode == SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE) {
885     SCULPT_face_sets_visibility_all_set(ss, false);
886     SCULPT_face_set_visibility_set(ss, active_face_set, true);
887   }
888 
889   if (mode == SCULPT_FACE_SET_VISIBILITY_HIDE_ACTIVE) {
890     SCULPT_face_set_visibility_set(ss, active_face_set, false);
891   }
892 
893   if (mode == SCULPT_FACE_SET_VISIBILITY_INVERT) {
894     SCULPT_face_sets_visibility_invert(ss);
895   }
896 
897   /* For modes that use the cursor active vertex, update the rotation origin for viewport
898    * navigation. */
899   if (ELEM(mode, SCULPT_FACE_SET_VISIBILITY_TOGGLE, SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE)) {
900     UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
901     float location[3];
902     copy_v3_v3(location, SCULPT_active_vertex_co_get(ss));
903     mul_m4_v3(ob->obmat, location);
904     copy_v3_v3(ups->average_stroke_accum, location);
905     ups->average_stroke_counter = 1;
906     ups->last_stroke_valid = true;
907   }
908 
909   /* Sync face sets visibility and vertex visibility. */
910   SCULPT_visibility_sync_all_face_sets_to_vertices(ob);
911 
912   SCULPT_undo_push_end();
913 
914   for (int i = 0; i < totnode; i++) {
915     BKE_pbvh_node_mark_update_visibility(nodes[i]);
916   }
917 
918   BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility);
919 
920   MEM_SAFE_FREE(nodes);
921 
922   if (BKE_pbvh_type(pbvh) == PBVH_FACES) {
923     BKE_mesh_flush_hidden_from_verts(ob->data);
924   }
925 
926   SCULPT_tag_update_overlays(C);
927 
928   return OPERATOR_FINISHED;
929 }
930 
sculpt_face_sets_change_visibility_invoke(bContext * C,wmOperator * op,const wmEvent * event)931 static int sculpt_face_sets_change_visibility_invoke(bContext *C,
932                                                      wmOperator *op,
933                                                      const wmEvent *event)
934 {
935   Object *ob = CTX_data_active_object(C);
936   SculptSession *ss = ob->sculpt;
937 
938   /* Update the active vertex and Face Set using the cursor position to avoid relying on the paint
939    * cursor updates. */
940   SculptCursorGeometryInfo sgi;
941   float mouse[2];
942   mouse[0] = event->mval[0];
943   mouse[1] = event->mval[1];
944   SCULPT_vertex_random_access_ensure(ss);
945   SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
946 
947   return sculpt_face_sets_change_visibility_exec(C, op);
948 }
949 
SCULPT_OT_face_sets_change_visibility(wmOperatorType * ot)950 void SCULPT_OT_face_sets_change_visibility(wmOperatorType *ot)
951 {
952   /* Identifiers. */
953   ot->name = "Face Sets Visibility";
954   ot->idname = "SCULPT_OT_face_set_change_visibility";
955   ot->description = "Change the visibility of the Face Sets of the sculpt";
956 
957   /* Api callbacks. */
958   ot->exec = sculpt_face_sets_change_visibility_exec;
959   ot->invoke = sculpt_face_sets_change_visibility_invoke;
960   ot->poll = SCULPT_mode_poll;
961 
962   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
963 
964   RNA_def_enum(ot->srna,
965                "mode",
966                prop_sculpt_face_sets_change_visibility_types,
967                SCULPT_FACE_SET_VISIBILITY_TOGGLE,
968                "Mode",
969                "");
970 }
971 
sculpt_face_sets_randomize_colors_exec(bContext * C,wmOperator * UNUSED (op))972 static int sculpt_face_sets_randomize_colors_exec(bContext *C, wmOperator *UNUSED(op))
973 {
974 
975   Object *ob = CTX_data_active_object(C);
976   SculptSession *ss = ob->sculpt;
977 
978   /* Dyntopo not supported. */
979   if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
980     return OPERATOR_CANCELLED;
981   }
982 
983   PBVH *pbvh = ob->sculpt->pbvh;
984   PBVHNode **nodes;
985   int totnode;
986   Mesh *mesh = ob->data;
987 
988   mesh->face_sets_color_seed += 1;
989   if (ss->face_sets) {
990     const int random_index = clamp_i(ss->totfaces * BLI_hash_int_01(mesh->face_sets_color_seed),
991                                      0,
992                                      max_ii(0, ss->totfaces - 1));
993     mesh->face_sets_color_default = ss->face_sets[random_index];
994   }
995   BKE_pbvh_face_sets_color_set(pbvh, mesh->face_sets_color_seed, mesh->face_sets_color_default);
996 
997   BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
998   for (int i = 0; i < totnode; i++) {
999     BKE_pbvh_node_mark_redraw(nodes[i]);
1000   }
1001 
1002   MEM_SAFE_FREE(nodes);
1003 
1004   SCULPT_tag_update_overlays(C);
1005 
1006   return OPERATOR_FINISHED;
1007 }
1008 
SCULPT_OT_face_sets_randomize_colors(wmOperatorType * ot)1009 void SCULPT_OT_face_sets_randomize_colors(wmOperatorType *ot)
1010 {
1011   /* Identifiers. */
1012   ot->name = "Randomize Face Sets Colors";
1013   ot->idname = "SCULPT_OT_face_sets_randomize_colors";
1014   ot->description = "Generates a new set of random colors to render the Face Sets in the viewport";
1015 
1016   /* Api callbacks. */
1017   ot->exec = sculpt_face_sets_randomize_colors_exec;
1018   ot->poll = SCULPT_mode_poll;
1019 
1020   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1021 }
1022 
1023 typedef enum eSculptFaceSetEditMode {
1024   SCULPT_FACE_SET_EDIT_GROW = 0,
1025   SCULPT_FACE_SET_EDIT_SHRINK = 1,
1026 } eSculptFaceSetEditMode;
1027 
1028 static EnumPropertyItem prop_sculpt_face_sets_edit_types[] = {
1029     {
1030         SCULPT_FACE_SET_EDIT_GROW,
1031         "GROW",
1032         0,
1033         "Grow Face Set",
1034         "Grows the Face Sets boundary by one face based on mesh topology",
1035     },
1036     {
1037         SCULPT_FACE_SET_EDIT_SHRINK,
1038         "SHRINK",
1039         0,
1040         "Shrink Face Set",
1041         "Shrinks the Face Sets boundary by one face based on mesh topology",
1042     },
1043     {0, NULL, 0, NULL, NULL},
1044 };
1045 
sculpt_face_set_grow(Object * ob,SculptSession * ss,const int * prev_face_sets,const int active_face_set_id,const bool modify_hidden)1046 static void sculpt_face_set_grow(Object *ob,
1047                                  SculptSession *ss,
1048                                  const int *prev_face_sets,
1049                                  const int active_face_set_id,
1050                                  const bool modify_hidden)
1051 {
1052   Mesh *mesh = BKE_mesh_from_object(ob);
1053   for (int p = 0; p < mesh->totpoly; p++) {
1054     if (!modify_hidden && prev_face_sets[p] <= 0) {
1055       continue;
1056     }
1057     const MPoly *c_poly = &mesh->mpoly[p];
1058     for (int l = 0; l < c_poly->totloop; l++) {
1059       const MLoop *c_loop = &mesh->mloop[c_poly->loopstart + l];
1060       const MeshElemMap *vert_map = &ss->pmap[c_loop->v];
1061       for (int i = 0; i < vert_map->count; i++) {
1062         const int neighbor_face_index = vert_map->indices[i];
1063         if (neighbor_face_index == p) {
1064           continue;
1065         }
1066         if (abs(prev_face_sets[neighbor_face_index]) == active_face_set_id) {
1067           ss->face_sets[p] = active_face_set_id;
1068         }
1069       }
1070     }
1071   }
1072 }
1073 
sculpt_face_set_shrink(Object * ob,SculptSession * ss,const int * prev_face_sets,const int active_face_set_id,const bool modify_hidden)1074 static void sculpt_face_set_shrink(Object *ob,
1075                                    SculptSession *ss,
1076                                    const int *prev_face_sets,
1077                                    const int active_face_set_id,
1078                                    const bool modify_hidden)
1079 {
1080   Mesh *mesh = BKE_mesh_from_object(ob);
1081   for (int p = 0; p < mesh->totpoly; p++) {
1082     if (!modify_hidden && prev_face_sets[p] <= 0) {
1083       continue;
1084     }
1085     if (abs(prev_face_sets[p]) == active_face_set_id) {
1086       const MPoly *c_poly = &mesh->mpoly[p];
1087       for (int l = 0; l < c_poly->totloop; l++) {
1088         const MLoop *c_loop = &mesh->mloop[c_poly->loopstart + l];
1089         const MeshElemMap *vert_map = &ss->pmap[c_loop->v];
1090         for (int i = 0; i < vert_map->count; i++) {
1091           const int neighbor_face_index = vert_map->indices[i];
1092           if (neighbor_face_index == p) {
1093             continue;
1094           }
1095           if (abs(prev_face_sets[neighbor_face_index]) != active_face_set_id) {
1096             ss->face_sets[p] = prev_face_sets[neighbor_face_index];
1097           }
1098         }
1099       }
1100     }
1101   }
1102 }
1103 
sculpt_face_set_apply_edit(Object * ob,const int active_face_set_id,const int mode,const bool modify_hidden)1104 static void sculpt_face_set_apply_edit(Object *ob,
1105                                        const int active_face_set_id,
1106                                        const int mode,
1107                                        const bool modify_hidden)
1108 {
1109   SculptSession *ss = ob->sculpt;
1110 
1111   int *prev_face_sets = MEM_dupallocN(ss->face_sets);
1112 
1113   switch (mode) {
1114     case SCULPT_FACE_SET_EDIT_GROW:
1115       sculpt_face_set_grow(ob, ss, prev_face_sets, active_face_set_id, modify_hidden);
1116       break;
1117     case SCULPT_FACE_SET_EDIT_SHRINK:
1118       sculpt_face_set_shrink(ob, ss, prev_face_sets, active_face_set_id, modify_hidden);
1119       break;
1120   }
1121 
1122   MEM_SAFE_FREE(prev_face_sets);
1123 }
1124 
sculpt_face_set_edit_invoke(bContext * C,wmOperator * op,const wmEvent * event)1125 static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1126 {
1127   Object *ob = CTX_data_active_object(C);
1128   SculptSession *ss = ob->sculpt;
1129   Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
1130 
1131   const int mode = RNA_enum_get(op->ptr, "mode");
1132 
1133   /* Dyntopo not supported. */
1134   if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
1135     return OPERATOR_CANCELLED;
1136   }
1137 
1138   /* Ignore other events to avoid repeated operations. */
1139   if (event->val != KM_PRESS) {
1140     return OPERATOR_CANCELLED;
1141   }
1142 
1143   BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
1144 
1145   /* Update the current active Face Set and Vertex as the operator can be used directly from the
1146    * tool without brush cursor. */
1147   SculptCursorGeometryInfo sgi;
1148   float mouse[2];
1149   mouse[0] = event->mval[0];
1150   mouse[1] = event->mval[1];
1151   SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
1152 
1153   PBVH *pbvh = ob->sculpt->pbvh;
1154   PBVHNode **nodes;
1155   int totnode;
1156   BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
1157 
1158   if (!nodes) {
1159     return OPERATOR_CANCELLED;
1160   }
1161 
1162   SCULPT_undo_push_begin("face set edit");
1163   SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS);
1164 
1165   const int active_face_set = SCULPT_active_face_set_get(ss);
1166   const bool modify_hidden = RNA_boolean_get(op->ptr, "modify_hidden");
1167 
1168   sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden);
1169 
1170   SCULPT_undo_push_end();
1171 
1172   /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */
1173   SCULPT_visibility_sync_all_face_sets_to_vertices(ob);
1174 
1175   for (int i = 0; i < totnode; i++) {
1176     BKE_pbvh_node_mark_update_visibility(nodes[i]);
1177   }
1178 
1179   BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility);
1180 
1181   MEM_SAFE_FREE(nodes);
1182 
1183   if (BKE_pbvh_type(pbvh) == PBVH_FACES) {
1184     BKE_mesh_flush_hidden_from_verts(ob->data);
1185   }
1186 
1187   SCULPT_tag_update_overlays(C);
1188 
1189   return OPERATOR_FINISHED;
1190 }
1191 
SCULPT_OT_face_sets_edit(struct wmOperatorType * ot)1192 void SCULPT_OT_face_sets_edit(struct wmOperatorType *ot)
1193 {
1194   /* Identifiers. */
1195   ot->name = "Edit Face Set";
1196   ot->idname = "SCULPT_OT_face_set_edit";
1197   ot->description = "Edits the current active Face Set";
1198 
1199   /* Api callbacks. */
1200   ot->invoke = sculpt_face_set_edit_invoke;
1201   ot->poll = SCULPT_mode_poll;
1202 
1203   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1204 
1205   RNA_def_enum(
1206       ot->srna, "mode", prop_sculpt_face_sets_edit_types, SCULPT_FACE_SET_EDIT_GROW, "Mode", "");
1207   ot->prop = RNA_def_boolean(ot->srna,
1208                              "modify_hidden",
1209                              true,
1210                              "Modify Hidden",
1211                              "Apply the edit operation to hidden Face Sets");
1212 }
1213