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  * along with this program; if not, write to the Free Software Foundation,
13  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
14  *
15  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
16  * All rights reserved.
17  *
18  * The Original Code is: some of this file.
19  */
20 
21 /** \file
22  * \ingroup edsculpt
23  * \brief Functions to paint images in 2D and 3D.
24  */
25 
26 #include <float.h>
27 #include <math.h>
28 #include <stdio.h>
29 #include <string.h>
30 
31 #include "MEM_guardedalloc.h"
32 
33 #include "BLI_blenlib.h"
34 #include "BLI_math.h"
35 #include "BLI_utildefines.h"
36 
37 #include "BLT_translation.h"
38 
39 #include "IMB_imbuf.h"
40 #include "IMB_imbuf_types.h"
41 
42 #include "DNA_brush_types.h"
43 #include "DNA_mesh_types.h"
44 #include "DNA_node_types.h"
45 #include "DNA_object_types.h"
46 
47 #include "BKE_brush.h"
48 #include "BKE_colorband.h"
49 #include "BKE_context.h"
50 #include "BKE_image.h"
51 #include "BKE_main.h"
52 #include "BKE_material.h"
53 #include "BKE_mesh.h"
54 #include "BKE_node.h"
55 #include "BKE_paint.h"
56 #include "BKE_undo_system.h"
57 
58 #include "DEG_depsgraph.h"
59 
60 #include "UI_interface.h"
61 #include "UI_view2d.h"
62 
63 #include "ED_image.h"
64 #include "ED_object.h"
65 #include "ED_paint.h"
66 #include "ED_screen.h"
67 #include "ED_view3d.h"
68 
69 #include "WM_api.h"
70 #include "WM_message.h"
71 #include "WM_toolsystem.h"
72 #include "WM_types.h"
73 
74 #include "RNA_access.h"
75 #include "RNA_define.h"
76 
77 #include "GPU_immediate.h"
78 #include "GPU_state.h"
79 
80 #include "IMB_colormanagement.h"
81 
82 #include "paint_intern.h"
83 
84 /**
85  * This is a static resource for non-global access.
86  * Maybe it should be exposed as part of the paint operation,
87  * but for now just give a public interface.
88  */
89 static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0};
90 
get_imapaintpartial(void)91 ImagePaintPartialRedraw *get_imapaintpartial(void)
92 {
93   return &imapaintpartial;
94 }
95 
set_imapaintpartial(struct ImagePaintPartialRedraw * ippr)96 void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr)
97 {
98   imapaintpartial = *ippr;
99 }
100 
101 /* Imagepaint Partial Redraw & Dirty Region */
102 
ED_imapaint_clear_partial_redraw(void)103 void ED_imapaint_clear_partial_redraw(void)
104 {
105   memset(&imapaintpartial, 0, sizeof(imapaintpartial));
106 }
107 
imapaint_region_tiles(ImBuf * ibuf,int x,int y,int w,int h,int * tx,int * ty,int * tw,int * th)108 void imapaint_region_tiles(
109     ImBuf *ibuf, int x, int y, int w, int h, int *tx, int *ty, int *tw, int *th)
110 {
111   int srcx = 0, srcy = 0;
112 
113   IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h);
114 
115   *tw = ((x + w - 1) >> ED_IMAGE_UNDO_TILE_BITS);
116   *th = ((y + h - 1) >> ED_IMAGE_UNDO_TILE_BITS);
117   *tx = (x >> ED_IMAGE_UNDO_TILE_BITS);
118   *ty = (y >> ED_IMAGE_UNDO_TILE_BITS);
119 }
120 
ED_imapaint_dirty_region(Image * ima,ImBuf * ibuf,ImageUser * iuser,int x,int y,int w,int h,bool find_old)121 void ED_imapaint_dirty_region(
122     Image *ima, ImBuf *ibuf, ImageUser *iuser, int x, int y, int w, int h, bool find_old)
123 {
124   ImBuf *tmpibuf = NULL;
125   int tilex, tiley, tilew, tileh, tx, ty;
126   int srcx = 0, srcy = 0;
127 
128   IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h);
129 
130   if (w == 0 || h == 0) {
131     return;
132   }
133 
134   if (!imapaintpartial.enabled) {
135     imapaintpartial.x1 = x;
136     imapaintpartial.y1 = y;
137     imapaintpartial.x2 = x + w;
138     imapaintpartial.y2 = y + h;
139     imapaintpartial.enabled = 1;
140   }
141   else {
142     imapaintpartial.x1 = min_ii(imapaintpartial.x1, x);
143     imapaintpartial.y1 = min_ii(imapaintpartial.y1, y);
144     imapaintpartial.x2 = max_ii(imapaintpartial.x2, x + w);
145     imapaintpartial.y2 = max_ii(imapaintpartial.y2, y + h);
146   }
147 
148   imapaint_region_tiles(ibuf, x, y, w, h, &tilex, &tiley, &tilew, &tileh);
149 
150   ListBase *undo_tiles = ED_image_paint_tile_list_get();
151 
152   for (ty = tiley; ty <= tileh; ty++) {
153     for (tx = tilex; tx <= tilew; tx++) {
154       ED_image_paint_tile_push(
155           undo_tiles, ima, ibuf, &tmpibuf, iuser, tx, ty, NULL, NULL, false, find_old);
156     }
157   }
158 
159   BKE_image_mark_dirty(ima, ibuf);
160 
161   if (tmpibuf) {
162     IMB_freeImBuf(tmpibuf);
163   }
164 }
165 
imapaint_image_update(SpaceImage * sima,Image * image,ImBuf * ibuf,ImageUser * iuser,short texpaint)166 void imapaint_image_update(
167     SpaceImage *sima, Image *image, ImBuf *ibuf, ImageUser *iuser, short texpaint)
168 {
169   if (imapaintpartial.x1 != imapaintpartial.x2 && imapaintpartial.y1 != imapaintpartial.y2) {
170     IMB_partial_display_buffer_update_delayed(
171         ibuf, imapaintpartial.x1, imapaintpartial.y1, imapaintpartial.x2, imapaintpartial.y2);
172   }
173 
174   if (ibuf->mipmap[0]) {
175     ibuf->userflags |= IB_MIPMAP_INVALID;
176   }
177 
178   /* todo: should set_tpage create ->rect? */
179   if (texpaint || (sima && sima->lock)) {
180     int w = imapaintpartial.x2 - imapaintpartial.x1;
181     int h = imapaintpartial.y2 - imapaintpartial.y1;
182     if (w && h) {
183       /* Testing with partial update in uv editor too */
184       BKE_image_update_gputexture(image, iuser, imapaintpartial.x1, imapaintpartial.y1, w, h);
185     }
186   }
187 }
188 
189 /* paint blur kernels. Projective painting enforces use of a 2x2 kernel due to lagging */
paint_new_blur_kernel(Brush * br,bool proj)190 BlurKernel *paint_new_blur_kernel(Brush *br, bool proj)
191 {
192   int i, j;
193   BlurKernel *kernel = MEM_mallocN(sizeof(BlurKernel), "blur kernel");
194   float radius;
195   int side;
196   eBlurKernelType type = br->blur_mode;
197 
198   if (proj) {
199     radius = 0.5f;
200 
201     side = kernel->side = 2;
202     kernel->side_squared = kernel->side * kernel->side;
203     kernel->wdata = MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data");
204     kernel->pixel_len = radius;
205   }
206   else {
207     if (br->blur_kernel_radius <= 0) {
208       br->blur_kernel_radius = 1;
209     }
210 
211     radius = br->blur_kernel_radius;
212 
213     side = kernel->side = radius * 2 + 1;
214     kernel->side_squared = kernel->side * kernel->side;
215     kernel->wdata = MEM_mallocN(sizeof(float) * kernel->side_squared, "blur kernel data");
216     kernel->pixel_len = br->blur_kernel_radius;
217   }
218 
219   switch (type) {
220     case KERNEL_BOX:
221       for (i = 0; i < kernel->side_squared; i++) {
222         kernel->wdata[i] = 1.0;
223       }
224       break;
225 
226     case KERNEL_GAUSSIAN: {
227       /* at 3.0 standard deviations distance, kernel is about zero */
228       float standard_dev = radius / 3.0f;
229 
230       /* make the necessary adjustment to the value for use in the normal distribution formula */
231       standard_dev = -standard_dev * standard_dev * 2;
232 
233       for (i = 0; i < side; i++) {
234         for (j = 0; j < side; j++) {
235           float idist = radius - i;
236           float jdist = radius - j;
237           float value = exp((idist * idist + jdist * jdist) / standard_dev);
238 
239           kernel->wdata[i + j * side] = value;
240         }
241       }
242 
243       break;
244     }
245 
246     default:
247       printf("unidentified kernel type, aborting\n");
248       MEM_freeN(kernel->wdata);
249       MEM_freeN(kernel);
250       return NULL;
251   }
252 
253   return kernel;
254 }
255 
paint_delete_blur_kernel(BlurKernel * kernel)256 void paint_delete_blur_kernel(BlurKernel *kernel)
257 {
258   if (kernel->wdata) {
259     MEM_freeN(kernel->wdata);
260   }
261 }
262 
263 /************************ image paint poll ************************/
264 
image_paint_brush(bContext * C)265 static Brush *image_paint_brush(bContext *C)
266 {
267   Scene *scene = CTX_data_scene(C);
268   ToolSettings *settings = scene->toolsettings;
269 
270   return BKE_paint_brush(&settings->imapaint.paint);
271 }
272 
image_paint_poll_ex(bContext * C,bool check_tool)273 static bool image_paint_poll_ex(bContext *C, bool check_tool)
274 {
275   Object *obact;
276 
277   if (!image_paint_brush(C)) {
278     return false;
279   }
280 
281   obact = CTX_data_active_object(C);
282   if ((obact && obact->mode & OB_MODE_TEXTURE_PAINT) && CTX_wm_region_view3d(C)) {
283     if (!check_tool || WM_toolsystem_active_tool_is_brush(C)) {
284       return true;
285     }
286   }
287   else {
288     SpaceImage *sima = CTX_wm_space_image(C);
289 
290     if (sima) {
291       if (sima->image != NULL && ID_IS_LINKED(sima->image)) {
292         return false;
293       }
294       ARegion *region = CTX_wm_region(C);
295 
296       if ((sima->mode == SI_MODE_PAINT) && region->regiontype == RGN_TYPE_WINDOW) {
297         return true;
298       }
299     }
300   }
301 
302   return false;
303 }
304 
image_paint_poll(bContext * C)305 static bool image_paint_poll(bContext *C)
306 {
307   return image_paint_poll_ex(C, true);
308 }
309 
image_paint_poll_ignore_tool(bContext * C)310 static bool image_paint_poll_ignore_tool(bContext *C)
311 {
312   return image_paint_poll_ex(C, false);
313 }
314 
image_paint_2d_clone_poll(bContext * C)315 static bool image_paint_2d_clone_poll(bContext *C)
316 {
317   Brush *brush = image_paint_brush(C);
318 
319   if (!CTX_wm_region_view3d(C) && image_paint_poll(C)) {
320     if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE)) {
321       if (brush->clone.image) {
322         return true;
323       }
324     }
325   }
326 
327   return false;
328 }
329 
330 /************************ paint operator ************************/
331 typedef enum eTexPaintMode {
332   PAINT_MODE_2D,
333   PAINT_MODE_3D_PROJECT,
334 } eTexPaintMode;
335 
336 typedef struct PaintOperation {
337   eTexPaintMode mode;
338 
339   void *custom_paint;
340 
341   float prevmouse[2];
342   float startmouse[2];
343   double starttime;
344 
345   void *cursor;
346   ViewContext vc;
347 } PaintOperation;
348 
paint_use_opacity_masking(Brush * brush)349 bool paint_use_opacity_masking(Brush *brush)
350 {
351   return ((brush->flag & BRUSH_AIRBRUSH) || (brush->flag & BRUSH_DRAG_DOT) ||
352                   (brush->flag & BRUSH_ANCHORED) || (brush->imagepaint_tool == PAINT_TOOL_SMEAR) ||
353                   (brush->imagepaint_tool == PAINT_TOOL_SOFTEN) ||
354                   (brush->imagepaint_tool == PAINT_TOOL_FILL) ||
355                   (brush->flag & BRUSH_USE_GRADIENT) ||
356                   (brush->mtex.tex && !ELEM(brush->mtex.brush_map_mode,
357                                             MTEX_MAP_MODE_TILED,
358                                             MTEX_MAP_MODE_STENCIL,
359                                             MTEX_MAP_MODE_3D)) ?
360               false :
361               true);
362 }
363 
paint_brush_color_get(struct Scene * scene,struct Brush * br,bool color_correction,bool invert,float distance,float pressure,float color[3],struct ColorManagedDisplay * display)364 void paint_brush_color_get(struct Scene *scene,
365                            struct Brush *br,
366                            bool color_correction,
367                            bool invert,
368                            float distance,
369                            float pressure,
370                            float color[3],
371                            struct ColorManagedDisplay *display)
372 {
373   if (invert) {
374     copy_v3_v3(color, BKE_brush_secondary_color_get(scene, br));
375   }
376   else {
377     if (br->flag & BRUSH_USE_GRADIENT) {
378       float color_gr[4];
379       switch (br->gradient_stroke_mode) {
380         case BRUSH_GRADIENT_PRESSURE:
381           BKE_colorband_evaluate(br->gradient, pressure, color_gr);
382           break;
383         case BRUSH_GRADIENT_SPACING_REPEAT: {
384           float coord = fmod(distance / br->gradient_spacing, 1.0);
385           BKE_colorband_evaluate(br->gradient, coord, color_gr);
386           break;
387         }
388         case BRUSH_GRADIENT_SPACING_CLAMP: {
389           BKE_colorband_evaluate(br->gradient, distance / br->gradient_spacing, color_gr);
390           break;
391         }
392       }
393       /* Gradient / Colorband colors are not considered PROP_COLOR_GAMMA.
394        * Brush colors are expected to be in sRGB though. */
395       IMB_colormanagement_scene_linear_to_srgb_v3(color_gr);
396 
397       copy_v3_v3(color, color_gr);
398     }
399     else {
400       copy_v3_v3(color, BKE_brush_color_get(scene, br));
401     }
402   }
403   if (color_correction) {
404     IMB_colormanagement_display_to_scene_linear_v3(color, display);
405   }
406 }
407 
paint_brush_init_tex(Brush * brush)408 void paint_brush_init_tex(Brush *brush)
409 {
410   /* init mtex nodes */
411   if (brush) {
412     MTex *mtex = &brush->mtex;
413     if (mtex->tex && mtex->tex->nodetree) {
414       /* has internal flag to detect it only does it once */
415       ntreeTexBeginExecTree(mtex->tex->nodetree);
416     }
417     mtex = &brush->mask_mtex;
418     if (mtex->tex && mtex->tex->nodetree) {
419       ntreeTexBeginExecTree(mtex->tex->nodetree);
420     }
421   }
422 }
423 
paint_brush_exit_tex(Brush * brush)424 void paint_brush_exit_tex(Brush *brush)
425 {
426   if (brush) {
427     MTex *mtex = &brush->mtex;
428     if (mtex->tex && mtex->tex->nodetree) {
429       ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
430     }
431     mtex = &brush->mask_mtex;
432     if (mtex->tex && mtex->tex->nodetree) {
433       ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
434     }
435   }
436 }
437 
gradient_draw_line(bContext * UNUSED (C),int x,int y,void * customdata)438 static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customdata)
439 {
440   PaintOperation *pop = (PaintOperation *)customdata;
441 
442   if (pop) {
443     GPU_line_smooth(true);
444     GPU_blend(GPU_BLEND_ALPHA);
445 
446     GPUVertFormat *format = immVertexFormat();
447     uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT);
448 
449     ARegion *region = pop->vc.region;
450 
451     immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
452 
453     GPU_line_width(4.0);
454     immUniformColor4ub(0, 0, 0, 255);
455 
456     immBegin(GPU_PRIM_LINES, 2);
457     immVertex2i(pos, x, y);
458     immVertex2i(
459         pos, pop->startmouse[0] + region->winrct.xmin, pop->startmouse[1] + region->winrct.ymin);
460     immEnd();
461 
462     GPU_line_width(2.0);
463     immUniformColor4ub(255, 255, 255, 255);
464 
465     immBegin(GPU_PRIM_LINES, 2);
466     immVertex2i(pos, x, y);
467     immVertex2i(
468         pos, pop->startmouse[0] + region->winrct.xmin, pop->startmouse[1] + region->winrct.ymin);
469     immEnd();
470 
471     immUnbindProgram();
472 
473     GPU_blend(GPU_BLEND_NONE);
474     GPU_line_smooth(false);
475   }
476 }
477 
texture_paint_init(bContext * C,wmOperator * op,const float mouse[2])478 static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const float mouse[2])
479 {
480   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
481   Scene *scene = CTX_data_scene(C);
482   ToolSettings *settings = scene->toolsettings;
483   PaintOperation *pop = MEM_callocN(sizeof(PaintOperation), "PaintOperation"); /* caller frees */
484   Brush *brush = BKE_paint_brush(&settings->imapaint.paint);
485   int mode = RNA_enum_get(op->ptr, "mode");
486   ED_view3d_viewcontext_init(C, &pop->vc, depsgraph);
487 
488   copy_v2_v2(pop->prevmouse, mouse);
489   copy_v2_v2(pop->startmouse, mouse);
490 
491   /* initialize from context */
492   if (CTX_wm_region_view3d(C)) {
493     ViewLayer *view_layer = CTX_data_view_layer(C);
494     Object *ob = OBACT(view_layer);
495     bool uvs, mat, tex, stencil;
496     if (!ED_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, &stencil)) {
497       ED_paint_data_warning(op->reports, uvs, mat, tex, stencil);
498       MEM_freeN(pop);
499       WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
500       return NULL;
501     }
502     pop->mode = PAINT_MODE_3D_PROJECT;
503     pop->custom_paint = paint_proj_new_stroke(C, ob, mouse, mode);
504   }
505   else {
506     pop->mode = PAINT_MODE_2D;
507     pop->custom_paint = paint_2d_new_stroke(C, op, mode);
508   }
509 
510   if (!pop->custom_paint) {
511     MEM_freeN(pop);
512     return NULL;
513   }
514 
515   if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) {
516     pop->cursor = WM_paint_cursor_activate(
517         SPACE_TYPE_ANY, RGN_TYPE_ANY, image_paint_poll, gradient_draw_line, pop);
518   }
519 
520   settings->imapaint.flag |= IMAGEPAINT_DRAWING;
521   ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_2D);
522 
523   return pop;
524 }
525 
paint_stroke_update_step(bContext * C,struct PaintStroke * stroke,PointerRNA * itemptr)526 static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
527 {
528   PaintOperation *pop = paint_stroke_mode_data(stroke);
529   Scene *scene = CTX_data_scene(C);
530   ToolSettings *toolsettings = CTX_data_tool_settings(C);
531   UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings;
532   Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint);
533 
534   float alphafac = (brush->flag & BRUSH_ACCUMULATE) ? ups->overlap_factor : 1.0f;
535 
536   /* initial brush values. Maybe it should be considered moving these to stroke system */
537   float startalpha = BKE_brush_alpha_get(scene, brush);
538 
539   float mouse[2];
540   float pressure;
541   float size;
542   float distance = paint_stroke_distance_get(stroke);
543   int eraser;
544 
545   RNA_float_get_array(itemptr, "mouse", mouse);
546   pressure = RNA_float_get(itemptr, "pressure");
547   eraser = RNA_boolean_get(itemptr, "pen_flip");
548   size = RNA_float_get(itemptr, "size");
549 
550   /* stroking with fill tool only acts on stroke end */
551   if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
552     copy_v2_v2(pop->prevmouse, mouse);
553     return;
554   }
555 
556   if (BKE_brush_use_alpha_pressure(brush)) {
557     BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure * alphafac));
558   }
559   else {
560     BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * alphafac));
561   }
562 
563   if ((brush->flag & BRUSH_DRAG_DOT) || (brush->flag & BRUSH_ANCHORED)) {
564     UndoStack *ustack = CTX_wm_manager(C)->undo_stack;
565     ED_image_undo_restore(ustack->step_init);
566   }
567 
568   if (pop->mode == PAINT_MODE_3D_PROJECT) {
569     paint_proj_stroke(
570         C, pop->custom_paint, pop->prevmouse, mouse, eraser, pressure, distance, size);
571   }
572   else {
573     paint_2d_stroke(pop->custom_paint, pop->prevmouse, mouse, eraser, pressure, distance, size);
574   }
575 
576   copy_v2_v2(pop->prevmouse, mouse);
577 
578   /* restore brush values */
579   BKE_brush_alpha_set(scene, brush, startalpha);
580 }
581 
paint_stroke_redraw(const bContext * C,struct PaintStroke * stroke,bool final)582 static void paint_stroke_redraw(const bContext *C, struct PaintStroke *stroke, bool final)
583 {
584   PaintOperation *pop = paint_stroke_mode_data(stroke);
585 
586   if (pop->mode == PAINT_MODE_3D_PROJECT) {
587     paint_proj_redraw(C, pop->custom_paint, final);
588   }
589   else {
590     paint_2d_redraw(C, pop->custom_paint, final);
591   }
592 }
593 
paint_stroke_done(const bContext * C,struct PaintStroke * stroke)594 static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
595 {
596   Scene *scene = CTX_data_scene(C);
597   ToolSettings *toolsettings = scene->toolsettings;
598   PaintOperation *pop = paint_stroke_mode_data(stroke);
599   Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint);
600 
601   toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
602 
603   if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
604     if (brush->flag & BRUSH_USE_GRADIENT) {
605       if (pop->mode == PAINT_MODE_2D) {
606         paint_2d_gradient_fill(C, brush, pop->startmouse, pop->prevmouse, pop->custom_paint);
607       }
608       else {
609         paint_proj_stroke(C,
610                           pop->custom_paint,
611                           pop->startmouse,
612                           pop->prevmouse,
613                           paint_stroke_flipped(stroke),
614                           1.0,
615                           0.0,
616                           BKE_brush_size_get(scene, brush));
617         /* two redraws, one for GPU update, one for notification */
618         paint_proj_redraw(C, pop->custom_paint, false);
619         paint_proj_redraw(C, pop->custom_paint, true);
620       }
621     }
622     else {
623       if (pop->mode == PAINT_MODE_2D) {
624         float color[3];
625         if (paint_stroke_inverted(stroke)) {
626           srgb_to_linearrgb_v3_v3(color, BKE_brush_secondary_color_get(scene, brush));
627         }
628         else {
629           srgb_to_linearrgb_v3_v3(color, BKE_brush_color_get(scene, brush));
630         }
631         paint_2d_bucket_fill(C, color, brush, pop->startmouse, pop->prevmouse, pop->custom_paint);
632       }
633       else {
634         paint_proj_stroke(C,
635                           pop->custom_paint,
636                           pop->startmouse,
637                           pop->prevmouse,
638                           paint_stroke_flipped(stroke),
639                           1.0,
640                           0.0,
641                           BKE_brush_size_get(scene, brush));
642         /* two redraws, one for GPU update, one for notification */
643         paint_proj_redraw(C, pop->custom_paint, false);
644         paint_proj_redraw(C, pop->custom_paint, true);
645       }
646     }
647   }
648   if (pop->mode == PAINT_MODE_3D_PROJECT) {
649     paint_proj_stroke_done(pop->custom_paint);
650   }
651   else {
652     paint_2d_stroke_done(pop->custom_paint);
653   }
654 
655   if (pop->cursor) {
656     WM_paint_cursor_end(pop->cursor);
657   }
658 
659   ED_image_undo_push_end();
660 
661   /* duplicate warning, see texpaint_init */
662 #if 0
663   if (pop->s.warnmultifile) {
664     BKE_reportf(op->reports,
665                 RPT_WARNING,
666                 "Image requires 4 color channels to paint: %s",
667                 pop->s.warnmultifile);
668   }
669   if (pop->s.warnpackedfile) {
670     BKE_reportf(op->reports,
671                 RPT_WARNING,
672                 "Packed MultiLayer files cannot be painted: %s",
673                 pop->s.warnpackedfile);
674   }
675 #endif
676   MEM_freeN(pop);
677 }
678 
paint_stroke_test_start(bContext * C,wmOperator * op,const float mouse[2])679 static bool paint_stroke_test_start(bContext *C, wmOperator *op, const float mouse[2])
680 {
681   PaintOperation *pop;
682 
683   /* TODO Should avoid putting this here. Instead, last position should be requested
684    * from stroke system. */
685 
686   if (!(pop = texture_paint_init(C, op, mouse))) {
687     return false;
688   }
689 
690   paint_stroke_set_mode_data(op->customdata, pop);
691 
692   return true;
693 }
694 
paint_invoke(bContext * C,wmOperator * op,const wmEvent * event)695 static int paint_invoke(bContext *C, wmOperator *op, const wmEvent *event)
696 {
697   int retval;
698 
699   op->customdata = paint_stroke_new(C,
700                                     op,
701                                     NULL,
702                                     paint_stroke_test_start,
703                                     paint_stroke_update_step,
704                                     paint_stroke_redraw,
705                                     paint_stroke_done,
706                                     event->type);
707 
708   if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
709     paint_stroke_free(C, op);
710     return OPERATOR_FINISHED;
711   }
712   /* add modal handler */
713   WM_event_add_modal_handler(C, op);
714 
715   OPERATOR_RETVAL_CHECK(retval);
716   BLI_assert(retval == OPERATOR_RUNNING_MODAL);
717 
718   return OPERATOR_RUNNING_MODAL;
719 }
720 
paint_exec(bContext * C,wmOperator * op)721 static int paint_exec(bContext *C, wmOperator *op)
722 {
723   PropertyRNA *strokeprop;
724   PointerRNA firstpoint;
725   float mouse[2];
726 
727   strokeprop = RNA_struct_find_property(op->ptr, "stroke");
728 
729   if (!RNA_property_collection_lookup_int(op->ptr, strokeprop, 0, &firstpoint)) {
730     return OPERATOR_CANCELLED;
731   }
732 
733   RNA_float_get_array(&firstpoint, "mouse", mouse);
734 
735   op->customdata = paint_stroke_new(C,
736                                     op,
737                                     NULL,
738                                     paint_stroke_test_start,
739                                     paint_stroke_update_step,
740                                     paint_stroke_redraw,
741                                     paint_stroke_done,
742                                     0);
743   /* frees op->customdata */
744   return paint_stroke_exec(C, op);
745 }
746 
PAINT_OT_image_paint(wmOperatorType * ot)747 void PAINT_OT_image_paint(wmOperatorType *ot)
748 {
749   /* identifiers */
750   ot->name = "Image Paint";
751   ot->idname = "PAINT_OT_image_paint";
752   ot->description = "Paint a stroke into the image";
753 
754   /* api callbacks */
755   ot->invoke = paint_invoke;
756   ot->modal = paint_stroke_modal;
757   ot->exec = paint_exec;
758   ot->poll = image_paint_poll;
759   ot->cancel = paint_stroke_cancel;
760 
761   /* flags */
762   ot->flag = OPTYPE_BLOCKING;
763 
764   paint_stroke_operator_properties(ot);
765 }
766 
get_imapaint_zoom(bContext * C,float * zoomx,float * zoomy)767 bool get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
768 {
769   ScrArea *area = CTX_wm_area(C);
770   if (area && area->spacetype == SPACE_IMAGE) {
771     SpaceImage *sima = area->spacedata.first;
772     if (sima->mode == SI_MODE_PAINT) {
773       ARegion *region = CTX_wm_region(C);
774       ED_space_image_get_zoom(sima, region, zoomx, zoomy);
775       return true;
776     }
777   }
778 
779   *zoomx = *zoomy = 1;
780 
781   return false;
782 }
783 
784 /************************ cursor drawing *******************************/
785 
toggle_paint_cursor(Scene * scene,bool enable)786 static void toggle_paint_cursor(Scene *scene, bool enable)
787 {
788   ToolSettings *settings = scene->toolsettings;
789   Paint *p = &settings->imapaint.paint;
790 
791   if (p->paint_cursor && !enable) {
792     WM_paint_cursor_end(p->paint_cursor);
793     p->paint_cursor = NULL;
794     paint_cursor_delete_textures();
795   }
796   else if (enable) {
797     paint_cursor_start(p, image_paint_poll);
798   }
799 }
800 
801 /* enable the paint cursor if it isn't already.
802  *
803  * purpose is to make sure the paint cursor is shown if paint
804  * mode is enabled in the image editor. the paint poll will
805  * ensure that the cursor is hidden when not in paint mode */
ED_space_image_paint_update(Main * bmain,wmWindowManager * wm,Scene * scene)806 void ED_space_image_paint_update(Main *bmain, wmWindowManager *wm, Scene *scene)
807 {
808   ToolSettings *settings = scene->toolsettings;
809   ImagePaintSettings *imapaint = &settings->imapaint;
810   bool enabled = false;
811 
812   LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
813     bScreen *screen = WM_window_get_active_screen(win);
814 
815     LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
816       if (area->spacetype == SPACE_IMAGE) {
817         if (((SpaceImage *)area->spacedata.first)->mode == SI_MODE_PAINT) {
818           enabled = true;
819         }
820       }
821     }
822   }
823 
824   if (enabled) {
825     BKE_paint_init(bmain, scene, PAINT_MODE_TEXTURE_2D, PAINT_CURSOR_TEXTURE_PAINT);
826 
827     paint_cursor_start(&imapaint->paint, image_paint_poll);
828   }
829   else {
830     paint_cursor_delete_textures();
831   }
832 }
833 
834 /************************ grab clone operator ************************/
835 
836 typedef struct GrabClone {
837   float startoffset[2];
838   int startx, starty;
839 } GrabClone;
840 
grab_clone_apply(bContext * C,wmOperator * op)841 static void grab_clone_apply(bContext *C, wmOperator *op)
842 {
843   Brush *brush = image_paint_brush(C);
844   float delta[2];
845 
846   RNA_float_get_array(op->ptr, "delta", delta);
847   add_v2_v2(brush->clone.offset, delta);
848   ED_region_tag_redraw(CTX_wm_region(C));
849 }
850 
grab_clone_exec(bContext * C,wmOperator * op)851 static int grab_clone_exec(bContext *C, wmOperator *op)
852 {
853   grab_clone_apply(C, op);
854 
855   return OPERATOR_FINISHED;
856 }
857 
grab_clone_invoke(bContext * C,wmOperator * op,const wmEvent * event)858 static int grab_clone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
859 {
860   Brush *brush = image_paint_brush(C);
861   GrabClone *cmv;
862 
863   cmv = MEM_callocN(sizeof(GrabClone), "GrabClone");
864   copy_v2_v2(cmv->startoffset, brush->clone.offset);
865   cmv->startx = event->x;
866   cmv->starty = event->y;
867   op->customdata = cmv;
868 
869   WM_event_add_modal_handler(C, op);
870 
871   return OPERATOR_RUNNING_MODAL;
872 }
873 
grab_clone_modal(bContext * C,wmOperator * op,const wmEvent * event)874 static int grab_clone_modal(bContext *C, wmOperator *op, const wmEvent *event)
875 {
876   Brush *brush = image_paint_brush(C);
877   ARegion *region = CTX_wm_region(C);
878   GrabClone *cmv = op->customdata;
879   float startfx, startfy, fx, fy, delta[2];
880   int xmin = region->winrct.xmin, ymin = region->winrct.ymin;
881 
882   switch (event->type) {
883     case LEFTMOUSE:
884     case MIDDLEMOUSE:
885     case RIGHTMOUSE: /* XXX hardcoded */
886       MEM_freeN(op->customdata);
887       return OPERATOR_FINISHED;
888     case MOUSEMOVE:
889       /* mouse moved, so move the clone image */
890       UI_view2d_region_to_view(
891           &region->v2d, cmv->startx - xmin, cmv->starty - ymin, &startfx, &startfy);
892       UI_view2d_region_to_view(&region->v2d, event->x - xmin, event->y - ymin, &fx, &fy);
893 
894       delta[0] = fx - startfx;
895       delta[1] = fy - startfy;
896       RNA_float_set_array(op->ptr, "delta", delta);
897 
898       copy_v2_v2(brush->clone.offset, cmv->startoffset);
899 
900       grab_clone_apply(C, op);
901       break;
902   }
903 
904   return OPERATOR_RUNNING_MODAL;
905 }
906 
grab_clone_cancel(bContext * UNUSED (C),wmOperator * op)907 static void grab_clone_cancel(bContext *UNUSED(C), wmOperator *op)
908 {
909   MEM_freeN(op->customdata);
910 }
911 
PAINT_OT_grab_clone(wmOperatorType * ot)912 void PAINT_OT_grab_clone(wmOperatorType *ot)
913 {
914   /* identifiers */
915   ot->name = "Grab Clone";
916   ot->idname = "PAINT_OT_grab_clone";
917   ot->description = "Move the clone source image";
918 
919   /* api callbacks */
920   ot->exec = grab_clone_exec;
921   ot->invoke = grab_clone_invoke;
922   ot->modal = grab_clone_modal;
923   ot->cancel = grab_clone_cancel;
924   ot->poll = image_paint_2d_clone_poll;
925 
926   /* flags */
927   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
928 
929   /* properties */
930   RNA_def_float_vector(ot->srna,
931                        "delta",
932                        2,
933                        NULL,
934                        -FLT_MAX,
935                        FLT_MAX,
936                        "Delta",
937                        "Delta offset of clone image in 0.0..1.0 coordinates",
938                        -1.0f,
939                        1.0f);
940 }
941 
942 /******************** sample color operator ********************/
943 typedef struct {
944   bool show_cursor;
945   short launch_event;
946   float initcolor[3];
947   bool sample_palette;
948 } SampleColorData;
949 
sample_color_update_header(SampleColorData * data,bContext * C)950 static void sample_color_update_header(SampleColorData *data, bContext *C)
951 {
952   char msg[UI_MAX_DRAW_STR];
953   ScrArea *area = CTX_wm_area(C);
954 
955   if (area) {
956     BLI_snprintf(msg,
957                  sizeof(msg),
958                  TIP_("Sample color for %s"),
959                  !data->sample_palette ?
960                      TIP_("Brush. Use Left Click to sample for palette instead") :
961                      TIP_("Palette. Use Left Click to sample more colors"));
962     ED_workspace_status_text(C, msg);
963   }
964 }
965 
sample_color_exec(bContext * C,wmOperator * op)966 static int sample_color_exec(bContext *C, wmOperator *op)
967 {
968   Paint *paint = BKE_paint_get_active_from_context(C);
969   Brush *brush = BKE_paint_brush(paint);
970   ePaintMode mode = BKE_paintmode_get_active_from_context(C);
971   ARegion *region = CTX_wm_region(C);
972   wmWindow *win = CTX_wm_window(C);
973   const bool show_cursor = ((paint->flags & PAINT_SHOW_BRUSH) != 0);
974   int location[2];
975   paint->flags &= ~PAINT_SHOW_BRUSH;
976 
977   /* force redraw without cursor */
978   WM_paint_cursor_tag_redraw(win, region);
979   WM_redraw_windows(C);
980 
981   RNA_int_get_array(op->ptr, "location", location);
982   const bool use_palette = RNA_boolean_get(op->ptr, "palette");
983   const bool use_sample_texture = (mode == PAINT_MODE_TEXTURE_3D) &&
984                                   !RNA_boolean_get(op->ptr, "merged");
985 
986   paint_sample_color(C, region, location[0], location[1], use_sample_texture, use_palette);
987 
988   if (show_cursor) {
989     paint->flags |= PAINT_SHOW_BRUSH;
990   }
991 
992   WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
993 
994   return OPERATOR_FINISHED;
995 }
996 
sample_color_invoke(bContext * C,wmOperator * op,const wmEvent * event)997 static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event)
998 {
999   Scene *scene = CTX_data_scene(C);
1000   Paint *paint = BKE_paint_get_active_from_context(C);
1001   Brush *brush = BKE_paint_brush(paint);
1002   SampleColorData *data = MEM_mallocN(sizeof(SampleColorData), "sample color custom data");
1003   ARegion *region = CTX_wm_region(C);
1004   wmWindow *win = CTX_wm_window(C);
1005 
1006   data->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
1007   data->show_cursor = ((paint->flags & PAINT_SHOW_BRUSH) != 0);
1008   copy_v3_v3(data->initcolor, BKE_brush_color_get(scene, brush));
1009   data->sample_palette = false;
1010   op->customdata = data;
1011   paint->flags &= ~PAINT_SHOW_BRUSH;
1012 
1013   sample_color_update_header(data, C);
1014 
1015   WM_event_add_modal_handler(C, op);
1016 
1017   /* force redraw without cursor */
1018   WM_paint_cursor_tag_redraw(win, region);
1019   WM_redraw_windows(C);
1020 
1021   RNA_int_set_array(op->ptr, "location", event->mval);
1022 
1023   ePaintMode mode = BKE_paintmode_get_active_from_context(C);
1024   const bool use_sample_texture = (mode == PAINT_MODE_TEXTURE_3D) &&
1025                                   !RNA_boolean_get(op->ptr, "merged");
1026 
1027   paint_sample_color(C, region, event->mval[0], event->mval[1], use_sample_texture, false);
1028   WM_cursor_modal_set(win, WM_CURSOR_EYEDROPPER);
1029 
1030   WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
1031 
1032   return OPERATOR_RUNNING_MODAL;
1033 }
1034 
sample_color_modal(bContext * C,wmOperator * op,const wmEvent * event)1035 static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event)
1036 {
1037   Scene *scene = CTX_data_scene(C);
1038   SampleColorData *data = op->customdata;
1039   Paint *paint = BKE_paint_get_active_from_context(C);
1040   Brush *brush = BKE_paint_brush(paint);
1041 
1042   if ((event->type == data->launch_event) && (event->val == KM_RELEASE)) {
1043     if (data->show_cursor) {
1044       paint->flags |= PAINT_SHOW_BRUSH;
1045     }
1046 
1047     if (data->sample_palette) {
1048       BKE_brush_color_set(scene, brush, data->initcolor);
1049       RNA_boolean_set(op->ptr, "palette", true);
1050     }
1051     WM_cursor_modal_restore(CTX_wm_window(C));
1052     MEM_freeN(data);
1053     ED_workspace_status_text(C, NULL);
1054 
1055     return OPERATOR_FINISHED;
1056   }
1057 
1058   ePaintMode mode = BKE_paintmode_get_active_from_context(C);
1059   const bool use_sample_texture = (mode == PAINT_MODE_TEXTURE_3D) &&
1060                                   !RNA_boolean_get(op->ptr, "merged");
1061 
1062   switch (event->type) {
1063     case MOUSEMOVE: {
1064       ARegion *region = CTX_wm_region(C);
1065       RNA_int_set_array(op->ptr, "location", event->mval);
1066       paint_sample_color(C, region, event->mval[0], event->mval[1], use_sample_texture, false);
1067       WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
1068       break;
1069     }
1070 
1071     case LEFTMOUSE:
1072       if (event->val == KM_PRESS) {
1073         ARegion *region = CTX_wm_region(C);
1074         RNA_int_set_array(op->ptr, "location", event->mval);
1075         paint_sample_color(C, region, event->mval[0], event->mval[1], use_sample_texture, true);
1076         if (!data->sample_palette) {
1077           data->sample_palette = true;
1078           sample_color_update_header(data, C);
1079         }
1080         WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, brush);
1081       }
1082       break;
1083   }
1084 
1085   return OPERATOR_RUNNING_MODAL;
1086 }
1087 
sample_color_poll(bContext * C)1088 static bool sample_color_poll(bContext *C)
1089 {
1090   return (image_paint_poll_ignore_tool(C) || vertex_paint_poll_ignore_tool(C));
1091 }
1092 
PAINT_OT_sample_color(wmOperatorType * ot)1093 void PAINT_OT_sample_color(wmOperatorType *ot)
1094 {
1095   /* identifiers */
1096   ot->name = "Sample Color";
1097   ot->idname = "PAINT_OT_sample_color";
1098   ot->description = "Use the mouse to sample a color in the image";
1099 
1100   /* api callbacks */
1101   ot->exec = sample_color_exec;
1102   ot->invoke = sample_color_invoke;
1103   ot->modal = sample_color_modal;
1104   ot->poll = sample_color_poll;
1105 
1106   /* flags */
1107   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1108 
1109   /* properties */
1110   PropertyRNA *prop;
1111 
1112   prop = RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "", 0, 16384);
1113   RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
1114 
1115   RNA_def_boolean(ot->srna, "merged", 0, "Sample Merged", "Sample the output display color");
1116   RNA_def_boolean(ot->srna, "palette", 0, "Add to Palette", "");
1117 }
1118 
1119 /******************** texture paint toggle operator ********************/
1120 
ED_object_texture_paint_mode_enter_ex(Main * bmain,Scene * scene,Object * ob)1121 void ED_object_texture_paint_mode_enter_ex(Main *bmain, Scene *scene, Object *ob)
1122 {
1123   Image *ima = NULL;
1124   ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
1125 
1126   /* This has to stay here to regenerate the texture paint
1127    * cache in case we are loading a file */
1128   BKE_texpaint_slots_refresh_object(scene, ob);
1129 
1130   ED_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
1131 
1132   /* entering paint mode also sets image to editors */
1133   if (imapaint->mode == IMAGEPAINT_MODE_MATERIAL) {
1134     /* set the current material active paint slot on image editor */
1135     Material *ma = BKE_object_material_get(ob, ob->actcol);
1136 
1137     if (ma && ma->texpaintslot) {
1138       ima = ma->texpaintslot[ma->paint_active_slot].ima;
1139     }
1140   }
1141   else if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
1142     ima = imapaint->canvas;
1143   }
1144 
1145   if (ima) {
1146     wmWindowManager *wm = bmain->wm.first;
1147     for (wmWindow *win = wm->windows.first; win; win = win->next) {
1148       const bScreen *screen = WM_window_get_active_screen(win);
1149       for (ScrArea *area = screen->areabase.first; area; area = area->next) {
1150         SpaceLink *sl = area->spacedata.first;
1151         if (sl->spacetype == SPACE_IMAGE) {
1152           SpaceImage *sima = (SpaceImage *)sl;
1153 
1154           if (!sima->pin) {
1155             ED_space_image_set(bmain, sima, NULL, ima, true);
1156           }
1157         }
1158       }
1159     }
1160   }
1161 
1162   ob->mode |= OB_MODE_TEXTURE_PAINT;
1163 
1164   BKE_paint_init(bmain, scene, PAINT_MODE_TEXTURE_3D, PAINT_CURSOR_TEXTURE_PAINT);
1165 
1166   BKE_paint_toolslots_brush_validate(bmain, &imapaint->paint);
1167 
1168   if (U.glreslimit != 0) {
1169     BKE_image_free_all_gputextures(bmain);
1170   }
1171   BKE_image_paint_set_mipmap(bmain, 0);
1172 
1173   toggle_paint_cursor(scene, true);
1174 
1175   Mesh *me = BKE_mesh_from_object(ob);
1176   BLI_assert(me != NULL);
1177   DEG_id_tag_update(&me->id, ID_RECALC_COPY_ON_WRITE);
1178   WM_main_add_notifier(NC_SCENE | ND_MODE, scene);
1179 }
1180 
ED_object_texture_paint_mode_enter(bContext * C)1181 void ED_object_texture_paint_mode_enter(bContext *C)
1182 {
1183   Main *bmain = CTX_data_main(C);
1184   Object *ob = CTX_data_active_object(C);
1185   Scene *scene = CTX_data_scene(C);
1186   ED_object_texture_paint_mode_enter_ex(bmain, scene, ob);
1187 }
1188 
ED_object_texture_paint_mode_exit_ex(Main * bmain,Scene * scene,Object * ob)1189 void ED_object_texture_paint_mode_exit_ex(Main *bmain, Scene *scene, Object *ob)
1190 {
1191   ob->mode &= ~OB_MODE_TEXTURE_PAINT;
1192 
1193   if (U.glreslimit != 0) {
1194     BKE_image_free_all_gputextures(bmain);
1195   }
1196   BKE_image_paint_set_mipmap(bmain, 1);
1197   toggle_paint_cursor(scene, false);
1198 
1199   Mesh *me = BKE_mesh_from_object(ob);
1200   BLI_assert(me != NULL);
1201   DEG_id_tag_update(&me->id, ID_RECALC_COPY_ON_WRITE);
1202   WM_main_add_notifier(NC_SCENE | ND_MODE, scene);
1203 }
1204 
ED_object_texture_paint_mode_exit(bContext * C)1205 void ED_object_texture_paint_mode_exit(bContext *C)
1206 {
1207   Main *bmain = CTX_data_main(C);
1208   Object *ob = CTX_data_active_object(C);
1209   Scene *scene = CTX_data_scene(C);
1210   ED_object_texture_paint_mode_exit_ex(bmain, scene, ob);
1211 }
1212 
texture_paint_toggle_poll(bContext * C)1213 static bool texture_paint_toggle_poll(bContext *C)
1214 {
1215   Object *ob = CTX_data_active_object(C);
1216   if (ob == NULL || ob->type != OB_MESH) {
1217     return false;
1218   }
1219   if (!ob->data || ID_IS_LINKED(ob->data)) {
1220     return false;
1221   }
1222 
1223   return true;
1224 }
1225 
texture_paint_toggle_exec(bContext * C,wmOperator * op)1226 static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
1227 {
1228   struct wmMsgBus *mbus = CTX_wm_message_bus(C);
1229   Main *bmain = CTX_data_main(C);
1230   Scene *scene = CTX_data_scene(C);
1231   Object *ob = CTX_data_active_object(C);
1232   const int mode_flag = OB_MODE_TEXTURE_PAINT;
1233   const bool is_mode_set = (ob->mode & mode_flag) != 0;
1234 
1235   if (!is_mode_set) {
1236     if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
1237       return OPERATOR_CANCELLED;
1238     }
1239   }
1240 
1241   if (ob->mode & mode_flag) {
1242     ED_object_texture_paint_mode_exit_ex(bmain, scene, ob);
1243   }
1244   else {
1245     ED_object_texture_paint_mode_enter_ex(bmain, scene, ob);
1246   }
1247 
1248   WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
1249 
1250   WM_toolsystem_update_from_context_view3d(C);
1251 
1252   return OPERATOR_FINISHED;
1253 }
1254 
PAINT_OT_texture_paint_toggle(wmOperatorType * ot)1255 void PAINT_OT_texture_paint_toggle(wmOperatorType *ot)
1256 {
1257   /* identifiers */
1258   ot->name = "Texture Paint Toggle";
1259   ot->idname = "PAINT_OT_texture_paint_toggle";
1260   ot->description = "Toggle texture paint mode in 3D view";
1261 
1262   /* api callbacks */
1263   ot->exec = texture_paint_toggle_exec;
1264   ot->poll = texture_paint_toggle_poll;
1265 
1266   /* flags */
1267   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1268 }
1269 
brush_colors_flip_exec(bContext * C,wmOperator * UNUSED (op))1270 static int brush_colors_flip_exec(bContext *C, wmOperator *UNUSED(op))
1271 {
1272   Scene *scene = CTX_data_scene(C);
1273   UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
1274 
1275   Paint *paint = BKE_paint_get_active_from_context(C);
1276   Brush *br = BKE_paint_brush(paint);
1277 
1278   if (ups->flag & UNIFIED_PAINT_COLOR) {
1279     swap_v3_v3(ups->rgb, ups->secondary_rgb);
1280   }
1281   else if (br) {
1282     swap_v3_v3(br->rgb, br->secondary_rgb);
1283   }
1284   else {
1285     return OPERATOR_CANCELLED;
1286   }
1287 
1288   WM_event_add_notifier(C, NC_BRUSH | NA_EDITED, br);
1289 
1290   return OPERATOR_FINISHED;
1291 }
1292 
brush_colors_flip_poll(bContext * C)1293 static bool brush_colors_flip_poll(bContext *C)
1294 {
1295   if (image_paint_poll(C)) {
1296     Brush *br = image_paint_brush(C);
1297     if (ELEM(br->imagepaint_tool, PAINT_TOOL_DRAW, PAINT_TOOL_FILL)) {
1298       return true;
1299     }
1300   }
1301   else {
1302     Object *ob = CTX_data_active_object(C);
1303     if (ob != NULL) {
1304       if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT | OB_MODE_SCULPT)) {
1305         return true;
1306       }
1307     }
1308   }
1309   return false;
1310 }
1311 
PAINT_OT_brush_colors_flip(wmOperatorType * ot)1312 void PAINT_OT_brush_colors_flip(wmOperatorType *ot)
1313 {
1314   /* identifiers */
1315   ot->name = "Swap Colors";
1316   ot->idname = "PAINT_OT_brush_colors_flip";
1317   ot->description = "Swap primary and secondary brush colors";
1318 
1319   /* api callbacks */
1320   ot->exec = brush_colors_flip_exec;
1321   ot->poll = brush_colors_flip_poll;
1322 
1323   /* flags */
1324   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1325 }
1326 
ED_imapaint_bucket_fill(struct bContext * C,float color[3],wmOperator * op,const int mouse[2])1327 void ED_imapaint_bucket_fill(struct bContext *C,
1328                              float color[3],
1329                              wmOperator *op,
1330                              const int mouse[2])
1331 {
1332   SpaceImage *sima = CTX_wm_space_image(C);
1333 
1334   if (sima && sima->image) {
1335     Image *ima = sima->image;
1336 
1337     ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_2D);
1338 
1339     const float mouse_init[2] = {mouse[0], mouse[1]};
1340     paint_2d_bucket_fill(C, color, NULL, mouse_init, NULL, NULL);
1341 
1342     ED_image_undo_push_end();
1343 
1344     DEG_id_tag_update(&ima->id, 0);
1345   }
1346 }
1347 
texture_paint_poll(bContext * C)1348 static bool texture_paint_poll(bContext *C)
1349 {
1350   if (texture_paint_toggle_poll(C)) {
1351     if (CTX_data_active_object(C)->mode & OB_MODE_TEXTURE_PAINT) {
1352       return true;
1353     }
1354   }
1355 
1356   return false;
1357 }
1358 
image_texture_paint_poll(bContext * C)1359 bool image_texture_paint_poll(bContext *C)
1360 {
1361   return (texture_paint_poll(C) || image_paint_poll(C));
1362 }
1363 
facemask_paint_poll(bContext * C)1364 bool facemask_paint_poll(bContext *C)
1365 {
1366   return BKE_paint_select_face_test(CTX_data_active_object(C));
1367 }
1368 
vert_paint_poll(bContext * C)1369 bool vert_paint_poll(bContext *C)
1370 {
1371   return BKE_paint_select_vert_test(CTX_data_active_object(C));
1372 }
1373 
mask_paint_poll(bContext * C)1374 bool mask_paint_poll(bContext *C)
1375 {
1376   return BKE_paint_select_elem_test(CTX_data_active_object(C));
1377 }
1378