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