Bevel mod: cleanup flags and extra data.
[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_object.h"
50 #include "BKE_paint.h"
51 #include "BKE_report.h"
52
53 #include "DEG_depsgraph.h"
54 #include "DEG_depsgraph_query.h"
55
56 #include "RNA_access.h"
57 #include "RNA_define.h"
58
59 #include "GPU_glew.h"
60 #include "GPU_matrix.h"
61 #include "GPU_state.h"
62
63 #include "IMB_colormanagement.h"
64 #include "IMB_imbuf_types.h"
65 #include "IMB_imbuf.h"
66
67 #include "RE_render_ext.h"
68
69 #include "ED_view3d.h"
70 #include "ED_screen.h"
71
72 #include "BLI_sys_types.h"
73 #include "ED_mesh.h" /* for face mask functions */
74
75 #include "WM_api.h"
76 #include "WM_types.h"
77
78 #include "paint_intern.h"
79
80 /* Convert the object-space axis-aligned bounding box (expressed as
81  * its minimum and maximum corners) into a screen-space rectangle,
82  * returns zero if the result is empty */
83 bool paint_convert_bb_to_rect(
84         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         ED_view3d_ob_project_mat_get(rv3d, ob, projection_mat);
101
102         for (i = 0; i < 2; ++i) {
103                 for (j = 0; j < 2; ++j) {
104                         for (k = 0; k < 2; ++k) {
105                                 float vec[3], proj[2];
106                                 int proj_i[2];
107                                 vec[0] = i ? bb_min[0] : bb_max[0];
108                                 vec[1] = j ? bb_min[1] : bb_max[1];
109                                 vec[2] = k ? bb_min[2] : bb_max[2];
110                                 /* convert corner to screen space */
111                                 ED_view3d_project_float_v2_m4(ar, vec, proj, projection_mat);
112                                 /* expand 2D rectangle */
113
114                                 /* we could project directly to int? */
115                                 proj_i[0] = proj[0];
116                                 proj_i[1] = proj[1];
117
118                                 BLI_rcti_do_minmax_v(rect, proj_i);
119                         }
120                 }
121         }
122
123         /* return false if the rectangle has non-positive area */
124         return rect->xmin < rect->xmax && rect->ymin < rect->ymax;
125 }
126
127 /* Get four planes in object-space that describe the projection of
128  * screen_rect from screen into object-space (essentially converting a
129  * 2D screens-space bounding box into four 3D planes) */
130 void paint_calc_redraw_planes(
131         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         negate_m4(planes);
148 }
149
150 float paint_calc_object_space_radius(
151         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(const 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(
182         const MTex *mtex, float u, float v, float rgba[4], struct ImagePool *pool,
183         int thread, bool convert_to_linear, struct ColorSpace *colorspace)
184 {
185         float co[3] = {u, v, 0.0f};
186         int hasrgb;
187         float intensity;
188
189         hasrgb = externtex(mtex, co, &intensity,
190                            rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false);
191         if (!hasrgb) {
192                 rgba[0] = intensity;
193                 rgba[1] = intensity;
194                 rgba[2] = intensity;
195                 rgba[3] = 1.0f;
196         }
197
198         if (convert_to_linear)
199                 IMB_colormanagement_colorspace_to_scene_linear_v3(rgba, colorspace);
200
201         linearrgb_to_srgb_v3_v3(rgba, rgba);
202
203         CLAMP(rgba[0], 0.0f, 1.0f);
204         CLAMP(rgba[1], 0.0f, 1.0f);
205         CLAMP(rgba[2], 0.0f, 1.0f);
206         CLAMP(rgba[3], 0.0f, 1.0f);
207 }
208
209 void paint_stroke_operator_properties(wmOperatorType *ot)
210 {
211         static const EnumPropertyItem stroke_mode_items[] = {
212                 {BRUSH_STROKE_NORMAL, "NORMAL", 0, "Regular", "Apply brush normally"},
213                 {BRUSH_STROKE_INVERT, "INVERT", 0, "Invert", "Invert action of brush for duration of stroke"},
214                 {BRUSH_STROKE_SMOOTH, "SMOOTH", 0, "Smooth", "Switch brush to smooth mode for duration of stroke"},
215                 {0},
216         };
217
218         PropertyRNA *prop;
219
220         prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
221         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
222
223         RNA_def_enum(ot->srna, "mode", stroke_mode_items, BRUSH_STROKE_NORMAL,
224                      "Stroke Mode",
225                      "Action taken when a paint stroke is made");
226
227 }
228
229 /* 3D Paint */
230
231 static void imapaint_project(float matrix[4][4], const float co[3], float pco[4])
232 {
233         copy_v3_v3(pco, co);
234         pco[3] = 1.0f;
235
236         mul_m4_v4(matrix, pco);
237 }
238
239 static void imapaint_tri_weights(
240         float matrix[4][4], GLint view[4],
241         const float v1[3], const float v2[3], const float v3[3],
242         const float co[2], float w[3])
243 {
244         float pv1[4], pv2[4], pv3[4], h[3], divw;
245         float wmat[3][3], invwmat[3][3];
246
247         /* compute barycentric coordinates */
248
249         /* project the verts */
250         imapaint_project(matrix, v1, pv1);
251         imapaint_project(matrix, v2, pv2);
252         imapaint_project(matrix, v3, pv3);
253
254         /* do inverse view mapping, see gluProject man page */
255         h[0] = (co[0] - view[0]) * 2.0f / view[2] - 1.0f;
256         h[1] = (co[1] - view[1]) * 2.0f / view[3] - 1.0f;
257         h[2] = 1.0f;
258
259         /* solve for (w1,w2,w3)/perspdiv in:
260          * h * perspdiv = Project * Model * (w1 * v1 + w2 * v2 + w3 * v3) */
261
262         wmat[0][0] = pv1[0];  wmat[1][0] = pv2[0];  wmat[2][0] = pv3[0];
263         wmat[0][1] = pv1[1];  wmat[1][1] = pv2[1];  wmat[2][1] = pv3[1];
264         wmat[0][2] = pv1[3];  wmat[1][2] = pv2[3];  wmat[2][2] = pv3[3];
265
266         invert_m3_m3(invwmat, wmat);
267         mul_m3_v3(invwmat, h);
268
269         copy_v3_v3(w, h);
270
271         /* w is still divided by perspdiv, make it sum to one */
272         divw = w[0] + w[1] + w[2];
273         if (divw != 0.0f) {
274                 mul_v3_fl(w, 1.0f / divw);
275         }
276 }
277
278 /* compute uv coordinates of mouse in face */
279 static void imapaint_pick_uv(Mesh *me_eval, Scene *scene, Object *ob_eval, unsigned int faceindex, const int xy[2], float uv[2])
280 {
281         int i, findex;
282         float p[2], w[3], absw, minabsw;
283         float matrix[4][4], proj[4][4];
284         GLint view[4];
285         const eImagePaintMode mode = scene->toolsettings->imapaint.mode;
286
287         const MLoopTri *lt = BKE_mesh_runtime_looptri_ensure(me_eval);
288         const int tottri = me_eval->runtime.looptris.len;
289
290         const MVert *mvert = me_eval->mvert;
291         const MPoly *mpoly = me_eval->mpoly;
292         const MLoop *mloop = me_eval->mloop;
293         const int *index_mp_to_orig  = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX);
294
295         /* get the needed opengl matrices */
296         GPU_viewport_size_get_i(view);
297         GPU_matrix_model_view_get(matrix);
298         GPU_matrix_projection_get(proj);
299         view[0] = view[1] = 0;
300         mul_m4_m4m4(matrix, matrix, ob_eval->obmat);
301         mul_m4_m4m4(matrix, proj, matrix);
302
303         minabsw = 1e10;
304         uv[0] = uv[1] = 0.0;
305
306         /* test all faces in the derivedmesh with the original index of the picked face */
307         /* face means poly here, not triangle, indeed */
308         for (i = 0; i < tottri; i++, lt++) {
309                 findex = index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
310
311                 if (findex == faceindex) {
312                         const MLoopUV *mloopuv;
313                         const MPoly *mp = &mpoly[lt->poly];
314                         const MLoopUV *tri_uv[3];
315                         float  tri_co[3][3];
316
317                         for (int j = 3; j--; ) {
318                                 copy_v3_v3(tri_co[j], mvert[mloop[lt->tri[j]].v].co);
319                         }
320
321                         if (mode == IMAGEPAINT_MODE_MATERIAL) {
322                                 const Material *ma;
323                                 const TexPaintSlot *slot;
324
325                                 ma = give_current_material(ob_eval, mp->mat_nr + 1);
326                                 slot = &ma->texpaintslot[ma->paint_active_slot];
327
328                                 if (!(slot && slot->uvname &&
329                                       (mloopuv = CustomData_get_layer_named(&me_eval->ldata, CD_MLOOPUV, slot->uvname))))
330                                 {
331                                         mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV);
332                                 }
333                         }
334                         else {
335                                 mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV);
336                         }
337
338                         tri_uv[0] = &mloopuv[lt->tri[0]];
339                         tri_uv[1] = &mloopuv[lt->tri[1]];
340                         tri_uv[2] = &mloopuv[lt->tri[2]];
341
342                         p[0] = xy[0];
343                         p[1] = xy[1];
344
345                         imapaint_tri_weights(matrix, view, UNPACK3(tri_co), p, w);
346                         absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
347                         if (absw < minabsw) {
348                                 uv[0] = tri_uv[0]->uv[0] * w[0] + tri_uv[1]->uv[0] * w[1] + tri_uv[2]->uv[0] * w[2];
349                                 uv[1] = tri_uv[0]->uv[1] * w[0] + tri_uv[1]->uv[1] * w[1] + tri_uv[2]->uv[1] * w[2];
350                                 minabsw = absw;
351                         }
352                 }
353         }
354 }
355
356 /* returns 0 if not found, otherwise 1 */
357 static int imapaint_pick_face(
358         ViewContext *vc, const int mval[2],
359         unsigned int *r_index, unsigned int totpoly)
360 {
361         if (totpoly == 0)
362                 return 0;
363
364         /* sample only on the exact position */
365         *r_index = ED_view3d_backbuf_sample(vc, mval[0], mval[1]);
366
367         if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) {
368                 return 0;
369         }
370
371         (*r_index)--;
372
373         return 1;
374 }
375
376
377 static Image *imapaint_face_image(Object *ob, Mesh *me, int face_index)
378 {
379         Image *ima;
380         MPoly *mp = me->mpoly + face_index;
381         Material *ma = give_current_material(ob, mp->mat_nr + 1);
382         ima = ma && ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
383
384         return ima;
385 }
386
387 /* Uses symm to selectively flip any axis of a coordinate. */
388 void flip_v3_v3(float out[3], const float in[3], const char symm)
389 {
390         if (symm & PAINT_SYMM_X)
391                 out[0] = -in[0];
392         else
393                 out[0] = in[0];
394         if (symm & PAINT_SYMM_Y)
395                 out[1] = -in[1];
396         else
397                 out[1] = in[1];
398         if (symm & PAINT_SYMM_Z)
399                 out[2] = -in[2];
400         else
401                 out[2] = in[2];
402 }
403
404 void flip_qt_qt(float out[4], const float in[4], const char symm)
405 {
406         float axis[3], angle;
407
408         quat_to_axis_angle(axis, &angle, in);
409         normalize_v3(axis);
410
411         if (symm & PAINT_SYMM_X) {
412                 axis[0] *= -1.0f;
413                 angle *= -1.0f;
414         }
415         if (symm & PAINT_SYMM_Y) {
416                 axis[1] *= -1.0f;
417                 angle *= -1.0f;
418         }
419         if (symm & PAINT_SYMM_Z) {
420                 axis[2] *= -1.0f;
421                 angle *= -1.0f;
422         }
423
424         axis_angle_normalized_to_quat(out, axis, angle);
425 }
426
427 /* used for both 3d view and image window */
428 void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_proj, bool use_palette)
429 {
430         Scene *scene = CTX_data_scene(C);
431         Depsgraph *depsgraph = CTX_data_depsgraph(C);
432         Paint *paint = BKE_paint_get_active_from_context(C);
433         Palette *palette = BKE_paint_palette(paint);
434         PaletteColor *color = NULL;
435         Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
436         unsigned int col;
437         const unsigned char *cp;
438
439         CLAMP(x, 0, ar->winx);
440         CLAMP(y, 0, ar->winy);
441
442         if (use_palette) {
443                 if (!palette) {
444                         palette = BKE_palette_add(CTX_data_main(C), "Palette");
445                         BKE_paint_palette_set(paint, palette);
446                 }
447
448                 color = BKE_palette_color_add(palette);
449                 palette->active_color = BLI_listbase_count(&palette->colors) - 1;
450         }
451
452
453         if (CTX_wm_view3d(C) && texpaint_proj) {
454                 /* first try getting a colour directly from the mesh faces if possible */
455                 ViewLayer *view_layer = CTX_data_view_layer(C);
456                 Object *ob = OBACT(view_layer);
457                 Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
458                 bool sample_success = false;
459                 ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
460                 bool use_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
461
462                 if (ob) {
463                         Mesh *me = (Mesh *)ob->data;
464                         Mesh *me_eval = ob_eval->runtime.mesh_eval;
465
466                         ViewContext vc;
467                         const int mval[2] = {x, y};
468                         unsigned int faceindex;
469                         unsigned int totpoly = me->totpoly;
470
471                         if (CustomData_has_layer(&me_eval->ldata, CD_MLOOPUV)) {
472                                 ED_view3d_viewcontext_init(C, &vc);
473
474                                 view3d_operator_needs_opengl(C);
475
476                                 if (imapaint_pick_face(&vc, mval, &faceindex, totpoly)) {
477                                         Image *image;
478
479                                         if (use_material)
480                                                 image = imapaint_face_image(ob_eval, me_eval, faceindex);
481                                         else
482                                                 image = imapaint->canvas;
483
484                                         if (image) {
485                                                 ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL);
486                                                 if (ibuf && ibuf->rect) {
487                                                         float uv[2];
488                                                         float u, v;
489                                                         imapaint_pick_uv(me_eval, scene, ob_eval, faceindex, mval, uv);
490                                                         sample_success = true;
491
492                                                         u = fmodf(uv[0], 1.0f);
493                                                         v = fmodf(uv[1], 1.0f);
494
495                                                         if (u < 0.0f) u += 1.0f;
496                                                         if (v < 0.0f) v += 1.0f;
497
498                                                         u = u * ibuf->x;
499                                                         v = v * ibuf->y;
500
501                                                         if (ibuf->rect_float) {
502                                                                 float rgba_f[4];
503                                                                 bilinear_interpolation_color_wrap(ibuf, NULL, rgba_f, u, v);
504                                                                 straight_to_premul_v4(rgba_f);
505                                                                 if (use_palette) {
506                                                                         linearrgb_to_srgb_v3_v3(color->rgb, rgba_f);
507                                                                 }
508                                                                 else {
509                                                                         linearrgb_to_srgb_v3_v3(rgba_f, rgba_f);
510                                                                         BKE_brush_color_set(scene, br, rgba_f);
511                                                                 }
512                                                         }
513                                                         else {
514                                                                 unsigned char rgba[4];
515                                                                 bilinear_interpolation_color_wrap(ibuf, rgba, NULL, u, v);
516                                                                 if (use_palette) {
517                                                                         rgb_uchar_to_float(color->rgb, rgba);
518                                                                 }
519                                                                 else {
520                                                                         float rgba_f[3];
521                                                                         rgb_uchar_to_float(rgba_f, rgba);
522                                                                         BKE_brush_color_set(scene, br, rgba_f);
523                                                                 }
524                                                         }
525                                                 }
526
527                                                 BKE_image_release_ibuf(image, ibuf, NULL);
528                                         }
529                                 }
530                         }
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                 ViewLayer *view_layer = CTX_data_view_layer(C);
565                 BKE_brush_curve_preset(br, RNA_enum_get(op->ptr, "shape"));
566                 BKE_paint_invalidate_cursor_overlay(scene, view_layer, br->curve);
567         }
568
569         return OPERATOR_FINISHED;
570 }
571
572 static bool 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 const 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
592         ot->name = "Preset";
593         ot->description = "Set brush shape";
594         ot->idname = "BRUSH_OT_curve_preset";
595
596         ot->exec = brush_curve_preset_exec;
597         ot->poll = brush_curve_preset_poll;
598
599         prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
600         RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
601 }
602
603
604 /* face-select ops */
605 static int paint_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
606 {
607         paintface_select_linked(C, CTX_data_active_object(C), NULL, true);
608         ED_region_tag_redraw(CTX_wm_region(C));
609         return OPERATOR_FINISHED;
610 }
611
612 void PAINT_OT_face_select_linked(wmOperatorType *ot)
613 {
614         ot->name = "Select Linked";
615         ot->description = "Select linked faces";
616         ot->idname = "PAINT_OT_face_select_linked";
617
618         ot->exec = paint_select_linked_exec;
619         ot->poll = facemask_paint_poll;
620
621         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
622 }
623
624 static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
625 {
626         const bool select = !RNA_boolean_get(op->ptr, "deselect");
627         view3d_operator_needs_opengl(C);
628         paintface_select_linked(C, CTX_data_active_object(C), event->mval, select);
629         ED_region_tag_redraw(CTX_wm_region(C));
630         return OPERATOR_FINISHED;
631 }
632
633 void PAINT_OT_face_select_linked_pick(wmOperatorType *ot)
634 {
635         ot->name = "Select Linked Pick";
636         ot->description = "Select linked faces under the cursor";
637         ot->idname = "PAINT_OT_face_select_linked_pick";
638
639         ot->invoke = paint_select_linked_pick_invoke;
640         ot->poll = facemask_paint_poll;
641
642         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
643
644         RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect rather than select items");
645 }
646
647
648 static int face_select_all_exec(bContext *C, wmOperator *op)
649 {
650         Object *ob = CTX_data_active_object(C);
651         paintface_deselect_all_visible(C, ob, RNA_enum_get(op->ptr, "action"), true);
652         ED_region_tag_redraw(CTX_wm_region(C));
653         return OPERATOR_FINISHED;
654 }
655
656
657 void PAINT_OT_face_select_all(wmOperatorType *ot)
658 {
659         ot->name = "(De)select All";
660         ot->description = "Change selection for all faces";
661         ot->idname = "PAINT_OT_face_select_all";
662
663         ot->exec = face_select_all_exec;
664         ot->poll = facemask_paint_poll;
665
666         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
667
668         WM_operator_properties_select_all(ot);
669 }
670
671
672 static int vert_select_all_exec(bContext *C, wmOperator *op)
673 {
674         Object *ob = CTX_data_active_object(C);
675         paintvert_deselect_all_visible(ob, RNA_enum_get(op->ptr, "action"), true);
676         paintvert_tag_select_update(C, ob);
677         ED_region_tag_redraw(CTX_wm_region(C));
678         return OPERATOR_FINISHED;
679 }
680
681
682 void PAINT_OT_vert_select_all(wmOperatorType *ot)
683 {
684         ot->name = "(De)select All";
685         ot->description = "Change selection for all vertices";
686         ot->idname = "PAINT_OT_vert_select_all";
687
688         ot->exec = vert_select_all_exec;
689         ot->poll = vert_paint_poll;
690
691         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
692
693         WM_operator_properties_select_all(ot);
694 }
695
696
697 static int vert_select_ungrouped_exec(bContext *C, wmOperator *op)
698 {
699         Object *ob = CTX_data_active_object(C);
700         Mesh *me = ob->data;
701
702         if (BLI_listbase_is_empty(&ob->defbase) || (me->dvert == NULL)) {
703                 BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object");
704                 return OPERATOR_CANCELLED;
705         }
706
707         paintvert_select_ungrouped(ob, RNA_boolean_get(op->ptr, "extend"), true);
708         paintvert_tag_select_update(C, ob);
709         ED_region_tag_redraw(CTX_wm_region(C));
710         return OPERATOR_FINISHED;
711 }
712
713 void PAINT_OT_vert_select_ungrouped(wmOperatorType *ot)
714 {
715         /* identifiers */
716         ot->name = "Select Ungrouped";
717         ot->idname = "PAINT_OT_vert_select_ungrouped";
718         ot->description = "Select vertices without a group";
719
720         /* api callbacks */
721         ot->exec = vert_select_ungrouped_exec;
722         ot->poll = vert_paint_poll;
723
724         /* flags */
725         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
726
727         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
728 }
729
730 static int face_select_hide_exec(bContext *C, wmOperator *op)
731 {
732         const bool unselected = RNA_boolean_get(op->ptr, "unselected");
733         Object *ob = CTX_data_active_object(C);
734         paintface_hide(C, ob, unselected);
735         ED_region_tag_redraw(CTX_wm_region(C));
736         return OPERATOR_FINISHED;
737 }
738
739 void PAINT_OT_face_select_hide(wmOperatorType *ot)
740 {
741         ot->name = "Face Select Hide";
742         ot->description = "Hide selected faces";
743         ot->idname = "PAINT_OT_face_select_hide";
744
745         ot->exec = face_select_hide_exec;
746         ot->poll = facemask_paint_poll;
747
748         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
749
750         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
751 }
752
753 static int face_select_reveal_exec(bContext *C, wmOperator *op)
754 {
755         const bool select = RNA_boolean_get(op->ptr, "select");
756         Object *ob = CTX_data_active_object(C);
757         paintface_reveal(C, ob, select);
758         ED_region_tag_redraw(CTX_wm_region(C));
759         return OPERATOR_FINISHED;
760 }
761
762 void PAINT_OT_face_select_reveal(wmOperatorType *ot)
763 {
764         ot->name = "Face Select Reveal";
765         ot->description = "Reveal hidden faces";
766         ot->idname = "PAINT_OT_face_select_reveal";
767
768         ot->exec = face_select_reveal_exec;
769         ot->poll = facemask_paint_poll;
770
771         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
772
773         RNA_def_boolean(ot->srna, "select", true, "Select", "");
774 }