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