GPencil: Primitive: Polyline Tool
[blender.git] / source / blender / editors / sculpt_paint / paint_utils.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) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edsculpt
22  */
23
24 #include <math.h>
25 #include <stdlib.h>
26
27 #include "DNA_mesh_types.h"
28 #include "DNA_meshdata_types.h"
29 #include "DNA_object_types.h"
30 #include "DNA_material_types.h"
31
32 #include "DNA_scene_types.h"
33 #include "DNA_brush_types.h"
34
35 #include "BLI_math.h"
36 #include "BLI_math_color.h"
37 #include "BLI_utildefines.h"
38 #include "BLI_listbase.h"
39 #include "BLI_rect.h"
40
41 #include "BLT_translation.h"
42
43 #include "BKE_brush.h"
44 #include "BKE_context.h"
45 #include "BKE_customdata.h"
46 #include "BKE_image.h"
47 #include "BKE_material.h"
48 #include "BKE_mesh_runtime.h"
49 #include "BKE_paint.h"
50 #include "BKE_report.h"
51
52 #include "DEG_depsgraph.h"
53 #include "DEG_depsgraph_query.h"
54
55 #include "RNA_access.h"
56 #include "RNA_define.h"
57
58 #include "GPU_glew.h"
59 #include "GPU_matrix.h"
60 #include "GPU_state.h"
61
62 #include "IMB_colormanagement.h"
63 #include "IMB_imbuf_types.h"
64 #include "IMB_imbuf.h"
65
66 #include "RE_render_ext.h"
67
68 #include "ED_view3d.h"
69 #include "ED_screen.h"
70
71 #include "BLI_sys_types.h"
72 #include "ED_mesh.h" /* for face mask functions */
73
74 #include "DRW_select_buffer.h"
75
76 #include "WM_api.h"
77 #include "WM_types.h"
78
79 #include "paint_intern.h"
80
81 /* Convert the object-space axis-aligned bounding box (expressed as
82  * its minimum and maximum corners) into a screen-space rectangle,
83  * returns zero if the result is empty */
84 bool paint_convert_bb_to_rect(rcti *rect,
85                               const float bb_min[3],
86                               const float bb_max[3],
87                               const ARegion *ar,
88                               RegionView3D *rv3d,
89                               Object *ob)
90 {
91   float projection_mat[4][4];
92   int i, j, k;
93
94   BLI_rcti_init_minmax(rect);
95
96   /* return zero if the bounding box has non-positive volume */
97   if (bb_min[0] > bb_max[0] || bb_min[1] > bb_max[1] || bb_min[2] > bb_max[2]) {
98     return 0;
99   }
100
101   ED_view3d_ob_project_mat_get(rv3d, ob, projection_mat);
102
103   for (i = 0; i < 2; i++) {
104     for (j = 0; j < 2; j++) {
105       for (k = 0; k < 2; k++) {
106         float vec[3], proj[2];
107         int proj_i[2];
108         vec[0] = i ? bb_min[0] : bb_max[0];
109         vec[1] = j ? bb_min[1] : bb_max[1];
110         vec[2] = k ? bb_min[2] : bb_max[2];
111         /* convert corner to screen space */
112         ED_view3d_project_float_v2_m4(ar, vec, proj, projection_mat);
113         /* expand 2D rectangle */
114
115         /* we could project directly to int? */
116         proj_i[0] = proj[0];
117         proj_i[1] = proj[1];
118
119         BLI_rcti_do_minmax_v(rect, proj_i);
120       }
121     }
122   }
123
124   /* return false if the rectangle has non-positive area */
125   return rect->xmin < rect->xmax && rect->ymin < rect->ymax;
126 }
127
128 /* Get four planes in object-space that describe the projection of
129  * screen_rect from screen into object-space (essentially converting a
130  * 2D screens-space bounding box into four 3D planes) */
131 void paint_calc_redraw_planes(float planes[4][4],
132                               const ARegion *ar,
133                               Object *ob,
134                               const rcti *screen_rect)
135 {
136   BoundBox bb;
137   rcti rect;
138
139   /* use some extra space just in case */
140   rect = *screen_rect;
141   rect.xmin -= 2;
142   rect.xmax += 2;
143   rect.ymin -= 2;
144   rect.ymax += 2;
145
146   ED_view3d_clipping_calc(&bb, planes, ar, ob, &rect);
147 }
148
149 float paint_calc_object_space_radius(ViewContext *vc, const float center[3], float pixel_radius)
150 {
151   Object *ob = vc->obact;
152   float delta[3], scale, loc[3];
153   const float mval_f[2] = {pixel_radius, 0.0f};
154   float zfac;
155
156   mul_v3_m4v3(loc, ob->obmat, center);
157
158   zfac = ED_view3d_calc_zfac(vc->rv3d, loc, NULL);
159   ED_view3d_win_to_delta(vc->ar, mval_f, delta, zfac);
160
161   scale = fabsf(mat4_to_scale(ob->obmat));
162   scale = (scale == 0.0f) ? 1.0f : scale;
163
164   return len_v3(delta) / scale;
165 }
166
167 float paint_get_tex_pixel(const MTex *mtex, float u, float v, struct ImagePool *pool, int thread)
168 {
169   float intensity, rgba[4];
170   float co[3] = {u, v, 0.0f};
171
172   externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false);
173
174   return intensity;
175 }
176
177 void paint_get_tex_pixel_col(const MTex *mtex,
178                              float u,
179                              float v,
180                              float rgba[4],
181                              struct ImagePool *pool,
182                              int thread,
183                              bool convert_to_linear,
184                              struct ColorSpace *colorspace)
185 {
186   float co[3] = {u, v, 0.0f};
187   int hasrgb;
188   float intensity;
189
190   hasrgb = externtex(
191       mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false);
192   if (!hasrgb) {
193     rgba[0] = intensity;
194     rgba[1] = intensity;
195     rgba[2] = intensity;
196     rgba[3] = 1.0f;
197   }
198
199   if (convert_to_linear) {
200     IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, colorspace);
201   }
202
203   linearrgb_to_srgb_v3_v3(rgba, rgba);
204
205   CLAMP(rgba[0], 0.0f, 1.0f);
206   CLAMP(rgba[1], 0.0f, 1.0f);
207   CLAMP(rgba[2], 0.0f, 1.0f);
208   CLAMP(rgba[3], 0.0f, 1.0f);
209 }
210
211 void paint_stroke_operator_properties(wmOperatorType *ot)
212 {
213   static const EnumPropertyItem stroke_mode_items[] = {
214       {BRUSH_STROKE_NORMAL, "NORMAL", 0, "Regular", "Apply brush normally"},
215       {BRUSH_STROKE_INVERT,
216        "INVERT",
217        0,
218        "Invert",
219        "Invert action of brush for duration of stroke"},
220       {BRUSH_STROKE_SMOOTH,
221        "SMOOTH",
222        0,
223        "Smooth",
224        "Switch brush to smooth mode for duration of stroke"},
225       {0},
226   };
227
228   PropertyRNA *prop;
229
230   prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
231   RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
232
233   RNA_def_enum(ot->srna,
234                "mode",
235                stroke_mode_items,
236                BRUSH_STROKE_NORMAL,
237                "Stroke Mode",
238                "Action taken when a paint stroke is made");
239 }
240
241 /* 3D Paint */
242
243 static void imapaint_project(float matrix[4][4], const float co[3], float pco[4])
244 {
245   copy_v3_v3(pco, co);
246   pco[3] = 1.0f;
247
248   mul_m4_v4(matrix, pco);
249 }
250
251 static void imapaint_tri_weights(float matrix[4][4],
252                                  const GLint view[4],
253                                  const float v1[3],
254                                  const float v2[3],
255                                  const float v3[3],
256                                  const float co[2],
257                                  float w[3])
258 {
259   float pv1[4], pv2[4], pv3[4], h[3], divw;
260   float wmat[3][3], invwmat[3][3];
261
262   /* compute barycentric coordinates */
263
264   /* project the verts */
265   imapaint_project(matrix, v1, pv1);
266   imapaint_project(matrix, v2, pv2);
267   imapaint_project(matrix, v3, pv3);
268
269   /* do inverse view mapping, see gluProject man page */
270   h[0] = (co[0] - view[0]) * 2.0f / view[2] - 1.0f;
271   h[1] = (co[1] - view[1]) * 2.0f / view[3] - 1.0f;
272   h[2] = 1.0f;
273
274   /* solve for (w1,w2,w3)/perspdiv in:
275    * h * perspdiv = Project * Model * (w1 * v1 + w2 * v2 + w3 * v3) */
276
277   wmat[0][0] = pv1[0];
278   wmat[1][0] = pv2[0];
279   wmat[2][0] = pv3[0];
280   wmat[0][1] = pv1[1];
281   wmat[1][1] = pv2[1];
282   wmat[2][1] = pv3[1];
283   wmat[0][2] = pv1[3];
284   wmat[1][2] = pv2[3];
285   wmat[2][2] = pv3[3];
286
287   invert_m3_m3(invwmat, wmat);
288   mul_m3_v3(invwmat, h);
289
290   copy_v3_v3(w, h);
291
292   /* w is still divided by perspdiv, make it sum to one */
293   divw = w[0] + w[1] + w[2];
294   if (divw != 0.0f) {
295     mul_v3_fl(w, 1.0f / divw);
296   }
297 }
298
299 /* compute uv coordinates of mouse in face */
300 static void imapaint_pick_uv(Mesh *me_eval,
301                              Scene *scene,
302                              Object *ob_eval,
303                              unsigned int faceindex,
304                              const int xy[2],
305                              float uv[2])
306 {
307   int i, findex;
308   float p[2], w[3], absw, minabsw;
309   float matrix[4][4], proj[4][4];
310   GLint view[4];
311   const eImagePaintMode mode = scene->toolsettings->imapaint.mode;
312
313   const MLoopTri *lt = BKE_mesh_runtime_looptri_ensure(me_eval);
314   const int tottri = me_eval->runtime.looptris.len;
315
316   const MVert *mvert = me_eval->mvert;
317   const MPoly *mpoly = me_eval->mpoly;
318   const MLoop *mloop = me_eval->mloop;
319   const int *index_mp_to_orig = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX);
320
321   /* get the needed opengl matrices */
322   GPU_viewport_size_get_i(view);
323   GPU_matrix_model_view_get(matrix);
324   GPU_matrix_projection_get(proj);
325   view[0] = view[1] = 0;
326   mul_m4_m4m4(matrix, matrix, ob_eval->obmat);
327   mul_m4_m4m4(matrix, proj, matrix);
328
329   minabsw = 1e10;
330   uv[0] = uv[1] = 0.0;
331
332   /* test all faces in the derivedmesh with the original index of the picked face */
333   /* face means poly here, not triangle, indeed */
334   for (i = 0; i < tottri; i++, lt++) {
335     findex = index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
336
337     if (findex == faceindex) {
338       const MLoopUV *mloopuv;
339       const MPoly *mp = &mpoly[lt->poly];
340       const MLoopUV *tri_uv[3];
341       float tri_co[3][3];
342
343       for (int j = 3; j--;) {
344         copy_v3_v3(tri_co[j], mvert[mloop[lt->tri[j]].v].co);
345       }
346
347       if (mode == IMAGEPAINT_MODE_MATERIAL) {
348         const Material *ma;
349         const TexPaintSlot *slot;
350
351         ma = give_current_material(ob_eval, mp->mat_nr + 1);
352         slot = &ma->texpaintslot[ma->paint_active_slot];
353
354         if (!(slot && slot->uvname &&
355               (mloopuv = CustomData_get_layer_named(&me_eval->ldata, CD_MLOOPUV, slot->uvname)))) {
356           mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV);
357         }
358       }
359       else {
360         mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV);
361       }
362
363       tri_uv[0] = &mloopuv[lt->tri[0]];
364       tri_uv[1] = &mloopuv[lt->tri[1]];
365       tri_uv[2] = &mloopuv[lt->tri[2]];
366
367       p[0] = xy[0];
368       p[1] = xy[1];
369
370       imapaint_tri_weights(matrix, view, UNPACK3(tri_co), p, w);
371       absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
372       if (absw < minabsw) {
373         uv[0] = tri_uv[0]->uv[0] * w[0] + tri_uv[1]->uv[0] * w[1] + tri_uv[2]->uv[0] * w[2];
374         uv[1] = tri_uv[0]->uv[1] * w[0] + tri_uv[1]->uv[1] * w[1] + tri_uv[2]->uv[1] * w[2];
375         minabsw = absw;
376       }
377     }
378   }
379 }
380
381 /* returns 0 if not found, otherwise 1 */
382 static int imapaint_pick_face(ViewContext *vc,
383                               const int mval[2],
384                               unsigned int *r_index,
385                               unsigned int totpoly)
386 {
387   if (totpoly == 0) {
388     return 0;
389   }
390
391   /* sample only on the exact position */
392   ED_view3d_select_id_validate(vc);
393   *r_index = DRW_select_buffer_sample_point(vc->depsgraph, vc->ar, vc->v3d, mval);
394
395   if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) {
396     return 0;
397   }
398
399   (*r_index)--;
400
401   return 1;
402 }
403
404 static Image *imapaint_face_image(Object *ob, Mesh *me, int face_index)
405 {
406   Image *ima;
407   MPoly *mp = me->mpoly + face_index;
408   Material *ma = give_current_material(ob, mp->mat_nr + 1);
409   ima = ma && ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
410
411   return ima;
412 }
413
414 /* Uses symm to selectively flip any axis of a coordinate. */
415 void flip_v3_v3(float out[3], const float in[3], const char symm)
416 {
417   if (symm & PAINT_SYMM_X) {
418     out[0] = -in[0];
419   }
420   else {
421     out[0] = in[0];
422   }
423   if (symm & PAINT_SYMM_Y) {
424     out[1] = -in[1];
425   }
426   else {
427     out[1] = in[1];
428   }
429   if (symm & PAINT_SYMM_Z) {
430     out[2] = -in[2];
431   }
432   else {
433     out[2] = in[2];
434   }
435 }
436
437 void flip_qt_qt(float out[4], const float in[4], const char symm)
438 {
439   float axis[3], angle;
440
441   quat_to_axis_angle(axis, &angle, in);
442   normalize_v3(axis);
443
444   if (symm & PAINT_SYMM_X) {
445     axis[0] *= -1.0f;
446     angle *= -1.0f;
447   }
448   if (symm & PAINT_SYMM_Y) {
449     axis[1] *= -1.0f;
450     angle *= -1.0f;
451   }
452   if (symm & PAINT_SYMM_Z) {
453     axis[2] *= -1.0f;
454     angle *= -1.0f;
455   }
456
457   axis_angle_normalized_to_quat(out, axis, angle);
458 }
459
460 /* used for both 3d view and image window */
461 void paint_sample_color(
462     bContext *C, ARegion *ar, int x, int y, bool texpaint_proj, bool use_palette)
463 {
464   Scene *scene = CTX_data_scene(C);
465   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
466   Paint *paint = BKE_paint_get_active_from_context(C);
467   Palette *palette = BKE_paint_palette(paint);
468   PaletteColor *color = NULL;
469   Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
470   unsigned int col;
471   const unsigned char *cp;
472
473   CLAMP(x, 0, ar->winx);
474   CLAMP(y, 0, ar->winy);
475
476   if (use_palette) {
477     if (!palette) {
478       palette = BKE_palette_add(CTX_data_main(C), "Palette");
479       BKE_paint_palette_set(paint, palette);
480     }
481
482     color = BKE_palette_color_add(palette);
483     palette->active_color = BLI_listbase_count(&palette->colors) - 1;
484   }
485
486   if (CTX_wm_view3d(C) && texpaint_proj) {
487     /* first try getting a color directly from the mesh faces if possible */
488     ViewLayer *view_layer = CTX_data_view_layer(C);
489     Object *ob = OBACT(view_layer);
490     Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
491     bool sample_success = false;
492     ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
493     bool use_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
494
495     if (ob) {
496       CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
497       cddata_masks.pmask |= CD_MASK_ORIGINDEX;
498       Mesh *me = (Mesh *)ob->data;
499       Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob_eval, &cddata_masks);
500
501       ViewContext vc;
502       const int mval[2] = {x, y};
503       unsigned int faceindex;
504       unsigned int totpoly = me->totpoly;
505
506       if (CustomData_has_layer(&me_eval->ldata, CD_MLOOPUV)) {
507         ED_view3d_viewcontext_init(C, &vc, depsgraph);
508
509         view3d_operator_needs_opengl(C);
510
511         if (imapaint_pick_face(&vc, mval, &faceindex, totpoly)) {
512           Image *image;
513
514           if (use_material) {
515             image = imapaint_face_image(ob_eval, me_eval, faceindex);
516           }
517           else {
518             image = imapaint->canvas;
519           }
520
521           if (image) {
522             ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
523             if (ibuf && ibuf->rect) {
524               float uv[2];
525               float u, v;
526               imapaint_pick_uv(me_eval, scene, ob_eval, faceindex, mval, uv);
527               sample_success = true;
528
529               u = fmodf(uv[0], 1.0f);
530               v = fmodf(uv[1], 1.0f);
531
532               if (u < 0.0f) {
533                 u += 1.0f;
534               }
535               if (v < 0.0f) {
536                 v += 1.0f;
537               }
538
539               u = u * ibuf->x;
540               v = v * ibuf->y;
541
542               if (ibuf->rect_float) {
543                 float rgba_f[4];
544                 bilinear_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
545                 straight_to_premul_v4(rgba_f);
546                 if (use_palette) {
547                   linearrgb_to_srgb_v3_v3(color->rgb, rgba_f);
548                 }
549                 else {
550                   linearrgb_to_srgb_v3_v3(rgba_f, rgba_f);
551                   BKE_brush_color_set(scene, br, rgba_f);
552                 }
553               }
554               else {
555                 unsigned char rgba[4];
556                 bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
557                 if (use_palette) {
558                   rgb_uchar_to_float(color->rgb, rgba);
559                 }
560                 else {
561                   float rgba_f[3];
562                   rgb_uchar_to_float(rgba_f, rgba);
563                   BKE_brush_color_set(scene, br, rgba_f);
564                 }
565               }
566             }
567
568             BKE_image_release_ibuf(image, ibuf, NULL);
569           }
570         }
571       }
572     }
573
574     if (!sample_success) {
575       glReadBuffer(GL_FRONT);
576       glReadPixels(
577           x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
578       glReadBuffer(GL_BACK);
579     }
580     else {
581       return;
582     }
583   }
584   else {
585     glReadBuffer(GL_FRONT);
586     glReadPixels(x + ar->winrct.xmin, y + ar->winrct.ymin, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
587     glReadBuffer(GL_BACK);
588   }
589   cp = (unsigned char *)&col;
590
591   if (use_palette) {
592     rgb_uchar_to_float(color->rgb, cp);
593   }
594   else {
595     float rgba_f[3];
596     rgb_uchar_to_float(rgba_f, cp);
597     BKE_brush_color_set(scene, br, rgba_f);
598   }
599 }
600
601 static int brush_curve_preset_exec(bContext *C, wmOperator *op)
602 {
603   Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
604
605   if (br) {
606     Scene *scene = CTX_data_scene(C);
607     ViewLayer *view_layer = CTX_data_view_layer(C);
608     BKE_brush_curve_preset(br, RNA_enum_get(op->ptr, "shape"));
609     BKE_paint_invalidate_cursor_overlay(scene, view_layer, br->curve);
610   }
611
612   return OPERATOR_FINISHED;
613 }
614
615 static bool brush_curve_preset_poll(bContext *C)
616 {
617   Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
618
619   return br && br->curve;
620 }
621
622 void BRUSH_OT_curve_preset(wmOperatorType *ot)
623 {
624   PropertyRNA *prop;
625   static const EnumPropertyItem prop_shape_items[] = {
626       {CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""},
627       {CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""},
628       {CURVE_PRESET_MAX, "MAX", 0, "Max", ""},
629       {CURVE_PRESET_LINE, "LINE", 0, "Line", ""},
630       {CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""},
631       {CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""},
632       {0, NULL, 0, NULL, NULL},
633   };
634
635   ot->name = "Preset";
636   ot->description = "Set brush shape";
637   ot->idname = "BRUSH_OT_curve_preset";
638
639   ot->exec = brush_curve_preset_exec;
640   ot->poll = brush_curve_preset_poll;
641
642   prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
643   RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
644 }
645
646 /* face-select ops */
647 static int paint_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
648 {
649   paintface_select_linked(C, CTX_data_active_object(C), NULL, true);
650   ED_region_tag_redraw(CTX_wm_region(C));
651   return OPERATOR_FINISHED;
652 }
653
654 void PAINT_OT_face_select_linked(wmOperatorType *ot)
655 {
656   ot->name = "Select Linked";
657   ot->description = "Select linked faces";
658   ot->idname = "PAINT_OT_face_select_linked";
659
660   ot->exec = paint_select_linked_exec;
661   ot->poll = facemask_paint_poll;
662
663   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
664 }
665
666 static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
667 {
668   const bool select = !RNA_boolean_get(op->ptr, "deselect");
669   view3d_operator_needs_opengl(C);
670   paintface_select_linked(C, CTX_data_active_object(C), event->mval, select);
671   ED_region_tag_redraw(CTX_wm_region(C));
672   return OPERATOR_FINISHED;
673 }
674
675 void PAINT_OT_face_select_linked_pick(wmOperatorType *ot)
676 {
677   ot->name = "Select Linked Pick";
678   ot->description = "Select linked faces under the cursor";
679   ot->idname = "PAINT_OT_face_select_linked_pick";
680
681   ot->invoke = paint_select_linked_pick_invoke;
682   ot->poll = facemask_paint_poll;
683
684   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
685
686   RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect rather than select items");
687 }
688
689 static int face_select_all_exec(bContext *C, wmOperator *op)
690 {
691   Object *ob = CTX_data_active_object(C);
692   if (paintface_deselect_all_visible(C, ob, RNA_enum_get(op->ptr, "action"), true)) {
693     ED_region_tag_redraw(CTX_wm_region(C));
694     return OPERATOR_FINISHED;
695   }
696   return OPERATOR_CANCELLED;
697 }
698
699 void PAINT_OT_face_select_all(wmOperatorType *ot)
700 {
701   ot->name = "(De)select All";
702   ot->description = "Change selection for all faces";
703   ot->idname = "PAINT_OT_face_select_all";
704
705   ot->exec = face_select_all_exec;
706   ot->poll = facemask_paint_poll;
707
708   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
709
710   WM_operator_properties_select_all(ot);
711 }
712
713 static int vert_select_all_exec(bContext *C, wmOperator *op)
714 {
715   Object *ob = CTX_data_active_object(C);
716   paintvert_deselect_all_visible(ob, RNA_enum_get(op->ptr, "action"), true);
717   paintvert_tag_select_update(C, ob);
718   ED_region_tag_redraw(CTX_wm_region(C));
719   return OPERATOR_FINISHED;
720 }
721
722 void PAINT_OT_vert_select_all(wmOperatorType *ot)
723 {
724   ot->name = "(De)select All";
725   ot->description = "Change selection for all vertices";
726   ot->idname = "PAINT_OT_vert_select_all";
727
728   ot->exec = vert_select_all_exec;
729   ot->poll = vert_paint_poll;
730
731   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
732
733   WM_operator_properties_select_all(ot);
734 }
735
736 static int vert_select_ungrouped_exec(bContext *C, wmOperator *op)
737 {
738   Object *ob = CTX_data_active_object(C);
739   Mesh *me = ob->data;
740
741   if (BLI_listbase_is_empty(&ob->defbase) || (me->dvert == NULL)) {
742     BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object");
743     return OPERATOR_CANCELLED;
744   }
745
746   paintvert_select_ungrouped(ob, RNA_boolean_get(op->ptr, "extend"), true);
747   paintvert_tag_select_update(C, ob);
748   ED_region_tag_redraw(CTX_wm_region(C));
749   return OPERATOR_FINISHED;
750 }
751
752 void PAINT_OT_vert_select_ungrouped(wmOperatorType *ot)
753 {
754   /* identifiers */
755   ot->name = "Select Ungrouped";
756   ot->idname = "PAINT_OT_vert_select_ungrouped";
757   ot->description = "Select vertices without a group";
758
759   /* api callbacks */
760   ot->exec = vert_select_ungrouped_exec;
761   ot->poll = vert_paint_poll;
762
763   /* flags */
764   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
765
766   RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
767 }
768
769 static int face_select_hide_exec(bContext *C, wmOperator *op)
770 {
771   const bool unselected = RNA_boolean_get(op->ptr, "unselected");
772   Object *ob = CTX_data_active_object(C);
773   paintface_hide(C, ob, unselected);
774   ED_region_tag_redraw(CTX_wm_region(C));
775   return OPERATOR_FINISHED;
776 }
777
778 void PAINT_OT_face_select_hide(wmOperatorType *ot)
779 {
780   ot->name = "Face Select Hide";
781   ot->description = "Hide selected faces";
782   ot->idname = "PAINT_OT_face_select_hide";
783
784   ot->exec = face_select_hide_exec;
785   ot->poll = facemask_paint_poll;
786
787   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
788
789   RNA_def_boolean(
790       ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
791 }
792
793 static int face_select_reveal_exec(bContext *C, wmOperator *op)
794 {
795   const bool select = RNA_boolean_get(op->ptr, "select");
796   Object *ob = CTX_data_active_object(C);
797   paintface_reveal(C, ob, select);
798   ED_region_tag_redraw(CTX_wm_region(C));
799   return OPERATOR_FINISHED;
800 }
801
802 void PAINT_OT_face_select_reveal(wmOperatorType *ot)
803 {
804   ot->name = "Face Select Reveal";
805   ot->description = "Reveal hidden faces";
806   ot->idname = "PAINT_OT_face_select_reveal";
807
808   ot->exec = face_select_reveal_exec;
809   ot->poll = facemask_paint_poll;
810
811   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
812
813   RNA_def_boolean(ot->srna, "select", true, "Select", "");
814 }