Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / sculpt_paint / paint_stroke.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software  Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 by Nicholas Bishop
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Jason Wilkins, Tom Musgrove.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  *
27  */
28
29 /** \file blender/editors/sculpt_paint/paint_stroke.c
30  *  \ingroup edsculpt
31  */
32
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_math.h"
37 #include "BLI_utildefines.h"
38 #include "BLI_rand.h"
39 #include "BLI_listbase.h"
40
41 #include "DNA_object_types.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_brush_types.h"
44 #include "DNA_curve_types.h"
45
46 #include "RNA_access.h"
47
48 #include "BKE_context.h"
49 #include "BKE_paint.h"
50 #include "BKE_brush.h"
51 #include "BKE_curve.h"
52 #include "BKE_colortools.h"
53 #include "BKE_image.h"
54 #include "BKE_mesh.h"
55
56 #include "WM_api.h"
57 #include "WM_types.h"
58
59 #include "BIF_gl.h"
60 #include "BIF_glutil.h"
61
62 #include "GPU_immediate.h"
63
64 #include "ED_screen.h"
65 #include "ED_view3d.h"
66
67 #include "IMB_imbuf_types.h"
68
69 #include "paint_intern.h"
70
71 #include <float.h>
72 #include <math.h>
73
74 //#define DEBUG_TIME
75
76 #ifdef DEBUG_TIME
77 #  include "PIL_time_utildefines.h"
78 #endif
79
80 typedef struct PaintSample {
81         float mouse[2];
82         float pressure;
83 } PaintSample;
84
85 typedef struct PaintStroke {
86         void *mode_data;
87         void *stroke_cursor;
88         wmTimer *timer;
89
90         /* Cached values */
91         ViewContext vc;
92         Brush *brush;
93         UnifiedPaintSettings *ups;
94
95         /* used for lines and curves */
96         ListBase line;
97
98         /* Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES prior inputs
99          * to smooth the stroke */
100         PaintSample samples[PAINT_MAX_INPUT_SAMPLES];
101         int num_samples;
102         int cur_sample;
103
104         float last_mouse_position[2];
105         /* space distance covered so far */
106         float stroke_distance;
107
108         /* Set whether any stroke step has yet occurred
109          * e.g. in sculpt mode, stroke doesn't start until cursor
110          * passes over the mesh */
111         bool stroke_started;
112         /* event that started stroke, for modal() return */
113         int event_type;
114         /* check if stroke variables have been initialized */
115         bool stroke_init;
116         /* check if various brush mapping variables have been initialized */
117         bool brush_init;
118         float initial_mouse[2];
119         /* cached_pressure stores initial pressure for size pressure influence mainly */
120         float cached_size_pressure;
121         /* last pressure will store last pressure value for use in interpolation for space strokes */
122         float last_pressure;
123         int stroke_mode;
124
125         float zoom_2d;
126         int pen_flip;
127         
128         /* line constraint */
129         bool constrain_line;
130         float constrained_pos[2];
131
132         StrokeGetLocation get_location;
133         StrokeTestStart test_start;
134         StrokeUpdateStep update_step;
135         StrokeRedraw redraw;
136         StrokeDone done;
137 } PaintStroke;
138
139 /*** Cursors ***/
140 static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata)
141 {
142         Paint *paint = BKE_paint_get_active_from_context(C);
143         Brush *brush = BKE_paint_brush(paint);
144         PaintStroke *stroke = customdata;
145
146         if (stroke && brush) {
147                 glEnable(GL_LINE_SMOOTH);
148                 glEnable(GL_BLEND);
149
150                 unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
151                 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
152                 immUniformColor4ubv(paint->paint_cursor_col);
153
154                 immBegin(GWN_PRIM_LINES, 2);
155                 immVertex2f(pos, x, y);
156                 immVertex2f(pos, stroke->last_mouse_position[0], stroke->last_mouse_position[1]);
157                 immEnd();
158
159                 immUnbindProgram();
160
161                 glDisable(GL_BLEND);
162                 glDisable(GL_LINE_SMOOTH);
163         }
164 }
165
166 static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
167 {
168         Paint *paint = BKE_paint_get_active_from_context(C);
169         PaintStroke *stroke = customdata;
170
171         glEnable(GL_LINE_SMOOTH);
172
173         uint shdr_pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
174
175         immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
176
177         float viewport_size[4];
178         glGetFloatv(GL_VIEWPORT, viewport_size);
179         immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
180
181         immUniform1i("num_colors", 2);  /* "advanced" mode */
182         const float alpha = (float)paint->paint_cursor_col[3] / 255.0f;
183         immUniformArray4fv("colors", (float *)(float[][4]){{0.0f, 0.0f, 0.0f, alpha}, {1.0f, 1.0f, 1.0f, alpha}}, 2);
184         immUniform1f("dash_width", 6.0f);
185
186         immBegin(GWN_PRIM_LINES, 2);
187
188         if (stroke->constrain_line) {
189                 immVertex2f(shdr_pos, stroke->last_mouse_position[0], stroke->last_mouse_position[1]);
190                 immVertex2f(shdr_pos, stroke->constrained_pos[0], stroke->constrained_pos[1]);
191         }
192         else {
193                 immVertex2f(shdr_pos, stroke->last_mouse_position[0], stroke->last_mouse_position[1]);
194                 immVertex2f(shdr_pos, x, y);
195         }
196
197         immEnd();
198
199         immUnbindProgram();
200
201         glDisable(GL_LINE_SMOOTH);
202 }
203
204 static bool paint_tool_require_location(Brush *brush, ePaintMode mode)
205 {
206         switch (mode) {
207                 case ePaintSculpt:
208                         if (ELEM(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE,
209                                                      SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB))
210                         {
211                                 return false;
212                         }
213                         else {
214                                 return true;
215                         }
216                 default:
217                         break;
218         }
219
220         return true;
221 }
222
223 /* Initialize the stroke cache variants from operator properties */
224 static bool paint_brush_update(bContext *C,
225                                Brush *brush,
226                                ePaintMode mode,
227                                struct PaintStroke *stroke,
228                                const float mouse_init[2],
229                                float mouse[2], float pressure,
230                                float location[3])
231 {
232         Scene *scene = CTX_data_scene(C);
233         UnifiedPaintSettings *ups = stroke->ups;
234         bool location_sampled = false;
235         bool location_success = false;
236         /* Use to perform all operations except applying the stroke,
237          * needed for operations that require cursor motion (rake). */
238         bool is_dry_run = false;
239         bool do_random = false;
240         bool do_random_mask = false;
241         /* XXX: Use pressure value from first brush step for brushes which don't
242          *      support strokes (grab, thumb). They depends on initial state and
243          *      brush coord/pressure/etc.
244          *      It's more an events design issue, which doesn't split coordinate/pressure/angle
245          *      changing events. We should avoid this after events system re-design */
246         if (!stroke->brush_init) {
247                 copy_v2_v2(stroke->initial_mouse, mouse);
248                 copy_v2_v2(ups->last_rake, mouse);
249                 copy_v2_v2(ups->tex_mouse, mouse);
250                 copy_v2_v2(ups->mask_tex_mouse, mouse);
251                 stroke->cached_size_pressure = pressure;
252
253                 ups->do_linear_conversion = false;
254                 ups->colorspace = NULL;
255
256                 /* check here if color sampling the main brush should do color conversion. This is done here
257                  * to avoid locking up to get the image buffer during sampling */
258                 if (brush->mtex.tex && brush->mtex.tex->type == TEX_IMAGE && brush->mtex.tex->ima) {
259                         ImBuf *tex_ibuf = BKE_image_pool_acquire_ibuf(brush->mtex.tex->ima, &brush->mtex.tex->iuser, NULL);
260                         if (tex_ibuf && tex_ibuf->rect_float == NULL) {
261                                 ups->do_linear_conversion = true;
262                                 ups->colorspace = tex_ibuf->rect_colorspace;
263                         }
264                         BKE_image_pool_release_ibuf(brush->mtex.tex->ima, tex_ibuf, NULL);
265                 }
266
267                 stroke->brush_init = true;
268         }
269
270         if (paint_supports_dynamic_size(brush, mode)) {
271                 copy_v2_v2(ups->tex_mouse, mouse);
272                 copy_v2_v2(ups->mask_tex_mouse, mouse);
273                 stroke->cached_size_pressure = pressure;
274         }
275
276         /* Truly temporary data that isn't stored in properties */
277
278         ups->stroke_active = true;
279         ups->size_pressure_value = stroke->cached_size_pressure;
280
281         ups->pixel_radius = BKE_brush_size_get(scene, brush);
282
283         if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, mode)) {
284                 ups->pixel_radius *= stroke->cached_size_pressure;
285         }
286
287         if (paint_supports_dynamic_tex_coords(brush, mode)) {
288
289                 if (ELEM(brush->mtex.brush_map_mode,
290                          MTEX_MAP_MODE_VIEW,
291                          MTEX_MAP_MODE_AREA,
292                          MTEX_MAP_MODE_RANDOM))
293                 {
294                         do_random = true;
295                 }
296
297                 if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
298                         BKE_brush_randomize_texture_coords(ups, false);
299                 else {
300                         copy_v2_v2(ups->tex_mouse, mouse);
301                 }
302
303                 /* take care of mask texture, if any */
304                 if (brush->mask_mtex.tex) {
305
306                         if (ELEM(brush->mask_mtex.brush_map_mode,
307                                  MTEX_MAP_MODE_VIEW,
308                                  MTEX_MAP_MODE_AREA,
309                                  MTEX_MAP_MODE_RANDOM))
310                         {
311                                 do_random_mask = true;
312                         }
313
314                         if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
315                                 BKE_brush_randomize_texture_coords(ups, true);
316                         else {
317                                 copy_v2_v2(ups->mask_tex_mouse, mouse);
318                         }
319                 }
320         }
321
322
323         if (brush->flag & BRUSH_ANCHORED) {
324                 bool hit = false;
325                 float halfway[2];
326
327                 const float dx = mouse[0] - stroke->initial_mouse[0];
328                 const float dy = mouse[1] - stroke->initial_mouse[1];
329
330                 ups->anchored_size = ups->pixel_radius = sqrtf(dx * dx + dy * dy);
331
332                 ups->brush_rotation = ups->brush_rotation_sec = atan2f(dx, dy) + (float)M_PI;
333
334                 if (brush->flag & BRUSH_EDGE_TO_EDGE) {
335                         halfway[0] = dx * 0.5f + stroke->initial_mouse[0];
336                         halfway[1] = dy * 0.5f + stroke->initial_mouse[1];
337
338                         if (stroke->get_location) {
339                                 if (stroke->get_location(C, location, halfway)) {
340                                         hit = true;
341                                         location_sampled = true;
342                                         location_success = true;
343                                 }
344                                 else if (!paint_tool_require_location(brush, mode)) {
345                                         hit = true;
346                                 }
347                         }
348                         else {
349                                 hit = true;
350                         }
351                 }
352                 if (hit) {
353                         copy_v2_v2(ups->anchored_initial_mouse, halfway);
354                         copy_v2_v2(ups->tex_mouse, halfway);
355                         copy_v2_v2(ups->mask_tex_mouse, halfway);
356                         copy_v2_v2(mouse, halfway);
357                         ups->anchored_size /= 2.0f;
358                         ups->pixel_radius  /= 2.0f;
359                         stroke->stroke_distance = ups->pixel_radius;
360                 }
361                 else {
362                         copy_v2_v2(ups->anchored_initial_mouse, stroke->initial_mouse);
363                         copy_v2_v2(mouse, stroke->initial_mouse);
364                         stroke->stroke_distance = ups->pixel_radius;
365                 }
366                 ups->pixel_radius /= stroke->zoom_2d;
367                 ups->draw_anchored = true;
368         }
369         else {
370                 /* here we are using the initial mouse coordinate because we do not want the rake
371                  * result to depend on jittering */
372                 if (!stroke->brush_init) {
373                         copy_v2_v2(ups->last_rake, mouse_init);
374                 }
375                 /* curve strokes do their own rake calculation */
376                 else if (!(brush->flag & BRUSH_CURVE)) {
377                         if (!paint_calculate_rake_rotation(ups, brush, mouse_init)) {
378                                 /* Not enough motion to define an angle. */
379                                 is_dry_run = true;
380                         }
381                 }
382         }
383
384         if (do_random) {
385                 if (brush->mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) {
386                         ups->brush_rotation += -brush->mtex.random_angle / 2.0f +
387                                                brush->mtex.random_angle * BLI_frand();
388                 }
389         }
390
391         if (do_random_mask) {
392                 if (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) {
393                         ups->brush_rotation_sec += -brush->mask_mtex.random_angle / 2.0f +
394                                                    brush->mask_mtex.random_angle * BLI_frand();
395                 }
396         }
397
398         if (!location_sampled) {
399                 if (stroke->get_location) {
400                         if (stroke->get_location(C, location, mouse))
401                                 location_success = true;
402                         else if (!paint_tool_require_location(brush, mode))
403                                 location_success = true;
404                 }
405                 else {
406                         zero_v3(location);
407                         location_success = true;
408                 }
409         }
410
411         return location_success && (is_dry_run == false);
412 }
413
414 static bool paint_stroke_use_jitter(ePaintMode mode, Brush *brush, bool invert)
415 {
416         bool use_jitter = (brush->flag & BRUSH_ABSOLUTE_JITTER) ?
417                 (brush->jitter_absolute != 0) : (brush->jitter != 0);
418
419         /* jitter-ed brush gives weird and unpredictable result for this
420          * kinds of stroke, so manually disable jitter usage (sergey) */
421         use_jitter &= (brush->flag & (BRUSH_DRAG_DOT | BRUSH_ANCHORED)) == 0;
422         use_jitter &= (!ELEM(mode, ePaintTexture2D, ePaintTextureProjective) ||
423                        !(invert && brush->imagepaint_tool == PAINT_TOOL_CLONE));
424
425
426         return use_jitter;
427 }
428
429 /* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */
430 static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float mouse_in[2], float pressure)
431 {
432         Scene *scene = CTX_data_scene(C);
433         Paint *paint = BKE_paint_get_active_from_context(C);
434         ePaintMode mode = BKE_paintmode_get_active_from_context(C);
435         Brush *brush = BKE_paint_brush(paint);
436         PaintStroke *stroke = op->customdata;
437         UnifiedPaintSettings *ups = stroke->ups;
438         float mouse_out[2];
439         PointerRNA itemptr;
440         float location[3];
441
442 /* the following code is adapted from texture paint. It may not be needed but leaving here
443  * just in case for reference (code in texpaint removed as part of refactoring).
444  * It's strange that only texpaint had these guards. */
445 #if 0
446         /* special exception here for too high pressure values on first touch in
447          * windows for some tablets, then we just skip first touch ..  */
448         if (tablet && (pressure >= 0.99f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || BKE_brush_use_alpha_pressure(scene, pop->s.brush) || BKE_brush_use_size_pressure(scene, pop->s.brush)))
449                 return;
450
451         /* This can be removed once fixed properly in
452          * BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user)
453          * at zero pressure we should do nothing 1/2^12 is 0.0002 which is the sensitivity of the most sensitive pen tablet available */
454         if (tablet && (pressure < 0.0002f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || BKE_brush_use_alpha_pressure(scene, pop->s.brush) || BKE_brush_use_size_pressure(scene, pop->s.brush)))
455                 return;
456 #endif
457
458         /* copy last position -before- jittering, or space fill code
459          * will create too many dabs */
460         copy_v2_v2(stroke->last_mouse_position, mouse_in);
461         stroke->last_pressure = pressure;
462
463         if (paint_stroke_use_jitter(mode, brush, stroke->stroke_mode == BRUSH_STROKE_INVERT)) {
464                 float delta[2];
465                 float factor = stroke->zoom_2d;
466
467                 if (brush->flag & BRUSH_JITTER_PRESSURE)
468                         factor *= pressure;
469
470                 BKE_brush_jitter_pos(scene, brush, mouse_in, mouse_out);
471
472                 /* XXX: meh, this is round about because
473                  * BKE_brush_jitter_pos isn't written in the best way to
474                  * be reused here */
475                 if (factor != 1.0f) {
476                         sub_v2_v2v2(delta, mouse_out, mouse_in);
477                         mul_v2_fl(delta, factor);
478                         add_v2_v2v2(mouse_out, mouse_in, delta);
479                 }
480         }
481         else {
482                 copy_v2_v2(mouse_out, mouse_in);
483         }
484
485
486         ups->last_hit = paint_brush_update(C, brush, mode, stroke, mouse_in, mouse_out, pressure, location);
487         copy_v3_v3(ups->last_location, location);
488         if (!ups->last_hit) {
489                 return;
490         }
491
492         /* Add to stroke */
493         RNA_collection_add(op->ptr, "stroke", &itemptr);
494         RNA_float_set(&itemptr, "size", ups->pixel_radius);
495         RNA_float_set_array(&itemptr, "location", location);
496         RNA_float_set_array(&itemptr, "mouse", mouse_out);
497         RNA_boolean_set(&itemptr, "pen_flip", stroke->pen_flip);
498         RNA_float_set(&itemptr, "pressure", pressure);
499
500         stroke->update_step(C, stroke, &itemptr);
501
502         /* don't record this for now, it takes up a lot of memory when doing long
503          * strokes with small brush size, and operators have register disabled */
504         RNA_collection_clear(op->ptr, "stroke");
505 }
506
507 /* Returns zero if no sculpt changes should be made, non-zero otherwise */
508 static bool paint_smooth_stroke(
509         PaintStroke *stroke, const PaintSample *sample, ePaintMode mode,
510         float r_mouse[2], float *r_pressure)
511 {
512         if (paint_supports_smooth_stroke(stroke->brush, mode)) {
513                 float radius = stroke->brush->smooth_stroke_radius * stroke->zoom_2d;
514                 float u = stroke->brush->smooth_stroke_factor;
515
516                 /* If the mouse is moving within the radius of the last move,
517                  * don't update the mouse position. This allows sharp turns. */
518                 if (len_squared_v2v2(stroke->last_mouse_position, sample->mouse) < SQUARE(radius)) {
519                         return false;
520                 }
521
522                 interp_v2_v2v2(r_mouse, sample->mouse, stroke->last_mouse_position, u);
523                 *r_pressure = interpf(sample->pressure, stroke->last_pressure, u);
524         }
525         else {
526                 r_mouse[0] = sample->mouse[0];
527                 r_mouse[1] = sample->mouse[1];
528                 *r_pressure = sample->pressure;
529         }
530
531         return true;
532 }
533
534 static float paint_space_stroke_spacing(const Scene *scene, PaintStroke *stroke, float size_pressure, float spacing_pressure)
535 {
536         /* brushes can have a minimum size of 1.0 but with pressure it can be smaller then a pixel
537          * causing very high step sizes, hanging blender [#32381] */
538         const float size_clamp = max_ff(1.0f, BKE_brush_size_get(scene, stroke->brush) * size_pressure);
539         float spacing = stroke->brush->spacing;
540
541         /* apply spacing pressure */
542         if (stroke->brush->flag & BRUSH_SPACING_PRESSURE)
543                 spacing = spacing * (1.5f - spacing_pressure);
544
545         /* stroke system is used for 2d paint too, so we need to account for
546          * the fact that brush can be scaled there. */
547         spacing *= stroke->zoom_2d;
548
549         return max_ff(1.0, size_clamp * spacing / 50.0f);
550 }
551
552
553
554 static float paint_stroke_overlapped_curve(Brush *br, float x, float spacing)
555 {
556         int i;
557         const int n = 100 / spacing;
558         const float h = spacing / 50.0f;
559         const float x0 = x - 1;
560
561         float sum;
562
563         sum = 0;
564         for (i = 0; i < n; i++) {
565                 float xx;
566
567                 xx = fabsf(x0 + i * h);
568
569                 if (xx < 1.0f)
570                         sum += BKE_brush_curve_strength(br, xx, 1);
571         }
572
573         return sum;
574 }
575
576 static float paint_stroke_integrate_overlap(Brush *br, float factor)
577 {
578         int i;
579         int m;
580         float g;
581         float max;
582
583         float spacing = br->spacing * factor;
584
585         if (!(br->flag & BRUSH_SPACE_ATTEN && (br->spacing < 100)))
586                 return 1.0;
587
588         m = 10;
589         g = 1.0f / m;
590         max = 0;
591         for (i = 0; i < m; i++) {
592                 float overlap = fabs(paint_stroke_overlapped_curve(br, i * g, spacing));
593
594                 if (overlap > max)
595                         max = overlap;
596         }
597
598         if (max == 0.0f)
599                 return 1.0f;
600         else
601                 return 1.0f / max;
602 }
603
604 static float paint_space_stroke_spacing_variable(const Scene *scene, PaintStroke *stroke, float pressure, float dpressure, float length)
605 {
606         if (BKE_brush_use_size_pressure(scene, stroke->brush)) {
607                 /* use pressure to modify size. set spacing so that at 100%, the circles
608                  * are aligned nicely with no overlap. for this the spacing needs to be
609                  * the average of the previous and next size. */
610                 float s = paint_space_stroke_spacing(scene, stroke, 1.0f, pressure);
611                 float q = s * dpressure / (2.0f * length);
612                 float pressure_fac = (1.0f + q) / (1.0f - q);
613
614                 float last_size_pressure = stroke->last_pressure;
615                 float new_size_pressure = stroke->last_pressure * pressure_fac;
616
617                 /* average spacing */
618                 float last_spacing = paint_space_stroke_spacing(scene, stroke, last_size_pressure, pressure);
619                 float new_spacing = paint_space_stroke_spacing(scene, stroke, new_size_pressure, pressure);
620
621                 return 0.5f * (last_spacing + new_spacing);
622         }
623         else {
624                 /* no size pressure */
625                 return paint_space_stroke_spacing(scene, stroke, 1.0f, pressure);
626         }
627 }
628
629 /* For brushes with stroke spacing enabled, moves mouse in steps
630  * towards the final mouse location. */
631 static int paint_space_stroke(bContext *C, wmOperator *op, const float final_mouse[2], float final_pressure)
632 {
633         const Scene *scene = CTX_data_scene(C);
634         PaintStroke *stroke = op->customdata;
635         UnifiedPaintSettings *ups = stroke->ups;
636         int cnt = 0;
637
638         float pressure, dpressure;
639         float mouse[2], dmouse[2];
640         float length;
641         float no_pressure_spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
642
643         sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position);
644
645         pressure = stroke->last_pressure;
646         dpressure = final_pressure - stroke->last_pressure;
647
648         length = normalize_v2(dmouse);
649
650         while (length > 0.0f) {
651                 float spacing = paint_space_stroke_spacing_variable(scene, stroke, pressure, dpressure, length);
652
653                 if (length >= spacing) {
654                         mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing;
655                         mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing;
656                         pressure = stroke->last_pressure + (spacing / length) * dpressure;
657
658                         ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, spacing / no_pressure_spacing);
659
660                         stroke->stroke_distance += spacing / stroke->zoom_2d;
661                         paint_brush_stroke_add_step(C, op, mouse, pressure);
662
663                         length -= spacing;
664                         pressure = stroke->last_pressure;
665                         dpressure = final_pressure - stroke->last_pressure;
666
667                         cnt++;
668                 }
669                 else {
670                         break;
671                 }
672         }
673
674         return cnt;
675 }
676
677 /**** Public API ****/
678
679 PaintStroke *paint_stroke_new(bContext *C,
680                               wmOperator *op,
681                               StrokeGetLocation get_location,
682                               StrokeTestStart test_start,
683                               StrokeUpdateStep update_step,
684                               StrokeRedraw redraw,
685                               StrokeDone done, int event_type)
686 {
687         PaintStroke *stroke = MEM_callocN(sizeof(PaintStroke), "PaintStroke");
688         ToolSettings *toolsettings = CTX_data_tool_settings(C);
689         UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings;
690         Paint *p = BKE_paint_get_active_from_context(C);
691         Brush *br = stroke->brush = BKE_paint_brush(p);
692         float zoomx, zoomy;
693
694         view3d_set_viewcontext(C, &stroke->vc);
695
696         stroke->get_location = get_location;
697         stroke->test_start = test_start;
698         stroke->update_step = update_step;
699         stroke->redraw = redraw;
700         stroke->done = done;
701         stroke->event_type = event_type; /* for modal, return event */
702         stroke->ups = ups;
703         stroke->stroke_mode = RNA_enum_get(op->ptr, "mode");
704
705         get_imapaint_zoom(C, &zoomx, &zoomy);
706         stroke->zoom_2d = max_ff(zoomx, zoomy);
707
708         if (stroke->stroke_mode == BRUSH_STROKE_INVERT) {
709                 if (br->flag & (BRUSH_CURVE)) {
710                         RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL);
711                 }
712         }
713         /* initialize here */
714         ups->overlap_factor = 1.0;
715         ups->stroke_active = true;
716         
717         zero_v3(ups->average_stroke_accum);
718         ups->average_stroke_counter = 0;
719         
720         /* initialize here to avoid initialization conflict with threaded strokes */
721         curvemapping_initialize(br->curve);
722         if (p->flags & PAINT_USE_CAVITY_MASK)
723                 curvemapping_initialize(p->cavity_curve);
724
725         BKE_paint_set_overlay_override(br->overlay_flags);
726
727         return stroke;
728 }
729
730 void paint_stroke_data_free(struct wmOperator *op)
731 {
732         BKE_paint_set_overlay_override(0);
733         MEM_SAFE_FREE(op->customdata);
734 }
735
736 static void stroke_done(struct bContext *C, struct wmOperator *op)
737 {
738         struct PaintStroke *stroke = op->customdata;
739         UnifiedPaintSettings *ups = stroke->ups;
740
741         ups->draw_anchored = false;
742         ups->stroke_active = false;
743
744         /* reset rotation here to avoid doing so in cursor display */
745         if (!(stroke->brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE))
746                 ups->brush_rotation = 0.0f;
747
748         if (!(stroke->brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE))
749                 ups->brush_rotation_sec = 0.0f;
750
751         if (stroke->stroke_started) {
752                 if (stroke->redraw)
753                         stroke->redraw(C, stroke, true);
754
755                 if (stroke->done)
756                         stroke->done(C, stroke);
757         }
758
759         if (stroke->timer) {
760                 WM_event_remove_timer(
761                         CTX_wm_manager(C),
762                         CTX_wm_window(C),
763                         stroke->timer);
764         }
765
766         if (stroke->stroke_cursor)
767                 WM_paint_cursor_end(CTX_wm_manager(C), stroke->stroke_cursor);
768
769         BLI_freelistN(&stroke->line);
770
771         paint_stroke_data_free(op);
772 }
773
774 /* Returns zero if the stroke dots should not be spaced, non-zero otherwise */
775 bool paint_space_stroke_enabled(Brush *br, ePaintMode mode)
776 {
777         return (br->flag & BRUSH_SPACE) && paint_supports_dynamic_size(br, mode);
778 }
779
780 static bool sculpt_is_grab_tool(Brush *br)
781 {
782         return ELEM(br->sculpt_tool,
783                      SCULPT_TOOL_GRAB,
784                      SCULPT_TOOL_THUMB,
785                      SCULPT_TOOL_ROTATE,
786                      SCULPT_TOOL_SNAKE_HOOK);
787 }
788
789 /* return true if the brush size can change during paint (normally used for pressure) */
790 bool paint_supports_dynamic_size(Brush *br, ePaintMode mode)
791 {
792         if (br->flag & BRUSH_ANCHORED)
793                 return false;
794
795         switch (mode) {
796                 case ePaintSculpt:
797                         if (sculpt_is_grab_tool(br))
798                                 return false;
799                         break;
800
801                 case ePaintTexture2D: /* fall through */
802                 case ePaintTextureProjective:
803                         if ((br->imagepaint_tool == PAINT_TOOL_FILL) &&
804                             (br->flag & BRUSH_USE_GRADIENT))
805                         {
806                                 return false;
807                         }
808                         break;
809
810                 default:
811                         break;
812         }
813         return true;
814 }
815
816 bool paint_supports_smooth_stroke(Brush *br, ePaintMode mode)
817 {
818         if (!(br->flag & BRUSH_SMOOTH_STROKE) ||
819             (br->flag & (BRUSH_ANCHORED | BRUSH_DRAG_DOT | BRUSH_LINE)))
820         {
821                 return false;
822         }
823
824         switch (mode) {
825                 case ePaintSculpt:
826                         if (sculpt_is_grab_tool(br))
827                                 return false;
828                         break;
829                 default:
830                         break;
831         }
832         return true;
833 }
834
835 bool paint_supports_texture(ePaintMode mode)
836 {
837         /* omit: PAINT_WEIGHT, PAINT_SCULPT_UV, PAINT_INVALID */
838         return ELEM(mode, ePaintSculpt, ePaintVertex, ePaintTextureProjective, ePaintTexture2D);
839 }
840
841 /* return true if the brush size can change during paint (normally used for pressure) */
842 bool paint_supports_dynamic_tex_coords(Brush *br, ePaintMode mode)
843 {
844         if (br->flag & BRUSH_ANCHORED)
845                 return false;
846
847         switch (mode) {
848                 case ePaintSculpt:
849                         if (sculpt_is_grab_tool(br))
850                                 return false;
851                         break;
852                 default:
853                         break;
854         }
855         return true;
856 }
857
858 #define PAINT_STROKE_MODAL_CANCEL 1
859
860 /* called in paint_ops.c, on each regeneration of keymaps  */
861 struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf)
862 {
863         static struct EnumPropertyItem modal_items[] = {
864                 {PAINT_STROKE_MODAL_CANCEL, "CANCEL", 0,
865                 "Cancel",
866                 "Cancel and undo a stroke in progress"},
867
868                 { 0 }
869         };
870
871         static const char *name = "Paint Stroke Modal";
872
873         struct wmKeyMap *keymap = WM_modalkeymap_get(keyconf, name);
874
875         /* this function is called for each spacetype, only needs to add map once */
876         if (!keymap) {
877                 keymap = WM_modalkeymap_add(keyconf, name, modal_items);
878
879                 /* items for modal map */
880                 WM_modalkeymap_add_item(
881                         keymap, ESCKEY, KM_PRESS, KM_ANY, 0, PAINT_STROKE_MODAL_CANCEL);
882         }
883
884         return keymap;
885 }
886
887 static void paint_stroke_add_sample(const Paint *paint,
888                                     PaintStroke *stroke,
889                                     float x, float y, float pressure)
890 {
891         PaintSample *sample = &stroke->samples[stroke->cur_sample];
892         int max_samples = CLAMPIS(paint->num_input_samples, 1, PAINT_MAX_INPUT_SAMPLES);
893
894         sample->mouse[0] = x;
895         sample->mouse[1] = y;
896         sample->pressure = pressure;
897
898         stroke->cur_sample++;
899         if (stroke->cur_sample >= max_samples)
900                 stroke->cur_sample = 0;
901         if (stroke->num_samples < max_samples)
902                 stroke->num_samples++;
903 }
904
905 static void paint_stroke_sample_average(const PaintStroke *stroke,
906                                         PaintSample *average)
907 {
908         int i;
909         
910         memset(average, 0, sizeof(*average));
911
912         BLI_assert(stroke->num_samples > 0);
913         
914         for (i = 0; i < stroke->num_samples; i++) {
915                 add_v2_v2(average->mouse, stroke->samples[i].mouse);
916                 average->pressure += stroke->samples[i].pressure;
917         }
918
919         mul_v2_fl(average->mouse, 1.0f / stroke->num_samples);
920         average->pressure /= stroke->num_samples;
921
922         /*printf("avg=(%f, %f), num=%d\n", average->mouse[0], average->mouse[1], stroke->num_samples);*/
923 }
924
925 /**
926  * Slightly different version of spacing for line/curve strokes,
927  * makes sure the dabs stay on the line path.
928  */
929 static void paint_line_strokes_spacing(
930         bContext *C, wmOperator *op, PaintStroke *stroke, float spacing, float *length_residue,
931         const float old_pos[2], const float new_pos[2])
932 {
933         UnifiedPaintSettings *ups = stroke->ups;
934
935         float mouse[2], dmouse[2];
936         float length;
937
938         sub_v2_v2v2(dmouse, new_pos, old_pos);
939         copy_v2_v2(stroke->last_mouse_position, old_pos);
940
941         length = normalize_v2(dmouse);
942
943         BLI_assert(length >= 0.0f);
944
945         if (length == 0.0f)
946                 return;
947
948         while (length > 0.0f) {
949                 float spacing_final = spacing - *length_residue;
950                 length += *length_residue;
951                 *length_residue = 0.0;
952
953                 if (length >= spacing) {
954                         mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing_final;
955                         mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing_final;
956
957                         ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, 1.0);
958
959                         stroke->stroke_distance += spacing / stroke->zoom_2d;
960                         paint_brush_stroke_add_step(C, op, mouse, 1.0);
961
962                         length -= spacing;
963                         spacing_final = spacing;
964                 }
965                 else {
966                         break;
967                 }
968         }
969
970         *length_residue = length;
971 }
972
973
974 static void paint_stroke_line_end(bContext *C, wmOperator *op, PaintStroke *stroke, float mouse[2])
975 {
976         Brush *br = stroke->brush;
977         if (stroke->stroke_started && (br->flag & BRUSH_LINE)) {
978                 stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
979
980                 paint_brush_stroke_add_step(C, op, stroke->last_mouse_position, 1.0);
981                 paint_space_stroke(C, op, mouse, 1.0);
982         }
983 }
984
985 static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *stroke)
986 {
987         Brush *br = stroke->brush;
988
989         if (br->flag & BRUSH_CURVE) {
990                 UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
991                 const Scene *scene = CTX_data_scene(C);
992                 const float spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
993                 PaintCurve *pc = br->paint_curve;
994                 PaintCurvePoint *pcp;
995                 float length_residue = 0.0f;
996                 int i;
997
998                 if (!pc)
999                         return true;
1000
1001 #ifdef DEBUG_TIME
1002                 TIMEIT_START_AVERAGED(whole_stroke);
1003 #endif
1004
1005                 pcp = pc->points;
1006                 stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
1007
1008                 for (i = 0; i < pc->tot_points - 1; i++, pcp++) {
1009                         int j;
1010                         float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
1011                         float tangents[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
1012                         PaintCurvePoint *pcp_next = pcp + 1;
1013                         bool do_rake = false;
1014
1015                         for (j = 0; j < 2; j++) {
1016                                 BKE_curve_forward_diff_bezier(
1017                                         pcp->bez.vec[1][j],
1018                                         pcp->bez.vec[2][j],
1019                                         pcp_next->bez.vec[0][j],
1020                                         pcp_next->bez.vec[1][j],
1021                                         data + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
1022                         }
1023
1024                         if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) ||
1025                             (br->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE))
1026                         {
1027                                 do_rake = true;
1028                                 for (j = 0; j < 2; j++) {
1029                                         BKE_curve_forward_diff_tangent_bezier(
1030                                                 pcp->bez.vec[1][j],
1031                                                 pcp->bez.vec[2][j],
1032                                                 pcp_next->bez.vec[0][j],
1033                                                 pcp_next->bez.vec[1][j],
1034                                                 tangents + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
1035                                 }
1036                         }
1037
1038                         for (j = 0; j < PAINT_CURVE_NUM_SEGMENTS; j++) {
1039                                 if (do_rake) {
1040                                         float rotation = atan2f(tangents[2 * j], tangents[2 * j + 1]);
1041                                         paint_update_brush_rake_rotation(ups, br, rotation);
1042                                 }
1043
1044                                 if (!stroke->stroke_started) {
1045                                         stroke->last_pressure = 1.0;
1046                                         copy_v2_v2(stroke->last_mouse_position, data + 2 * j);
1047                                         stroke->stroke_started = stroke->test_start(C, op, stroke->last_mouse_position);
1048
1049                                         if (stroke->stroke_started) {
1050                                                 paint_brush_stroke_add_step(C, op, data + 2 * j, 1.0);
1051                                                 paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
1052                                         }
1053                                 }
1054                                 else {
1055                                         paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
1056                                 }
1057                         }
1058                 }
1059
1060                 stroke_done(C, op);
1061
1062 #ifdef DEBUG_TIME
1063                 TIMEIT_END_AVERAGED(whole_stroke);
1064 #endif
1065
1066                 return true;
1067         }
1068
1069         return false;
1070 }
1071
1072 static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2])
1073 {
1074         if (stroke->constrain_line) {
1075                 float line[2];
1076                 float angle, len, res;
1077                 
1078                 sub_v2_v2v2(line, mouse, stroke->last_mouse_position);
1079                 angle = atan2f(line[1], line[0]);
1080                 len = len_v2(line);
1081                 
1082                 /* divide angle by PI/4 */
1083                 angle = 4.0f * angle / (float)M_PI;
1084                 
1085                 /* now take residue */
1086                 res = angle - floorf(angle);
1087                 
1088                 /* residue decides how close we are at a certain angle */
1089                 if (res <= 0.5f) {
1090                         angle = floorf(angle) * (float)M_PI_4;
1091                 }
1092                 else {
1093                         angle = (floorf(angle) + 1.0f) * (float)M_PI_4;
1094                 }
1095                 
1096                 mouse[0] = stroke->constrained_pos[0] = len * cosf(angle) + stroke->last_mouse_position[0];
1097                 mouse[1] = stroke->constrained_pos[1] = len * sinf(angle) + stroke->last_mouse_position[1];
1098         }
1099 }
1100
1101 int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
1102 {
1103         Paint *p = BKE_paint_get_active_from_context(C);
1104         ePaintMode mode = BKE_paintmode_get_active_from_context(C);
1105         PaintStroke *stroke = op->customdata;
1106         Brush *br = stroke->brush;
1107         PaintSample sample_average;
1108         float mouse[2];
1109         bool first_dab = false;
1110         bool first_modal = false;
1111         bool redraw = false;
1112         float pressure;
1113
1114         /* see if tablet affects event. Line, anchored and drag dot strokes do not support pressure */
1115         pressure = (br->flag & (BRUSH_LINE | BRUSH_ANCHORED | BRUSH_DRAG_DOT)) ? 1.0f : WM_event_tablet_data(event, &stroke->pen_flip, NULL);
1116
1117         paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1], pressure);
1118         paint_stroke_sample_average(stroke, &sample_average);
1119
1120 #ifdef WITH_INPUT_NDOF
1121         /* let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously!
1122          * this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it
1123          * since the 2D deltas are zero -- code in this file needs to be updated to use the
1124          * post-NDOF_MOTION MOUSEMOVE */
1125         if (event->type == NDOF_MOTION)
1126                 return OPERATOR_PASS_THROUGH;
1127 #endif
1128
1129         /* one time initialization */
1130         if (!stroke->stroke_init) {
1131                 if (paint_stroke_curve_end(C, op, stroke))
1132                         return OPERATOR_FINISHED;
1133
1134                 if (paint_supports_smooth_stroke(br, mode))
1135                         stroke->stroke_cursor =
1136                             WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_smooth_cursor, stroke);
1137
1138                 stroke->stroke_init = true;
1139                 first_modal = true;
1140         }
1141
1142         /* one time stroke initialization */
1143         if (!stroke->stroke_started) {
1144                 stroke->last_pressure = sample_average.pressure;
1145                 copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
1146                 stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse);
1147                 BLI_assert((stroke->stroke_started & ~1) == 0);  /* 0/1 */
1148
1149                 if (stroke->stroke_started) {
1150                         if (br->flag & BRUSH_AIRBRUSH)
1151                                 stroke->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, stroke->brush->rate);
1152
1153                         if (br->flag & BRUSH_LINE) {
1154                                 stroke->stroke_cursor =
1155                                         WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_line_cursor, stroke);
1156                         }
1157
1158                         first_dab = true;
1159                 }
1160         }
1161
1162         /* Cancel */
1163         if (event->type == EVT_MODAL_MAP && event->val == PAINT_STROKE_MODAL_CANCEL) {
1164                 if (op->type->cancel) {
1165                         op->type->cancel(C, op);
1166                 }
1167                 else {
1168                         paint_stroke_cancel(C, op);
1169                 }
1170                 return OPERATOR_CANCELLED;
1171         }
1172
1173         if (event->type == stroke->event_type && !first_modal) {
1174                 if (event->val == KM_RELEASE) {
1175                         copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
1176                         paint_stroke_line_constrain(stroke, mouse);
1177                         paint_stroke_line_end(C, op, stroke, mouse);
1178                         stroke_done(C, op);
1179                         return OPERATOR_FINISHED;
1180                 }
1181         }
1182         else if (ELEM(event->type, RETKEY, SPACEKEY)) {
1183                 paint_stroke_line_end(C, op, stroke, sample_average.mouse);
1184                 stroke_done(C, op);
1185                 return OPERATOR_FINISHED;
1186         }
1187         else if (br->flag & BRUSH_LINE) {
1188                 if (event->alt)
1189                         stroke->constrain_line = true;
1190                 else 
1191                         stroke->constrain_line = false;
1192
1193                 copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
1194                 paint_stroke_line_constrain(stroke, mouse);
1195                 
1196                 if (stroke->stroke_started && (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)))) {
1197                         if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) || (br->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) {
1198                                 copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position);
1199                         }
1200                         paint_calculate_rake_rotation(stroke->ups, br, mouse);
1201                 }
1202         }
1203         else if (first_modal ||
1204                  /* regular dabs */
1205                  (!(br->flag & (BRUSH_AIRBRUSH)) && (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))) ||
1206                  /* airbrush */
1207                  ((br->flag & BRUSH_AIRBRUSH) && event->type == TIMER && event->customdata == stroke->timer))
1208         {
1209                 if (paint_smooth_stroke(stroke, &sample_average, mode, mouse, &pressure)) {
1210                         if (stroke->stroke_started) {
1211                                 if (paint_space_stroke_enabled(br, mode)) {
1212                                         if (paint_space_stroke(C, op, mouse, pressure))
1213                                                 redraw = true;
1214                                 }
1215                                 else {
1216                                         float dmouse[2];
1217                                         sub_v2_v2v2(dmouse, mouse, stroke->last_mouse_position);
1218                                         stroke->stroke_distance += len_v2(dmouse);
1219                                         paint_brush_stroke_add_step(C, op, mouse, pressure);
1220                                         redraw = true;
1221                                 }
1222                         }
1223                 }
1224         }
1225
1226         /* we want the stroke to have the first daub at the start location
1227          * instead of waiting till we have moved the space distance */
1228         if (first_dab &&
1229             paint_space_stroke_enabled(br, mode) &&
1230             !(br->flag & BRUSH_SMOOTH_STROKE))
1231         {
1232                 stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, 1.0);
1233                 paint_brush_stroke_add_step(C, op, sample_average.mouse, sample_average.pressure);
1234                 redraw = true;
1235         }
1236
1237         /* do updates for redraw. if event is inbetween mousemove there are more
1238          * coming, so postpone potentially slow redraw updates until all are done */
1239         if (event->type != INBETWEEN_MOUSEMOVE) {
1240                 wmWindow *window = CTX_wm_window(C);
1241                 ARegion *ar = CTX_wm_region(C);
1242
1243                 /* At the very least, invalidate the cursor */
1244                 if (ar && (p->flags & PAINT_SHOW_BRUSH))
1245                         WM_paint_cursor_tag_redraw(window, ar);
1246
1247                 if (redraw && stroke->redraw)
1248                         stroke->redraw(C, stroke, false);
1249         }
1250
1251         return OPERATOR_RUNNING_MODAL;
1252 }
1253
1254 int paint_stroke_exec(bContext *C, wmOperator *op)
1255 {
1256         PaintStroke *stroke = op->customdata;
1257
1258         /* only when executed for the first time */
1259         if (stroke->stroke_started == 0) {
1260                 PropertyRNA *strokeprop;
1261                 PointerRNA firstpoint;
1262                 float mouse[2];
1263
1264                 strokeprop = RNA_struct_find_property(op->ptr, "stroke");
1265
1266                 if (RNA_property_collection_lookup_int(op->ptr, strokeprop, 0, &firstpoint)) {
1267                         RNA_float_get_array(&firstpoint, "mouse", mouse);
1268                         stroke->stroke_started = stroke->test_start(C, op, mouse);
1269                 }
1270         }
1271
1272         if (stroke->stroke_started) {
1273                 RNA_BEGIN (op->ptr, itemptr, "stroke")
1274                 {
1275                         stroke->update_step(C, stroke, &itemptr);
1276                 }
1277                 RNA_END;
1278         }
1279
1280         bool ok = (stroke->stroke_started != 0);
1281
1282         stroke_done(C, op);
1283
1284         return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1285 }
1286
1287 void paint_stroke_cancel(bContext *C, wmOperator *op)
1288 {
1289         stroke_done(C, op);
1290 }
1291
1292 ViewContext *paint_stroke_view_context(PaintStroke *stroke)
1293 {
1294         return &stroke->vc;
1295 }
1296
1297 void *paint_stroke_mode_data(struct PaintStroke *stroke)
1298 {
1299         return stroke->mode_data;
1300 }
1301
1302 bool paint_stroke_flipped(struct PaintStroke *stroke)
1303 {
1304         return stroke->pen_flip;
1305 }
1306
1307 float paint_stroke_distance_get(struct PaintStroke *stroke)
1308 {
1309         return stroke->stroke_distance;
1310 }
1311
1312 void paint_stroke_set_mode_data(PaintStroke *stroke, void *mode_data)
1313 {
1314         stroke->mode_data = mode_data;
1315 }
1316
1317 int paint_poll(bContext *C)
1318 {
1319         Paint *p = BKE_paint_get_active_from_context(C);
1320         Object *ob = CTX_data_active_object(C);
1321         ScrArea *sa = CTX_wm_area(C);
1322         ARegion *ar = CTX_wm_region(C);
1323
1324         return p && ob && BKE_paint_brush(p) &&
1325                (sa && ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) &&
1326                (ar && ar->regiontype == RGN_TYPE_WINDOW);
1327 }