Cleanup: style, use braces for editors
[blender.git] / source / blender / editors / sculpt_paint / paint_mask.c
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) 2012 by Nicholas Bishop
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edsculpt
22  */
23
24 #include "MEM_guardedalloc.h"
25
26 #include "DNA_meshdata_types.h"
27 #include "DNA_object_types.h"
28
29 #include "BLI_bitmap_draw_2d.h"
30 #include "BLI_math_matrix.h"
31 #include "BLI_math_geom.h"
32 #include "BLI_utildefines.h"
33 #include "BLI_lasso_2d.h"
34 #include "BLI_task.h"
35
36 #include "BKE_pbvh.h"
37 #include "BKE_ccg.h"
38 #include "BKE_context.h"
39 #include "BKE_multires.h"
40 #include "BKE_paint.h"
41 #include "BKE_subsurf.h"
42
43 #include "DEG_depsgraph.h"
44
45 #include "RNA_access.h"
46 #include "RNA_define.h"
47
48 #include "WM_api.h"
49 #include "WM_types.h"
50
51 #include "ED_screen.h"
52 #include "ED_sculpt.h"
53 #include "ED_view3d.h"
54
55 #include "bmesh.h"
56
57 #include "paint_intern.h"
58 #include "sculpt_intern.h" /* for undo push */
59
60 #include <stdlib.h>
61
62 static const EnumPropertyItem mode_items[] = {
63     {PAINT_MASK_FLOOD_VALUE,
64      "VALUE",
65      0,
66      "Value",
67      "Set mask to the level specified by the 'value' property"},
68     {PAINT_MASK_FLOOD_VALUE_INVERSE,
69      "VALUE_INVERSE",
70      0,
71      "Value Inverted",
72      "Set mask to the level specified by the inverted 'value' property"},
73     {PAINT_MASK_INVERT, "INVERT", 0, "Invert", "Invert the mask"},
74     {0}};
75
76 static void mask_flood_fill_set_elem(float *elem, PaintMaskFloodMode mode, float value)
77 {
78   switch (mode) {
79     case PAINT_MASK_FLOOD_VALUE:
80       (*elem) = value;
81       break;
82     case PAINT_MASK_FLOOD_VALUE_INVERSE:
83       (*elem) = 1.0f - value;
84       break;
85     case PAINT_MASK_INVERT:
86       (*elem) = 1.0f - (*elem);
87       break;
88   }
89 }
90
91 typedef struct MaskTaskData {
92   Object *ob;
93   PBVH *pbvh;
94   PBVHNode **nodes;
95   bool multires;
96
97   PaintMaskFloodMode mode;
98   float value;
99   float (*clip_planes_final)[4];
100 } MaskTaskData;
101
102 static void mask_flood_fill_task_cb(void *__restrict userdata,
103                                     const int i,
104                                     const ParallelRangeTLS *__restrict UNUSED(tls))
105 {
106   MaskTaskData *data = userdata;
107
108   PBVHNode *node = data->nodes[i];
109
110   const PaintMaskFloodMode mode = data->mode;
111   const float value = data->value;
112
113   PBVHVertexIter vi;
114
115   sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_MASK);
116
117   BKE_pbvh_vertex_iter_begin(data->pbvh, node, vi, PBVH_ITER_UNIQUE)
118   {
119     mask_flood_fill_set_elem(vi.mask, mode, value);
120   }
121   BKE_pbvh_vertex_iter_end;
122
123   BKE_pbvh_node_mark_redraw(node);
124   if (data->multires) {
125     BKE_pbvh_node_mark_normals_update(node);
126   }
127 }
128
129 static int mask_flood_fill_exec(bContext *C, wmOperator *op)
130 {
131   ARegion *ar = CTX_wm_region(C);
132   struct Scene *scene = CTX_data_scene(C);
133   Object *ob = CTX_data_active_object(C);
134   Depsgraph *depsgraph = CTX_data_depsgraph(C);
135   PaintMaskFloodMode mode;
136   float value;
137   PBVH *pbvh;
138   PBVHNode **nodes;
139   int totnode;
140   bool multires;
141   Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
142
143   mode = RNA_enum_get(op->ptr, "mode");
144   value = RNA_float_get(op->ptr, "value");
145
146   BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, true);
147   pbvh = ob->sculpt->pbvh;
148   multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
149
150   BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);
151
152   sculpt_undo_push_begin("Mask flood fill");
153
154   MaskTaskData data = {
155       .ob = ob,
156       .pbvh = pbvh,
157       .nodes = nodes,
158       .multires = multires,
159       .mode = mode,
160       .value = value,
161   };
162
163   ParallelRangeSettings settings;
164   BLI_parallel_range_settings_defaults(&settings);
165   settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_THREADED_LIMIT);
166   BLI_task_parallel_range(
167
168       0, totnode, &data, mask_flood_fill_task_cb, &settings);
169
170   if (multires) {
171     multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
172   }
173
174   sculpt_undo_push_end();
175
176   if (nodes) {
177     MEM_freeN(nodes);
178   }
179
180   ED_region_tag_redraw(ar);
181
182   WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
183
184   return OPERATOR_FINISHED;
185 }
186
187 void PAINT_OT_mask_flood_fill(struct wmOperatorType *ot)
188 {
189   /* identifiers */
190   ot->name = "Mask Flood Fill";
191   ot->idname = "PAINT_OT_mask_flood_fill";
192   ot->description = "Fill the whole mask with a given value, or invert its values";
193
194   /* api callbacks */
195   ot->exec = mask_flood_fill_exec;
196   ot->poll = sculpt_mode_poll;
197
198   ot->flag = OPTYPE_REGISTER;
199
200   /* rna */
201   RNA_def_enum(ot->srna, "mode", mode_items, PAINT_MASK_FLOOD_VALUE, "Mode", NULL);
202   RNA_def_float(
203       ot->srna,
204       "value",
205       0,
206       0,
207       1,
208       "Value",
209       "Mask level to use when mode is 'Value'; zero means no masking and one is fully masked",
210       0,
211       1);
212 }
213
214 /* Box select, operator is VIEW3D_OT_select_box, defined in view3d_select.c */
215
216 static bool is_effected(float planes[4][4], const float co[3])
217 {
218   return isect_point_planes_v3(planes, 4, co);
219 }
220
221 static void flip_plane(float out[4], const float in[4], const char symm)
222 {
223   if (symm & PAINT_SYMM_X) {
224     out[0] = -in[0];
225   }
226   else {
227     out[0] = in[0];
228   }
229   if (symm & PAINT_SYMM_Y) {
230     out[1] = -in[1];
231   }
232   else {
233     out[1] = in[1];
234   }
235   if (symm & PAINT_SYMM_Z) {
236     out[2] = -in[2];
237   }
238   else {
239     out[2] = in[2];
240   }
241
242   out[3] = in[3];
243 }
244
245 static void mask_box_select_task_cb(void *__restrict userdata,
246                                     const int i,
247                                     const ParallelRangeTLS *__restrict UNUSED(tls))
248 {
249   MaskTaskData *data = userdata;
250
251   PBVHNode *node = data->nodes[i];
252
253   const PaintMaskFloodMode mode = data->mode;
254   const float value = data->value;
255   float(*clip_planes_final)[4] = data->clip_planes_final;
256
257   PBVHVertexIter vi;
258   bool any_masked = false;
259
260   BKE_pbvh_vertex_iter_begin(data->pbvh, node, vi, PBVH_ITER_UNIQUE)
261   {
262     if (is_effected(clip_planes_final, vi.co)) {
263       if (!any_masked) {
264         any_masked = true;
265
266         sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_MASK);
267
268         BKE_pbvh_node_mark_redraw(node);
269         if (data->multires) {
270           BKE_pbvh_node_mark_normals_update(node);
271         }
272       }
273       mask_flood_fill_set_elem(vi.mask, mode, value);
274     }
275   }
276   BKE_pbvh_vertex_iter_end;
277 }
278
279 bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *rect, bool select)
280 {
281   Depsgraph *depsgraph = CTX_data_depsgraph(C);
282   Sculpt *sd = vc->scene->toolsettings->sculpt;
283   BoundBox bb;
284   float clip_planes[4][4];
285   float clip_planes_final[4][4];
286   ARegion *ar = vc->ar;
287   struct Scene *scene = vc->scene;
288   Object *ob = vc->obact;
289   PaintMaskFloodMode mode;
290   float value;
291   bool multires;
292   PBVH *pbvh;
293   PBVHNode **nodes;
294   int totnode, symmpass;
295   int symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
296
297   mode = PAINT_MASK_FLOOD_VALUE;
298   value = select ? 1.0 : 0.0;
299
300   /* transform the clip planes in object space */
301   ED_view3d_clipping_calc(&bb, clip_planes, vc->ar, vc->obact, rect);
302   negate_m4(clip_planes);
303
304   BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, true);
305   pbvh = ob->sculpt->pbvh;
306   multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
307
308   sculpt_undo_push_begin("Mask box fill");
309
310   for (symmpass = 0; symmpass <= symm; ++symmpass) {
311     if (symmpass == 0 || (symm & symmpass && (symm != 5 || symmpass != 3) &&
312                           (symm != 6 || (symmpass != 3 && symmpass != 5)))) {
313       int j = 0;
314
315       /* flip the planes symmetrically as needed */
316       for (; j < 4; j++) {
317         flip_plane(clip_planes_final[j], clip_planes[j], symmpass);
318       }
319
320       BKE_pbvh_search_gather(
321           pbvh, BKE_pbvh_node_planes_contain_AABB, clip_planes_final, &nodes, &totnode);
322
323       MaskTaskData data = {
324           .ob = ob,
325           .pbvh = pbvh,
326           .nodes = nodes,
327           .multires = multires,
328           .mode = mode,
329           .value = value,
330           .clip_planes_final = clip_planes_final,
331       };
332
333       ParallelRangeSettings settings;
334       BLI_parallel_range_settings_defaults(&settings);
335       settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) &&
336                                 totnode > SCULPT_THREADED_LIMIT);
337       BLI_task_parallel_range(0, totnode, &data, mask_box_select_task_cb, &settings);
338
339       if (nodes) {
340         MEM_freeN(nodes);
341       }
342     }
343   }
344
345   if (multires) {
346     multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
347   }
348
349   sculpt_undo_push_end();
350
351   ED_region_tag_redraw(ar);
352
353   WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
354
355   return true;
356 }
357
358 typedef struct LassoMaskData {
359   struct ViewContext *vc;
360   float projviewobjmat[4][4];
361   BLI_bitmap *px;
362   int width;
363   rcti rect; /* bounding box for scanfilling */
364   int symmpass;
365
366   MaskTaskData task_data;
367 } LassoMaskData;
368
369 /**
370  * Lasso select. This could be defined as part of #VIEW3D_OT_select_lasso,
371  * still the shortcuts conflict, so we will use a separate operator.
372  */
373 static bool is_effected_lasso(LassoMaskData *data, float co[3])
374 {
375   float scr_co_f[2];
376   int scr_co_s[2];
377   float co_final[3];
378
379   flip_v3_v3(co_final, co, data->symmpass);
380   /* first project point to 2d space */
381   ED_view3d_project_float_v2_m4(data->vc->ar, co_final, scr_co_f, data->projviewobjmat);
382
383   scr_co_s[0] = scr_co_f[0];
384   scr_co_s[1] = scr_co_f[1];
385
386   /* clip against screen, because lasso is limited to screen only */
387   if ((scr_co_s[0] < data->rect.xmin) || (scr_co_s[1] < data->rect.ymin) ||
388       (scr_co_s[0] >= data->rect.xmax) || (scr_co_s[1] >= data->rect.ymax)) {
389     return false;
390   }
391
392   scr_co_s[0] -= data->rect.xmin;
393   scr_co_s[1] -= data->rect.ymin;
394
395   return BLI_BITMAP_TEST_BOOL(data->px, scr_co_s[1] * data->width + scr_co_s[0]);
396 }
397
398 static void mask_lasso_px_cb(int x, int x_end, int y, void *user_data)
399 {
400   LassoMaskData *data = user_data;
401   int index = (y * data->width) + x;
402   int index_end = (y * data->width) + x_end;
403   do {
404     BLI_BITMAP_ENABLE(data->px, index);
405   } while (++index != index_end);
406 }
407
408 static void mask_gesture_lasso_task_cb(void *__restrict userdata,
409                                        const int i,
410                                        const ParallelRangeTLS *__restrict UNUSED(tls))
411 {
412   LassoMaskData *lasso_data = userdata;
413   MaskTaskData *data = &lasso_data->task_data;
414
415   PBVHNode *node = data->nodes[i];
416
417   const PaintMaskFloodMode mode = data->mode;
418   const float value = data->value;
419
420   PBVHVertexIter vi;
421   bool any_masked = false;
422
423   BKE_pbvh_vertex_iter_begin(data->pbvh, node, vi, PBVH_ITER_UNIQUE)
424   {
425     if (is_effected_lasso(lasso_data, vi.co)) {
426       if (!any_masked) {
427         any_masked = true;
428
429         sculpt_undo_push_node(data->ob, node, SCULPT_UNDO_MASK);
430
431         BKE_pbvh_node_mark_redraw(node);
432         if (data->multires) {
433           BKE_pbvh_node_mark_normals_update(node);
434         }
435       }
436
437       mask_flood_fill_set_elem(vi.mask, mode, value);
438     }
439   }
440   BKE_pbvh_vertex_iter_end;
441 }
442
443 static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
444 {
445   int mcords_tot;
446   const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
447
448   if (mcords) {
449     Depsgraph *depsgraph = CTX_data_depsgraph(C);
450     float clip_planes[4][4], clip_planes_final[4][4];
451     BoundBox bb;
452     Object *ob;
453     ViewContext vc;
454     LassoMaskData data;
455     struct Scene *scene = CTX_data_scene(C);
456     Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
457     int symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
458     PBVH *pbvh;
459     PBVHNode **nodes;
460     int totnode, symmpass;
461     bool multires;
462     PaintMaskFloodMode mode = RNA_enum_get(op->ptr, "mode");
463     float value = RNA_float_get(op->ptr, "value");
464
465     /* Calculations of individual vertices are done in 2D screen space to diminish the amount of
466      * calculations done. Bounding box PBVH collision is not computed against enclosing rectangle
467      * of lasso */
468     ED_view3d_viewcontext_init(C, &vc);
469
470     /* lasso data calculations */
471     data.vc = &vc;
472     ob = vc.obact;
473     ED_view3d_ob_project_mat_get(vc.rv3d, ob, data.projviewobjmat);
474
475     BLI_lasso_boundbox(&data.rect, mcords, mcords_tot);
476     data.width = data.rect.xmax - data.rect.xmin;
477     data.px = BLI_BITMAP_NEW(data.width * (data.rect.ymax - data.rect.ymin), __func__);
478
479     BLI_bitmap_draw_2d_poly_v2i_n(data.rect.xmin,
480                                   data.rect.ymin,
481                                   data.rect.xmax,
482                                   data.rect.ymax,
483                                   mcords,
484                                   mcords_tot,
485                                   mask_lasso_px_cb,
486                                   &data);
487
488     ED_view3d_clipping_calc(&bb, clip_planes, vc.ar, vc.obact, &data.rect);
489     negate_m4(clip_planes);
490
491     BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, false, true);
492     pbvh = ob->sculpt->pbvh;
493     multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);
494
495     sculpt_undo_push_begin("Mask lasso fill");
496
497     for (symmpass = 0; symmpass <= symm; ++symmpass) {
498       if ((symmpass == 0) || (symm & symmpass && (symm != 5 || symmpass != 3) &&
499                               (symm != 6 || (symmpass != 3 && symmpass != 5)))) {
500         int j = 0;
501
502         /* flip the planes symmetrically as needed */
503         for (; j < 4; j++) {
504           flip_plane(clip_planes_final[j], clip_planes[j], symmpass);
505         }
506
507         data.symmpass = symmpass;
508
509         /* gather nodes inside lasso's enclosing rectangle
510          * (should greatly help with bigger meshes) */
511         BKE_pbvh_search_gather(
512             pbvh, BKE_pbvh_node_planes_contain_AABB, clip_planes_final, &nodes, &totnode);
513
514         data.task_data.ob = ob;
515         data.task_data.pbvh = pbvh;
516         data.task_data.nodes = nodes;
517         data.task_data.multires = multires;
518         data.task_data.mode = mode;
519         data.task_data.value = value;
520
521         ParallelRangeSettings settings;
522         BLI_parallel_range_settings_defaults(&settings);
523         settings.use_threading = ((sd->flags & SCULPT_USE_OPENMP) &&
524                                   (totnode > SCULPT_THREADED_LIMIT));
525         BLI_task_parallel_range(0, totnode, &data, mask_gesture_lasso_task_cb, &settings);
526
527         if (nodes) {
528           MEM_freeN(nodes);
529         }
530       }
531     }
532
533     if (multires) {
534       multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
535     }
536
537     sculpt_undo_push_end();
538
539     ED_region_tag_redraw(vc.ar);
540     MEM_freeN((void *)mcords);
541     MEM_freeN(data.px);
542
543     WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
544
545     return OPERATOR_FINISHED;
546   }
547   return OPERATOR_PASS_THROUGH;
548 }
549
550 void PAINT_OT_mask_lasso_gesture(wmOperatorType *ot)
551 {
552   ot->name = "Mask Lasso Gesture";
553   ot->idname = "PAINT_OT_mask_lasso_gesture";
554   ot->description = "Add mask within the lasso as you move the brush";
555
556   ot->invoke = WM_gesture_lasso_invoke;
557   ot->modal = WM_gesture_lasso_modal;
558   ot->exec = paint_mask_gesture_lasso_exec;
559
560   ot->poll = sculpt_mode_poll;
561
562   ot->flag = OPTYPE_REGISTER;
563
564   /* properties */
565   WM_operator_properties_gesture_lasso(ot);
566
567   RNA_def_enum(ot->srna, "mode", mode_items, PAINT_MASK_FLOOD_VALUE, "Mode", NULL);
568   RNA_def_float(
569       ot->srna,
570       "value",
571       1.0,
572       0,
573       1.0,
574       "Value",
575       "Mask level to use when mode is 'Value'; zero means no masking and one is fully masked",
576       0,
577       1);
578 }