Blender  V2.93
paint_stroke.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2009 by Nicholas Bishop
17  * All rights reserved.
18  */
19 
24 #include "MEM_guardedalloc.h"
25 
26 #include "BLI_listbase.h"
27 #include "BLI_math.h"
28 #include "BLI_rand.h"
29 #include "BLI_utildefines.h"
30 
31 #include "PIL_time.h"
32 
33 #include "DNA_brush_types.h"
34 #include "DNA_curve_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_scene_types.h"
37 
38 #include "RNA_access.h"
39 
40 #include "BKE_brush.h"
41 #include "BKE_colortools.h"
42 #include "BKE_context.h"
43 #include "BKE_curve.h"
44 #include "BKE_image.h"
45 #include "BKE_paint.h"
46 
47 #include "WM_api.h"
48 #include "WM_types.h"
49 
50 #include "GPU_immediate.h"
51 #include "GPU_state.h"
52 
53 #include "ED_screen.h"
54 #include "ED_view3d.h"
55 
56 #include "IMB_imbuf_types.h"
57 
58 #include "paint_intern.h"
59 #include "sculpt_intern.h"
60 
61 #include <float.h>
62 #include <math.h>
63 
64 //#define DEBUG_TIME
65 
66 #ifdef DEBUG_TIME
67 # include "PIL_time_utildefines.h"
68 #endif
69 
70 typedef struct PaintSample {
71  float mouse[2];
72  float pressure;
74 
75 typedef struct PaintStroke {
76  void *mode_data;
79  struct RNG *rng;
80 
81  /* Cached values */
85 
86  /* used for lines and curves */
88 
89  /* Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES prior inputs
90  * to smooth the stroke */
95 
99  /* space distance covered so far */
101 
102  /* Set whether any stroke step has yet occurred
103  * e.g. in sculpt mode, stroke doesn't start until cursor
104  * passes over the mesh */
106  /* Set when enough motion was found for rake rotation */
108  /* event that started stroke, for modal() return */
110  /* check if stroke variables have been initialized */
112  /* check if various brush mapping variables have been initialized */
114  float initial_mouse[2];
115  /* cached_pressure stores initial pressure for size pressure influence mainly */
117  /* last pressure will store last pressure value for use in interpolation for space strokes */
120 
122 
123  float zoom_2d;
124  int pen_flip;
125 
126  /* Tilt, as read from the event. */
127  float x_tilt;
128  float y_tilt;
129 
130  /* line constraint */
132  float constrained_pos[2];
133 
140 
141 /*** Cursors ***/
142 static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata)
143 {
145  Brush *brush = BKE_paint_brush(paint);
146  PaintStroke *stroke = customdata;
147 
148  if (stroke && brush) {
149  GPU_line_smooth(true);
151 
152  ARegion *region = stroke->vc.region;
153 
157 
159  immVertex2f(pos, x, y);
161  stroke->last_mouse_position[0] + region->winrct.xmin,
162  stroke->last_mouse_position[1] + region->winrct.ymin);
163 
164  immEnd();
165 
167 
169  GPU_line_smooth(false);
170  }
171 }
172 
173 static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
174 {
176  PaintStroke *stroke = customdata;
177 
178  GPU_line_smooth(true);
179 
180  uint shdr_pos = GPU_vertformat_attr_add(
182 
184 
185  float viewport_size[4];
186  GPU_viewport_size_get_f(viewport_size);
187  immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
188 
189  immUniform1i("colors_len", 2); /* "advanced" mode */
190  const float alpha = (float)paint->paint_cursor_col[3] / 255.0f;
192  "colors", (float *)(float[][4]){{0.0f, 0.0f, 0.0f, alpha}, {1.0f, 1.0f, 1.0f, alpha}}, 2);
193  immUniform1f("dash_width", 6.0f);
194  immUniform1f("dash_factor", 0.5f);
195 
197 
198  ARegion *region = stroke->vc.region;
199 
200  if (stroke->constrain_line) {
201  immVertex2f(shdr_pos,
202  stroke->last_mouse_position[0] + region->winrct.xmin,
203  stroke->last_mouse_position[1] + region->winrct.ymin);
204 
205  immVertex2f(shdr_pos,
206  stroke->constrained_pos[0] + region->winrct.xmin,
207  stroke->constrained_pos[1] + region->winrct.ymin);
208  }
209  else {
210  immVertex2f(shdr_pos,
211  stroke->last_mouse_position[0] + region->winrct.xmin,
212  stroke->last_mouse_position[1] + region->winrct.ymin);
213 
214  immVertex2f(shdr_pos, x, y);
215  }
216 
217  immEnd();
218 
220 
221  GPU_line_smooth(false);
222 }
223 
225 {
226  switch (mode) {
227  case PAINT_MODE_SCULPT:
228  if (ELEM(brush->sculpt_tool,
236  return false;
237  }
238  else if (SCULPT_is_cloth_deform_brush(brush)) {
239  return false;
240  }
241  else {
242  return true;
243  }
244  default:
245  break;
246  }
247 
248  return true;
249 }
250 
252 {
253  switch (mode) {
254  case PAINT_MODE_SCULPT:
255  return brush->flag & BRUSH_SCENE_SPACING;
256  default:
257  break;
258  }
259  return false;
260 }
261 
263 {
264  if (brush->flag & BRUSH_ANCHORED) {
265  return false;
266  }
267 
268  switch (mode) {
269  case PAINT_MODE_SCULPT:
270  if (ELEM(brush->sculpt_tool,
278  SCULPT_TOOL_POSE)) {
279  return false;
280  }
281  else {
282  return true;
283  }
284  default:
285  break;
286  }
287 
288  return true;
289 }
290 
291 /* Initialize the stroke cache variants from operator properties */
293  Brush *brush,
294  ePaintMode mode,
295  struct PaintStroke *stroke,
296  const float mouse_init[2],
297  float mouse[2],
298  float pressure,
299  float r_location[3],
300  bool *r_location_is_set)
301 {
303  UnifiedPaintSettings *ups = stroke->ups;
304  bool location_sampled = false;
305  bool location_success = false;
306  /* Use to perform all operations except applying the stroke,
307  * needed for operations that require cursor motion (rake). */
308  bool is_dry_run = false;
309  bool do_random = false;
310  bool do_random_mask = false;
311  *r_location_is_set = false;
312  /* XXX: Use pressure value from first brush step for brushes which don't
313  * support strokes (grab, thumb). They depends on initial state and
314  * brush coord/pressure/etc.
315  * It's more an events design issue, which doesn't split coordinate/pressure/angle
316  * changing events. We should avoid this after events system re-design */
317  if (!stroke->brush_init) {
318  copy_v2_v2(stroke->initial_mouse, mouse);
319  copy_v2_v2(ups->last_rake, mouse);
320  copy_v2_v2(ups->tex_mouse, mouse);
321  copy_v2_v2(ups->mask_tex_mouse, mouse);
322  stroke->cached_size_pressure = pressure;
323 
324  ups->do_linear_conversion = false;
325  ups->colorspace = NULL;
326 
327  /* check here if color sampling the main brush should do color conversion. This is done here
328  * to avoid locking up to get the image buffer during sampling */
329  if (brush->mtex.tex && brush->mtex.tex->type == TEX_IMAGE && brush->mtex.tex->ima) {
331  brush->mtex.tex->ima, &brush->mtex.tex->iuser, NULL);
332  if (tex_ibuf && tex_ibuf->rect_float == NULL) {
333  ups->do_linear_conversion = true;
334  ups->colorspace = tex_ibuf->rect_colorspace;
335  }
336  BKE_image_pool_release_ibuf(brush->mtex.tex->ima, tex_ibuf, NULL);
337  }
338 
339  stroke->brush_init = true;
340  }
341 
342  if (paint_supports_dynamic_size(brush, mode)) {
343  copy_v2_v2(ups->tex_mouse, mouse);
344  copy_v2_v2(ups->mask_tex_mouse, mouse);
345  stroke->cached_size_pressure = pressure;
346  }
347 
348  /* Truly temporary data that isn't stored in properties */
349 
350  ups->stroke_active = true;
352 
353  ups->pixel_radius = BKE_brush_size_get(scene, brush);
355 
356  if (BKE_brush_use_size_pressure(brush) && paint_supports_dynamic_size(brush, mode)) {
357  ups->pixel_radius *= stroke->cached_size_pressure;
358  }
359 
360  if (paint_supports_dynamic_tex_coords(brush, mode)) {
361 
362  if (ELEM(brush->mtex.brush_map_mode,
366  do_random = true;
367  }
368 
369  if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM) {
371  }
372  else {
373  copy_v2_v2(ups->tex_mouse, mouse);
374  }
375 
376  /* take care of mask texture, if any */
377  if (brush->mask_mtex.tex) {
378 
379  if (ELEM(brush->mask_mtex.brush_map_mode,
383  do_random_mask = true;
384  }
385 
388  }
389  else {
390  copy_v2_v2(ups->mask_tex_mouse, mouse);
391  }
392  }
393  }
394 
395  if (brush->flag & BRUSH_ANCHORED) {
396  bool hit = false;
397  float halfway[2];
398 
399  const float dx = mouse[0] - stroke->initial_mouse[0];
400  const float dy = mouse[1] - stroke->initial_mouse[1];
401 
402  ups->anchored_size = ups->pixel_radius = sqrtf(dx * dx + dy * dy);
403 
404  ups->brush_rotation = ups->brush_rotation_sec = atan2f(dx, dy) + (float)M_PI;
405 
406  if (brush->flag & BRUSH_EDGE_TO_EDGE) {
407  halfway[0] = dx * 0.5f + stroke->initial_mouse[0];
408  halfway[1] = dy * 0.5f + stroke->initial_mouse[1];
409 
410  if (stroke->get_location) {
411  if (stroke->get_location(C, r_location, halfway)) {
412  hit = true;
413  location_sampled = true;
414  location_success = true;
415  *r_location_is_set = true;
416  }
417  else if (!paint_tool_require_location(brush, mode)) {
418  hit = true;
419  }
420  }
421  else {
422  hit = true;
423  }
424  }
425  if (hit) {
426  copy_v2_v2(ups->anchored_initial_mouse, halfway);
427  copy_v2_v2(ups->tex_mouse, halfway);
428  copy_v2_v2(ups->mask_tex_mouse, halfway);
429  copy_v2_v2(mouse, halfway);
430  ups->anchored_size /= 2.0f;
431  ups->pixel_radius /= 2.0f;
432  stroke->stroke_distance = ups->pixel_radius;
433  }
434  else {
436  copy_v2_v2(mouse, stroke->initial_mouse);
437  stroke->stroke_distance = ups->pixel_radius;
438  }
439  ups->pixel_radius /= stroke->zoom_2d;
440  ups->draw_anchored = true;
441  }
442  else {
443  /* here we are using the initial mouse coordinate because we do not want the rake
444  * result to depend on jittering */
445  if (!stroke->brush_init) {
446  copy_v2_v2(ups->last_rake, mouse_init);
447  }
448  /* curve strokes do their own rake calculation */
449  else if (!(brush->flag & BRUSH_CURVE)) {
450  if (!paint_calculate_rake_rotation(ups, brush, mouse_init)) {
451  /* Not enough motion to define an angle. */
452  if (!stroke->rake_started) {
453  is_dry_run = true;
454  }
455  }
456  else {
457  stroke->rake_started = true;
458  }
459  }
460  }
461 
462  if ((do_random || do_random_mask) && stroke->rng == NULL) {
463  /* Lazy initialization. */
464  uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
465  rng_seed ^= (uint)POINTER_AS_INT(brush);
466  stroke->rng = BLI_rng_new(rng_seed);
467  }
468 
469  if (do_random) {
470  if (brush->mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) {
471  ups->brush_rotation += -brush->mtex.random_angle / 2.0f +
472  brush->mtex.random_angle * BLI_rng_get_float(stroke->rng);
473  }
474  }
475 
476  if (do_random_mask) {
478  ups->brush_rotation_sec += -brush->mask_mtex.random_angle / 2.0f +
479  brush->mask_mtex.random_angle * BLI_rng_get_float(stroke->rng);
480  }
481  }
482 
483  if (!location_sampled) {
484  if (stroke->get_location) {
485  if (stroke->get_location(C, r_location, mouse)) {
486  location_success = true;
487  *r_location_is_set = true;
488  }
489  else if (!paint_tool_require_location(brush, mode)) {
490  location_success = true;
491  }
492  }
493  else {
494  zero_v3(r_location);
495  location_success = true;
496  /* don't set 'r_location_is_set', since we don't want to use the value. */
497  }
498  }
499 
500  return location_success && (is_dry_run == false);
501 }
502 
503 static bool paint_stroke_use_dash(Brush *brush)
504 {
505  /* Only these stroke modes support dash lines */
506  return brush->flag & BRUSH_SPACE || brush->flag & BRUSH_LINE || brush->flag & BRUSH_CURVE;
507 }
508 
509 static bool paint_stroke_use_jitter(ePaintMode mode, Brush *brush, bool invert)
510 {
511  bool use_jitter = (brush->flag & BRUSH_ABSOLUTE_JITTER) ? (brush->jitter_absolute != 0) :
512  (brush->jitter != 0);
513 
514  /* jitter-ed brush gives weird and unpredictable result for this
515  * kinds of stroke, so manually disable jitter usage (sergey) */
516  use_jitter &= (brush->flag & (BRUSH_DRAG_DOT | BRUSH_ANCHORED)) == 0;
517  use_jitter &= (!ELEM(mode, PAINT_MODE_TEXTURE_2D, PAINT_MODE_TEXTURE_3D) ||
518  !(invert && brush->imagepaint_tool == PAINT_TOOL_CLONE));
519 
520  return use_jitter;
521 }
522 
523 /* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */
525  wmOperator *op,
526  const float mouse_in[2],
527  float pressure)
528 {
532  Brush *brush = BKE_paint_brush(paint);
533  PaintStroke *stroke = op->customdata;
534  UnifiedPaintSettings *ups = stroke->ups;
535  float mouse_out[2];
536  PointerRNA itemptr;
537  float location[3];
538 
539 /* the following code is adapted from texture paint. It may not be needed but leaving here
540  * just in case for reference (code in texpaint removed as part of refactoring).
541  * It's strange that only texpaint had these guards. */
542 #if 0
543  /* special exception here for too high pressure values on first touch in
544  * windows for some tablets, then we just skip first touch .. */
545  if (tablet && (pressure >= 0.99f) &&
546  ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) ||
547  BKE_brush_use_alpha_pressure(pop->s.brush) ||
548  BKE_brush_use_size_pressure(pop->s.brush))) {
549  return;
550  }
551 
552  /* This can be removed once fixed properly in
553  * BKE_brush_painter_paint(
554  * BrushPainter *painter, BrushFunc func,
555  * float *pos, double time, float pressure, void *user);
556  * at zero pressure we should do nothing 1/2^12 is 0.0002
557  * which is the sensitivity of the most sensitive pen tablet available */
558  if (tablet && (pressure < 0.0002f) &&
559  ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) ||
560  BKE_brush_use_alpha_pressure(pop->s.brush) ||
561  BKE_brush_use_size_pressure(pop->s.brush))) {
562  return;
563  }
564 #endif
565 
566  /* copy last position -before- jittering, or space fill code
567  * will create too many dabs */
568  copy_v2_v2(stroke->last_mouse_position, mouse_in);
569  stroke->last_pressure = pressure;
570 
571  if (paint_stroke_use_scene_spacing(brush, mode)) {
573  mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position);
574  }
575 
576  if (paint_stroke_use_jitter(mode, brush, stroke->stroke_mode == BRUSH_STROKE_INVERT)) {
577  float delta[2];
578  float factor = stroke->zoom_2d;
579 
580  if (brush->flag & BRUSH_JITTER_PRESSURE) {
581  factor *= pressure;
582  }
583 
584  BKE_brush_jitter_pos(scene, brush, mouse_in, mouse_out);
585 
586  /* XXX: meh, this is round about because
587  * BKE_brush_jitter_pos isn't written in the best way to
588  * be reused here */
589  if (factor != 1.0f) {
590  sub_v2_v2v2(delta, mouse_out, mouse_in);
591  mul_v2_fl(delta, factor);
592  add_v2_v2v2(mouse_out, mouse_in, delta);
593  }
594  }
595  else {
596  copy_v2_v2(mouse_out, mouse_in);
597  }
598 
599  bool is_location_is_set;
601  C, brush, mode, stroke, mouse_in, mouse_out, pressure, location, &is_location_is_set);
602  if (is_location_is_set) {
603  copy_v3_v3(ups->last_location, location);
604  }
605  if (!ups->last_hit) {
606  return;
607  }
608 
609  /* Dash */
610  bool add_step = true;
611  if (paint_stroke_use_dash(brush)) {
612  int dash_samples = stroke->tot_samples % brush->dash_samples;
613  float dash = (float)dash_samples / (float)brush->dash_samples;
614  if (dash > brush->dash_ratio) {
615  add_step = false;
616  }
617  }
618 
619  /* Add to stroke */
620  if (add_step) {
621  RNA_collection_add(op->ptr, "stroke", &itemptr);
622  RNA_float_set(&itemptr, "size", ups->pixel_radius);
623  RNA_float_set_array(&itemptr, "location", location);
624  /* Mouse coordinates modified by the stroke type options. */
625  RNA_float_set_array(&itemptr, "mouse", mouse_out);
626  /* Original mouse coordinates. */
627  RNA_float_set_array(&itemptr, "mouse_event", mouse_in);
628  RNA_boolean_set(&itemptr, "pen_flip", stroke->pen_flip);
629  RNA_float_set(&itemptr, "pressure", pressure);
630  RNA_float_set(&itemptr, "x_tilt", stroke->x_tilt);
631  RNA_float_set(&itemptr, "y_tilt", stroke->y_tilt);
632 
633  stroke->update_step(C, stroke, &itemptr);
634 
635  /* don't record this for now, it takes up a lot of memory when doing long
636  * strokes with small brush size, and operators have register disabled */
637  RNA_collection_clear(op->ptr, "stroke");
638  }
639 
640  stroke->tot_samples++;
641 }
642 
643 /* Returns zero if no sculpt changes should be made, non-zero otherwise */
644 static bool paint_smooth_stroke(PaintStroke *stroke,
645  const PaintSample *sample,
646  ePaintMode mode,
647  float r_mouse[2],
648  float *r_pressure)
649 {
650  if (paint_supports_smooth_stroke(stroke->brush, mode)) {
651  float radius = stroke->brush->smooth_stroke_radius * stroke->zoom_2d;
652  float u = stroke->brush->smooth_stroke_factor;
653 
654  /* If the mouse is moving within the radius of the last move,
655  * don't update the mouse position. This allows sharp turns. */
656  if (len_squared_v2v2(stroke->last_mouse_position, sample->mouse) < square_f(radius)) {
657  return false;
658  }
659 
660  interp_v2_v2v2(r_mouse, sample->mouse, stroke->last_mouse_position, u);
661  *r_pressure = interpf(sample->pressure, stroke->last_pressure, u);
662  }
663  else {
664  r_mouse[0] = sample->mouse[0];
665  r_mouse[1] = sample->mouse[1];
666  *r_pressure = sample->pressure;
667  }
668 
669  return true;
670 }
671 
673  const Scene *scene,
674  PaintStroke *stroke,
675  float size_pressure,
676  float spacing_pressure)
677 {
680  Brush *brush = BKE_paint_brush(paint);
681  float size_clamp = 0.0f;
682  float size = BKE_brush_size_get(scene, stroke->brush) * size_pressure;
683  if (paint_stroke_use_scene_spacing(brush, mode)) {
684  if (!BKE_brush_use_locked_size(scene, brush)) {
685  float last_object_space_position[3];
686  mul_v3_m4v3(
687  last_object_space_position, stroke->vc.obact->imat, stroke->last_world_space_position);
688  size_clamp = paint_calc_object_space_radius(&stroke->vc, last_object_space_position, size);
689  }
690  else {
691  size_clamp = BKE_brush_unprojected_radius_get(scene, brush) * size_pressure;
692  }
693  }
694  else {
695  /* brushes can have a minimum size of 1.0 but with pressure it can be smaller than a pixel
696  * causing very high step sizes, hanging blender T32381. */
697  size_clamp = max_ff(1.0f, size);
698  }
699 
700  float spacing = stroke->brush->spacing;
701 
702  /* apply spacing pressure */
703  if (stroke->brush->flag & BRUSH_SPACING_PRESSURE) {
704  spacing = spacing * (1.5f - spacing_pressure);
705  }
706 
707  if (SCULPT_is_cloth_deform_brush(brush)) {
708  /* The spacing in tools that use the cloth solver should not be affected by the brush radius to
709  * avoid affecting the simulation update rate when changing the radius of the brush.
710  * With a value of 100 and the brush default of 10 for spacing, a simulation step runs every 2
711  * pixels movement of the cursor. */
712  size_clamp = 100.0f;
713  }
714 
715  /* stroke system is used for 2d paint too, so we need to account for
716  * the fact that brush can be scaled there. */
717  spacing *= stroke->zoom_2d;
718 
719  if (paint_stroke_use_scene_spacing(brush, mode)) {
720  return max_ff(0.001f, size_clamp * spacing / 50.0f);
721  }
722  return max_ff(stroke->zoom_2d, size_clamp * spacing / 50.0f);
723 }
724 
725 static float paint_stroke_overlapped_curve(Brush *br, float x, float spacing)
726 {
727  const int n = 100 / spacing;
728  const float h = spacing / 50.0f;
729  const float x0 = x - 1;
730 
731  float sum = 0;
732  for (int i = 0; i < n; i++) {
733  float xx;
734 
735  xx = fabsf(x0 + i * h);
736 
737  if (xx < 1.0f) {
738  sum += BKE_brush_curve_strength(br, xx, 1);
739  }
740  }
741 
742  return sum;
743 }
744 
745 static float paint_stroke_integrate_overlap(Brush *br, float factor)
746 {
747  float spacing = br->spacing * factor;
748 
749  if (!(br->flag & BRUSH_SPACE_ATTEN && (br->spacing < 100))) {
750  return 1.0;
751  }
752 
753  int m = 10;
754  float g = 1.0f / m;
755  float max = 0;
756  for (int i = 0; i < m; i++) {
757  float overlap = fabs(paint_stroke_overlapped_curve(br, i * g, spacing));
758 
759  if (overlap > max) {
760  max = overlap;
761  }
762  }
763 
764  if (max == 0.0f) {
765  return 1.0f;
766  }
767  return 1.0f / max;
768 }
769 
771  const Scene *scene,
772  PaintStroke *stroke,
773  float pressure,
774  float dpressure,
775  float length)
776 {
777  if (BKE_brush_use_size_pressure(stroke->brush)) {
778  /* use pressure to modify size. set spacing so that at 100%, the circles
779  * are aligned nicely with no overlap. for this the spacing needs to be
780  * the average of the previous and next size. */
781  float s = paint_space_stroke_spacing(C, scene, stroke, 1.0f, pressure);
782  float q = s * dpressure / (2.0f * length);
783  float pressure_fac = (1.0f + q) / (1.0f - q);
784 
785  float last_size_pressure = stroke->last_pressure;
786  float new_size_pressure = stroke->last_pressure * pressure_fac;
787 
788  /* average spacing */
789  float last_spacing = paint_space_stroke_spacing(
790  C, scene, stroke, last_size_pressure, pressure);
791  float new_spacing = paint_space_stroke_spacing(C, scene, stroke, new_size_pressure, pressure);
792 
793  return 0.5f * (last_spacing + new_spacing);
794  }
795 
796  /* no size pressure */
797  return paint_space_stroke_spacing(C, scene, stroke, 1.0f, pressure);
798 }
799 
800 /* For brushes with stroke spacing enabled, moves mouse in steps
801  * towards the final mouse location. */
803  wmOperator *op,
804  const float final_mouse[2],
805  float final_pressure)
806 {
807  const Scene *scene = CTX_data_scene(C);
808  ARegion *region = CTX_wm_region(C);
809  PaintStroke *stroke = op->customdata;
810  UnifiedPaintSettings *ups = stroke->ups;
813  Brush *brush = BKE_paint_brush(paint);
814  int cnt = 0;
815 
816  const bool use_scene_spacing = paint_stroke_use_scene_spacing(brush, mode);
817  float d_world_space_position[3] = {0.0f};
818 
819  float no_pressure_spacing = paint_space_stroke_spacing(C, scene, stroke, 1.0f, 1.0f);
820  float pressure = stroke->last_pressure;
821  float dpressure = final_pressure - stroke->last_pressure;
822 
823  float dmouse[2];
824  sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position);
825  float length = normalize_v2(dmouse);
826 
827  if (use_scene_spacing) {
828  float world_space_position[3];
829  bool hit = SCULPT_stroke_get_location(C, world_space_position, final_mouse);
830  mul_m4_v3(stroke->vc.obact->obmat, world_space_position);
831  if (hit && stroke->stroke_over_mesh) {
832  sub_v3_v3v3(d_world_space_position, world_space_position, stroke->last_world_space_position);
833  length = len_v3(d_world_space_position);
834  stroke->stroke_over_mesh = true;
835  }
836  else {
837  length = 0.0f;
838  zero_v3(d_world_space_position);
839  stroke->stroke_over_mesh = hit;
840  if (stroke->stroke_over_mesh) {
841  copy_v3_v3(stroke->last_world_space_position, world_space_position);
842  }
843  }
844  }
845 
846  while (length > 0.0f) {
847  float spacing = paint_space_stroke_spacing_variable(
848  C, scene, stroke, pressure, dpressure, length);
849  float mouse[3];
850 
851  if (length >= spacing) {
852  if (use_scene_spacing) {
853  float final_world_space_position[3];
854  normalize_v3(d_world_space_position);
855  mul_v3_v3fl(final_world_space_position, d_world_space_position, spacing);
856  add_v3_v3v3(final_world_space_position,
858  final_world_space_position);
859  ED_view3d_project(region, final_world_space_position, mouse);
860  }
861  else {
862  mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing;
863  mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing;
864  }
865  pressure = stroke->last_pressure + (spacing / length) * dpressure;
866 
868  spacing / no_pressure_spacing);
869 
870  stroke->stroke_distance += spacing / stroke->zoom_2d;
871  paint_brush_stroke_add_step(C, op, mouse, pressure);
872 
873  length -= spacing;
874  pressure = stroke->last_pressure;
875  dpressure = final_pressure - stroke->last_pressure;
876 
877  cnt++;
878  }
879  else {
880  break;
881  }
882  }
883 
884  return cnt;
885 }
886 
887 /**** Public API ****/
888 
890  wmOperator *op,
891  StrokeGetLocation get_location,
892  StrokeTestStart test_start,
893  StrokeUpdateStep update_step,
894  StrokeRedraw redraw,
895  StrokeDone done,
896  int event_type)
897 {
899  PaintStroke *stroke = MEM_callocN(sizeof(PaintStroke), "PaintStroke");
900  ToolSettings *toolsettings = CTX_data_tool_settings(C);
901  UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings;
903  Brush *br = stroke->brush = BKE_paint_brush(p);
905  float zoomx, zoomy;
906 
908 
909  stroke->get_location = get_location;
910  stroke->test_start = test_start;
911  stroke->update_step = update_step;
912  stroke->redraw = redraw;
913  stroke->done = done;
914  stroke->event_type = event_type; /* for modal, return event */
915  stroke->ups = ups;
916  stroke->stroke_mode = RNA_enum_get(op->ptr, "mode");
917 
918  get_imapaint_zoom(C, &zoomx, &zoomy);
919  stroke->zoom_2d = max_ff(zoomx, zoomy);
920 
921  if (stroke->stroke_mode == BRUSH_STROKE_INVERT) {
922  if (br->flag & BRUSH_CURVE) {
923  RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL);
924  }
925  }
926  /* initialize here */
927  ups->overlap_factor = 1.0;
928  ups->stroke_active = true;
929 
930  if (rv3d) {
931  rv3d->rflag |= RV3D_PAINTING;
932  }
933 
935  ups->average_stroke_counter = 0;
936 
937  /* initialize here to avoid initialization conflict with threaded strokes */
939  if (p->flags & PAINT_USE_CAVITY_MASK) {
941  }
942 
944 
945  return stroke;
946 }
947 
949 {
951  if (rv3d) {
952  rv3d->rflag &= ~RV3D_PAINTING;
953  }
954 
956 
957  PaintStroke *stroke = op->customdata;
958  if (stroke == NULL) {
959  return;
960  }
961 
962  UnifiedPaintSettings *ups = stroke->ups;
963  ups->draw_anchored = false;
964  ups->stroke_active = false;
965 
966  if (stroke->timer) {
968  }
969 
970  if (stroke->rng) {
971  BLI_rng_free(stroke->rng);
972  }
973 
974  if (stroke->stroke_cursor) {
976  }
977 
978  BLI_freelistN(&stroke->line);
979 
981 }
982 
983 static void stroke_done(bContext *C, wmOperator *op)
984 {
985  PaintStroke *stroke = op->customdata;
986  UnifiedPaintSettings *ups = stroke->ups;
987 
988  /* reset rotation here to avoid doing so in cursor display */
989  if (!(stroke->brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) {
990  ups->brush_rotation = 0.0f;
991  }
992 
993  if (!(stroke->brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) {
994  ups->brush_rotation_sec = 0.0f;
995  }
996 
997  if (stroke->stroke_started) {
998  if (stroke->redraw) {
999  stroke->redraw(C, stroke, true);
1000  }
1001 
1002  if (stroke->done) {
1003  stroke->done(C, stroke);
1004  }
1005  }
1006 
1007  paint_stroke_free(C, op);
1008 }
1009 
1010 /* Returns zero if the stroke dots should not be spaced, non-zero otherwise */
1012 {
1013  if ((br->flag & BRUSH_SPACE) == 0) {
1014  return false;
1015  }
1016 
1018  /* The Cloth Brush is a special case for stroke spacing. Even if it has grab modes which do
1019  * not support dynamic size, stroke spacing needs to be enabled so it is possible to control
1020  * whether the simulation runs constantly or only when the brush moves when using the cloth
1021  * grab brushes. */
1022  return true;
1023  }
1024 
1025  return paint_supports_dynamic_size(br, mode);
1026 }
1027 
1028 static bool sculpt_is_grab_tool(Brush *br)
1029 {
1030 
1032  return true;
1033  }
1034  return ELEM(br->sculpt_tool,
1042 }
1043 
1044 /* return true if the brush size can change during paint (normally used for pressure) */
1046 {
1047  if (br->flag & BRUSH_ANCHORED) {
1048  return false;
1049  }
1050 
1051  switch (mode) {
1052  case PAINT_MODE_SCULPT:
1053  if (sculpt_is_grab_tool(br)) {
1054  return false;
1055  }
1056  break;
1057 
1058  case PAINT_MODE_TEXTURE_2D: /* fall through */
1059  case PAINT_MODE_TEXTURE_3D:
1060  if ((br->imagepaint_tool == PAINT_TOOL_FILL) && (br->flag & BRUSH_USE_GRADIENT)) {
1061  return false;
1062  }
1063  break;
1064 
1065  default:
1066  break;
1067  }
1068  return true;
1069 }
1070 
1072 {
1073  if (!(br->flag & BRUSH_SMOOTH_STROKE) ||
1074  (br->flag & (BRUSH_ANCHORED | BRUSH_DRAG_DOT | BRUSH_LINE))) {
1075  return false;
1076  }
1077 
1078  switch (mode) {
1079  case PAINT_MODE_SCULPT:
1080  if (sculpt_is_grab_tool(br)) {
1081  return false;
1082  }
1083  break;
1084  default:
1085  break;
1086  }
1087  return true;
1088 }
1089 
1091 {
1092  /* omit: PAINT_WEIGHT, PAINT_SCULPT_UV, PAINT_INVALID */
1093  return ELEM(
1095 }
1096 
1097 /* return true if the brush size can change during paint (normally used for pressure) */
1099 {
1100  if (br->flag & BRUSH_ANCHORED) {
1101  return false;
1102  }
1103 
1104  switch (mode) {
1105  case PAINT_MODE_SCULPT:
1106  if (sculpt_is_grab_tool(br)) {
1107  return false;
1108  }
1109  break;
1110  default:
1111  break;
1112  }
1113  return true;
1114 }
1115 
1116 #define PAINT_STROKE_MODAL_CANCEL 1
1117 
1118 /* called in paint_ops.c, on each regeneration of keymaps */
1120 {
1121  static struct EnumPropertyItem modal_items[] = {
1122  {PAINT_STROKE_MODAL_CANCEL, "CANCEL", 0, "Cancel", "Cancel and undo a stroke in progress"},
1123 
1124  {0}};
1125 
1126  static const char *name = "Paint Stroke Modal";
1127 
1128  struct wmKeyMap *keymap = WM_modalkeymap_find(keyconf, name);
1129 
1130  /* this function is called for each spacetype, only needs to add map once */
1131  if (!keymap) {
1132  keymap = WM_modalkeymap_ensure(keyconf, name, modal_items);
1133  }
1134 
1135  return keymap;
1136 }
1137 
1139  const Paint *paint, PaintStroke *stroke, float x, float y, float pressure)
1140 {
1141  PaintSample *sample = &stroke->samples[stroke->cur_sample];
1142  int max_samples = CLAMPIS(paint->num_input_samples, 1, PAINT_MAX_INPUT_SAMPLES);
1143 
1144  sample->mouse[0] = x;
1145  sample->mouse[1] = y;
1146  sample->pressure = pressure;
1147 
1148  stroke->cur_sample++;
1149  if (stroke->cur_sample >= max_samples) {
1150  stroke->cur_sample = 0;
1151  }
1152  if (stroke->num_samples < max_samples) {
1153  stroke->num_samples++;
1154  }
1155 }
1156 
1158 {
1159  memset(average, 0, sizeof(*average));
1160 
1161  BLI_assert(stroke->num_samples > 0);
1162 
1163  for (int i = 0; i < stroke->num_samples; i++) {
1164  add_v2_v2(average->mouse, stroke->samples[i].mouse);
1165  average->pressure += stroke->samples[i].pressure;
1166  }
1167 
1168  mul_v2_fl(average->mouse, 1.0f / stroke->num_samples);
1169  average->pressure /= stroke->num_samples;
1170 
1171  // printf("avg=(%f, %f), num=%d\n", average->mouse[0], average->mouse[1], stroke->num_samples);
1172 }
1173 
1179  wmOperator *op,
1180  PaintStroke *stroke,
1181  float spacing,
1182  float *length_residue,
1183  const float old_pos[2],
1184  const float new_pos[2])
1185 {
1186  UnifiedPaintSettings *ups = stroke->ups;
1188  Brush *brush = BKE_paint_brush(paint);
1190  ARegion *region = CTX_wm_region(C);
1191 
1192  const bool use_scene_spacing = paint_stroke_use_scene_spacing(brush, mode);
1193 
1194  float mouse[3], dmouse[2];
1195  float length;
1196  float d_world_space_position[3] = {0.0f};
1197  float world_space_position_old[3], world_space_position_new[3];
1198 
1199  copy_v2_v2(stroke->last_mouse_position, old_pos);
1200 
1201  if (use_scene_spacing) {
1202  bool hit_old = SCULPT_stroke_get_location(C, world_space_position_old, old_pos);
1203  bool hit_new = SCULPT_stroke_get_location(C, world_space_position_new, new_pos);
1204  mul_m4_v3(stroke->vc.obact->obmat, world_space_position_old);
1205  mul_m4_v3(stroke->vc.obact->obmat, world_space_position_new);
1206  if (hit_old && hit_new && stroke->stroke_over_mesh) {
1207  sub_v3_v3v3(d_world_space_position, world_space_position_new, world_space_position_old);
1208  length = len_v3(d_world_space_position);
1209  stroke->stroke_over_mesh = true;
1210  }
1211  else {
1212  length = 0.0f;
1213  zero_v3(d_world_space_position);
1214  stroke->stroke_over_mesh = hit_new;
1215  if (stroke->stroke_over_mesh) {
1216  copy_v3_v3(stroke->last_world_space_position, world_space_position_old);
1217  }
1218  }
1219  }
1220  else {
1221  sub_v2_v2v2(dmouse, new_pos, old_pos);
1222  length = normalize_v2(dmouse);
1223  }
1224 
1225  BLI_assert(length >= 0.0f);
1226 
1227  if (length == 0.0f) {
1228  return;
1229  }
1230 
1231  while (length > 0.0f) {
1232  float spacing_final = spacing - *length_residue;
1233  length += *length_residue;
1234  *length_residue = 0.0;
1235 
1236  if (length >= spacing) {
1237  if (use_scene_spacing) {
1238  float final_world_space_position[3];
1239  normalize_v3(d_world_space_position);
1240  mul_v3_v3fl(final_world_space_position, d_world_space_position, spacing_final);
1241  add_v3_v3v3(
1242  final_world_space_position, world_space_position_old, final_world_space_position);
1243  ED_view3d_project(region, final_world_space_position, mouse);
1244  }
1245  else {
1246  mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing_final;
1247  mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing_final;
1248  }
1249 
1251 
1252  stroke->stroke_distance += spacing / stroke->zoom_2d;
1253  paint_brush_stroke_add_step(C, op, mouse, 1.0);
1254 
1255  length -= spacing;
1256  spacing_final = spacing;
1257  }
1258  else {
1259  break;
1260  }
1261  }
1262 
1263  *length_residue = length;
1264 }
1265 
1267  wmOperator *op,
1268  PaintStroke *stroke,
1269  const float mouse[2])
1270 {
1271  Brush *br = stroke->brush;
1272  if (stroke->stroke_started && (br->flag & BRUSH_LINE)) {
1274 
1276  paint_space_stroke(C, op, mouse, 1.0);
1277  }
1278 }
1279 
1281 {
1282  Brush *br = stroke->brush;
1283 
1284  if (br->flag & BRUSH_CURVE) {
1286  const Scene *scene = CTX_data_scene(C);
1287  const float spacing = paint_space_stroke_spacing(C, scene, stroke, 1.0f, 1.0f);
1288  PaintCurve *pc = br->paint_curve;
1289  PaintCurvePoint *pcp;
1290  float length_residue = 0.0f;
1291  int i;
1292 
1293  if (!pc) {
1294  return true;
1295  }
1296 
1297 #ifdef DEBUG_TIME
1298  TIMEIT_START_AVERAGED(whole_stroke);
1299 #endif
1300 
1301  pcp = pc->points;
1303 
1304  for (i = 0; i < pc->tot_points - 1; i++, pcp++) {
1305  int j;
1306  float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
1307  float tangents[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
1308  PaintCurvePoint *pcp_next = pcp + 1;
1309  bool do_rake = false;
1310 
1311  for (j = 0; j < 2; j++) {
1313  pcp->bez.vec[2][j],
1314  pcp_next->bez.vec[0][j],
1315  pcp_next->bez.vec[1][j],
1316  data + j,
1318  sizeof(float[2]));
1319  }
1320 
1321  if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) ||
1323  do_rake = true;
1324  for (j = 0; j < 2; j++) {
1326  pcp->bez.vec[2][j],
1327  pcp_next->bez.vec[0][j],
1328  pcp_next->bez.vec[1][j],
1329  tangents + j,
1331  sizeof(float[2]));
1332  }
1333  }
1334 
1335  for (j = 0; j < PAINT_CURVE_NUM_SEGMENTS; j++) {
1336  if (do_rake) {
1337  float rotation = atan2f(tangents[2 * j], tangents[2 * j + 1]);
1338  paint_update_brush_rake_rotation(ups, br, rotation);
1339  }
1340 
1341  if (!stroke->stroke_started) {
1342  stroke->last_pressure = 1.0;
1343  copy_v2_v2(stroke->last_mouse_position, data + 2 * j);
1344 
1347  C, stroke->last_world_space_position, data + 2 * j);
1348  mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position);
1349  }
1350 
1351  stroke->stroke_started = stroke->test_start(C, op, stroke->last_mouse_position);
1352 
1353  if (stroke->stroke_started) {
1354  paint_brush_stroke_add_step(C, op, data + 2 * j, 1.0);
1356  C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
1357  }
1358  }
1359  else {
1361  C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
1362  }
1363  }
1364  }
1365 
1366  stroke_done(C, op);
1367 
1368 #ifdef DEBUG_TIME
1369  TIMEIT_END_AVERAGED(whole_stroke);
1370 #endif
1371 
1372  return true;
1373  }
1374 
1375  return false;
1376 }
1377 
1378 static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2])
1379 {
1380  if (stroke->constrain_line) {
1381  float line[2];
1382  float angle, len, res;
1383 
1384  sub_v2_v2v2(line, mouse, stroke->last_mouse_position);
1385  angle = atan2f(line[1], line[0]);
1386  len = len_v2(line);
1387 
1388  /* divide angle by PI/4 */
1389  angle = 4.0f * angle / (float)M_PI;
1390 
1391  /* now take residue */
1392  res = angle - floorf(angle);
1393 
1394  /* residue decides how close we are at a certain angle */
1395  if (res <= 0.5f) {
1396  angle = floorf(angle) * (float)M_PI_4;
1397  }
1398  else {
1399  angle = (floorf(angle) + 1.0f) * (float)M_PI_4;
1400  }
1401 
1402  mouse[0] = stroke->constrained_pos[0] = len * cosf(angle) + stroke->last_mouse_position[0];
1403  mouse[1] = stroke->constrained_pos[1] = len * sinf(angle) + stroke->last_mouse_position[1];
1404  }
1405 }
1406 
1408 {
1411  PaintStroke *stroke = op->customdata;
1412  Brush *br = stroke->brush = BKE_paint_brush(p);
1413  PaintSample sample_average;
1414  float mouse[2];
1415  bool first_dab = false;
1416  bool first_modal = false;
1417  bool redraw = false;
1418  float pressure;
1419 
1421  return OPERATOR_RUNNING_MODAL;
1422  }
1423 
1424  /* see if tablet affects event. Line, anchored and drag dot strokes do not support pressure */
1425  pressure = ((br->flag & (BRUSH_LINE | BRUSH_ANCHORED | BRUSH_DRAG_DOT)) ?
1426  1.0f :
1427  WM_event_tablet_data(event, &stroke->pen_flip, NULL));
1428 
1429  /* When processing a timer event the pressure from the event is 0, so use the last valid
1430  * pressure. */
1431  if (event->type == TIMER) {
1432  pressure = stroke->last_tablet_event_pressure;
1433  }
1434  else {
1435  stroke->last_tablet_event_pressure = pressure;
1436  }
1437 
1438  paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1], pressure);
1439  paint_stroke_sample_average(stroke, &sample_average);
1440 
1441  /* Tilt. */
1442  if (WM_event_is_tablet(event)) {
1443  stroke->x_tilt = event->tablet.x_tilt;
1444  stroke->y_tilt = event->tablet.y_tilt;
1445  }
1446 
1447 #ifdef WITH_INPUT_NDOF
1448  /* let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously!
1449  * this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it
1450  * since the 2D deltas are zero -- code in this file needs to be updated to use the
1451  * post-NDOF_MOTION MOUSEMOVE */
1452  if (event->type == NDOF_MOTION) {
1453  return OPERATOR_PASS_THROUGH;
1454  }
1455 #endif
1456 
1457  /* one time initialization */
1458  if (!stroke->stroke_init) {
1459  if (paint_stroke_curve_end(C, op, stroke)) {
1460  return OPERATOR_FINISHED;
1461  }
1462 
1463  if (paint_supports_smooth_stroke(br, mode)) {
1466  }
1467 
1468  stroke->stroke_init = true;
1469  first_modal = true;
1470  }
1471 
1472  /* one time stroke initialization */
1473  if (!stroke->stroke_started) {
1474  stroke->last_pressure = sample_average.pressure;
1475  copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
1476  if (paint_stroke_use_scene_spacing(br, mode)) {
1478  C, stroke->last_world_space_position, sample_average.mouse);
1479  mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position);
1480  }
1481  stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse);
1482  BLI_assert((stroke->stroke_started & ~1) == 0); /* 0/1 */
1483 
1484  if (stroke->stroke_started) {
1485  if (br->flag & BRUSH_AIRBRUSH) {
1486  stroke->timer = WM_event_add_timer(
1487  CTX_wm_manager(C), CTX_wm_window(C), TIMER, stroke->brush->rate);
1488  }
1489 
1490  if (br->flag & BRUSH_LINE) {
1493  }
1494 
1495  first_dab = true;
1496  }
1497  }
1498 
1499  /* Cancel */
1500  if (event->type == EVT_MODAL_MAP && event->val == PAINT_STROKE_MODAL_CANCEL) {
1501  if (op->type->cancel) {
1502  op->type->cancel(C, op);
1503  }
1504  else {
1505  paint_stroke_cancel(C, op);
1506  }
1507  return OPERATOR_CANCELLED;
1508  }
1509 
1510  if (event->type == stroke->event_type && !first_modal) {
1511  if (event->val == KM_RELEASE) {
1512  copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
1513  paint_stroke_line_constrain(stroke, mouse);
1514  paint_stroke_line_end(C, op, stroke, mouse);
1515  stroke_done(C, op);
1516  return OPERATOR_FINISHED;
1517  }
1518  }
1519  else if (ELEM(event->type, EVT_RETKEY, EVT_SPACEKEY)) {
1520  paint_stroke_line_end(C, op, stroke, sample_average.mouse);
1521  stroke_done(C, op);
1522  return OPERATOR_FINISHED;
1523  }
1524  else if (br->flag & BRUSH_LINE) {
1525  if (event->alt) {
1526  stroke->constrain_line = true;
1527  }
1528  else {
1529  stroke->constrain_line = false;
1530  }
1531 
1532  copy_v2_fl2(mouse, event->mval[0], event->mval[1]);
1533  paint_stroke_line_constrain(stroke, mouse);
1534 
1535  if (stroke->stroke_started &&
1536  (first_modal || (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)))) {
1537  if ((br->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) ||
1539  copy_v2_v2(stroke->ups->last_rake, stroke->last_mouse_position);
1540  }
1541  paint_calculate_rake_rotation(stroke->ups, br, mouse);
1542  }
1543  }
1544  else if (first_modal ||
1545  /* regular dabs */
1546  (!(br->flag & BRUSH_AIRBRUSH) && (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE))) ||
1547  /* airbrush */
1548  ((br->flag & BRUSH_AIRBRUSH) && event->type == TIMER &&
1549  event->customdata == stroke->timer)) {
1550  if (paint_smooth_stroke(stroke, &sample_average, mode, mouse, &pressure)) {
1551  if (stroke->stroke_started) {
1552  if (paint_space_stroke_enabled(br, mode)) {
1553  if (paint_space_stroke(C, op, mouse, pressure)) {
1554  redraw = true;
1555  }
1556  }
1557  else {
1558  float dmouse[2];
1559  sub_v2_v2v2(dmouse, mouse, stroke->last_mouse_position);
1560  stroke->stroke_distance += len_v2(dmouse);
1561  paint_brush_stroke_add_step(C, op, mouse, pressure);
1562  redraw = true;
1563  }
1564  }
1565  }
1566  }
1567 
1568  /* we want the stroke to have the first daub at the start location
1569  * instead of waiting till we have moved the space distance */
1570  if (first_dab && paint_space_stroke_enabled(br, mode) && !(br->flag & BRUSH_SMOOTH_STROKE)) {
1572  paint_brush_stroke_add_step(C, op, sample_average.mouse, sample_average.pressure);
1573  redraw = true;
1574  }
1575 
1576  /* do updates for redraw. if event is in between mouse-move there are more
1577  * coming, so postpone potentially slow redraw updates until all are done */
1578  if (event->type != INBETWEEN_MOUSEMOVE) {
1579  wmWindow *window = CTX_wm_window(C);
1580  ARegion *region = CTX_wm_region(C);
1581 
1582  /* At the very least, invalidate the cursor */
1583  if (region && (p->flags & PAINT_SHOW_BRUSH)) {
1584  WM_paint_cursor_tag_redraw(window, region);
1585  }
1586 
1587  if (redraw && stroke->redraw) {
1588  stroke->redraw(C, stroke, false);
1589  }
1590  }
1591 
1592  return OPERATOR_RUNNING_MODAL;
1593 }
1594 
1596 {
1597  PaintStroke *stroke = op->customdata;
1598 
1599  /* only when executed for the first time */
1600  if (stroke->stroke_started == 0) {
1601  PropertyRNA *strokeprop;
1602  PointerRNA firstpoint;
1603  float mouse[2];
1604 
1605  strokeprop = RNA_struct_find_property(op->ptr, "stroke");
1606 
1607  if (RNA_property_collection_lookup_int(op->ptr, strokeprop, 0, &firstpoint)) {
1608  RNA_float_get_array(&firstpoint, "mouse", mouse);
1609  stroke->stroke_started = stroke->test_start(C, op, mouse);
1610  }
1611  }
1612 
1613  if (stroke->stroke_started) {
1614  RNA_BEGIN (op->ptr, itemptr, "stroke") {
1615  stroke->update_step(C, stroke, &itemptr);
1616  }
1617  RNA_END;
1618  }
1619 
1620  bool ok = (stroke->stroke_started != 0);
1621 
1622  stroke_done(C, op);
1623 
1624  return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
1625 }
1626 
1628 {
1629  stroke_done(C, op);
1630 }
1631 
1633 {
1634  return &stroke->vc;
1635 }
1636 
1638 {
1639  return stroke->mode_data;
1640 }
1641 
1642 bool paint_stroke_flipped(struct PaintStroke *stroke)
1643 {
1644  return stroke->pen_flip;
1645 }
1646 
1648 {
1649  return stroke->stroke_mode == BRUSH_STROKE_INVERT;
1650 }
1651 
1653 {
1654  return stroke->stroke_distance;
1655 }
1656 
1657 void paint_stroke_set_mode_data(PaintStroke *stroke, void *mode_data)
1658 {
1659  stroke->mode_data = mode_data;
1660 }
1661 
1663 {
1666  ScrArea *area = CTX_wm_area(C);
1667  ARegion *region = CTX_wm_region(C);
1668 
1669  if (p && ob && BKE_paint_brush(p) &&
1670  (area && ELEM(area->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) &&
1671  (region && region->regiontype == RGN_TYPE_WINDOW)) {
1672  /* Check the current tool is a brush. */
1673  bToolRef *tref = area->runtime.tool;
1674  if (tref && tref->runtime && tref->runtime->data_block[0]) {
1675  return true;
1676  }
1677  }
1678  return false;
1679 }
typedef float(TangentPoint)[2]
bool BKE_brush_use_size_pressure(const struct Brush *brush)
float BKE_brush_curve_strength(const struct Brush *br, float p, const float len)
void BKE_brush_randomize_texture_coords(struct UnifiedPaintSettings *ups, bool mask)
Definition: brush.c:2401
int BKE_brush_size_get(const struct Scene *scene, const struct Brush *brush)
float BKE_brush_unprojected_radius_get(const struct Scene *scene, const struct Brush *brush)
bool BKE_brush_use_locked_size(const struct Scene *scene, const struct Brush *brush)
void BKE_brush_jitter_pos(const struct Scene *scene, struct Brush *brush, const float pos[2], float jitterpos[2])
bool BKE_brush_use_alpha_pressure(const struct Brush *brush)
void BKE_curvemapping_init(struct CurveMapping *cumap)
Definition: colortools.c:1200
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:714
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:689
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1279
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
struct ToolSettings * CTX_data_tool_settings(const bContext *C)
Definition: context.c:1208
struct RegionView3D * CTX_wm_region_view3d(const bContext *C)
Definition: context.c:769
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
Definition: curve.c:1804
void BKE_curve_forward_diff_tangent_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
Definition: curve.c:1833
void BKE_image_pool_release_ibuf(struct Image *ima, struct ImBuf *ibuf, struct ImagePool *pool)
Definition: image.c:5261
struct ImBuf * BKE_image_pool_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, struct ImagePool *pool)
Definition: image.c:5213
bool paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, struct Brush *brush, const float mouse_pos[2])
Definition: paint.c:1300
ePaintMode BKE_paintmode_get_active_from_context(const struct bContext *C)
struct Brush * BKE_paint_brush(struct Paint *paint)
Definition: paint.c:604
void BKE_paint_set_overlay_override(enum eOverlayFlags flag)
Definition: paint.c:283
struct Paint * BKE_paint_get_active_from_context(const struct bContext *C)
ePaintMode
Definition: BKE_paint.h:78
@ PAINT_MODE_TEXTURE_3D
Definition: BKE_paint.h:84
@ PAINT_MODE_SCULPT
Definition: BKE_paint.h:79
@ PAINT_MODE_TEXTURE_2D
Definition: BKE_paint.h:86
@ PAINT_MODE_VERTEX
Definition: BKE_paint.h:81
void paint_update_brush_rake_rotation(struct UnifiedPaintSettings *ups, struct Brush *brush, float rotation)
Definition: paint.c:1283
#define BLI_assert(a)
Definition: BLI_assert.h:58
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
MINLINE float max_ff(float a, float b)
MINLINE float square_f(float a)
MINLINE float interpf(float a, float b, float t)
#define M_PI
Definition: BLI_math_base.h:38
#define M_PI_4
Definition: BLI_math_base.h:44
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:742
void interp_v2_v2v2(float r[2], const float a[2], const float b[2], const float t)
Definition: math_vector.c:32
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v2_fl2(float v[2], float x, float y)
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v2_v2(float r[2], const float a[2])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE float len_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float normalize_v2(float r[2])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
Random number functions.
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
Definition: rand.cc:76
struct RNG * BLI_rng_new(unsigned int seed)
Definition: rand.cc:54
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: rand.cc:120
unsigned int uint
Definition: BLI_sys_types.h:83
#define CLAMPIS(a, b, c)
#define POINTER_AS_INT(i)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
@ BRUSH_SPACE_ATTEN
@ BRUSH_DRAG_DOT
@ BRUSH_SPACING_PRESSURE
@ BRUSH_LINE
@ BRUSH_CURVE
@ BRUSH_EDGE_TO_EDGE
@ BRUSH_SMOOTH_STROKE
@ BRUSH_ANCHORED
@ BRUSH_JITTER_PRESSURE
@ BRUSH_ABSOLUTE_JITTER
@ BRUSH_USE_GRADIENT
@ BRUSH_SCENE_SPACING
@ BRUSH_AIRBRUSH
@ BRUSH_SPACE
@ BRUSH_CLOTH_DEFORM_GRAB
@ SCULPT_TOOL_CLOTH
@ SCULPT_TOOL_THUMB
@ SCULPT_TOOL_GRAB
@ SCULPT_TOOL_BOUNDARY
@ SCULPT_TOOL_POSE
@ SCULPT_TOOL_ROTATE
@ SCULPT_TOOL_ELASTIC_DEFORM
@ SCULPT_TOOL_SNAKE_HOOK
@ PAINT_TOOL_CLONE
@ PAINT_TOOL_FILL
Object is a sort of wrapper for general info.
@ PAINT_USE_CAVITY_MASK
@ PAINT_SHOW_BRUSH
#define PAINT_MAX_INPUT_SAMPLES
#define RGN_TYPE_ANY
@ RGN_TYPE_WINDOW
@ SPACE_IMAGE
@ SPACE_VIEW3D
#define SPACE_TYPE_ANY
#define MTEX_MAP_MODE_VIEW
#define MTEX_ANGLE_RAKE
#define MTEX_MAP_MODE_AREA
#define MTEX_ANGLE_RANDOM
#define MTEX_MAP_MODE_RANDOM
#define RV3D_PAINTING
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
void ED_view3d_viewcontext_init(struct bContext *C, struct ViewContext *vc, struct Depsgraph *depsgraph)
void ED_view3d_project(const struct ARegion *region, const float world[3], float r_region_co[3])
void immUniformColor4ubv(const unsigned char rgba[4])
void immUniform2f(const char *name, float x, float y)
void immUnbindProgram(void)
void immVertex2f(uint attr_id, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immUniform1i(const char *name, int x)
void immUniform1f(const char *name, float x)
void immUniformArray4fv(const char *bare_name, const float *data, int count)
GPUVertFormat * immVertexFormat(void)
void immBegin(GPUPrimType, uint vertex_len)
void immEnd(void)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:36
@ GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR
Definition: GPU_shader.h:365
@ GPU_SHADER_2D_UNIFORM_COLOR
Definition: GPU_shader.h:171
@ GPU_BLEND_NONE
Definition: GPU_state.h:55
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:57
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:55
void GPU_line_smooth(bool enable)
Definition: gpu_state.cc:85
void GPU_viewport_size_get_f(float coords[4])
Definition: gpu_state.cc:279
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled Light Particle Volume TEX_IMAGE
Platform independent time functions.
Utility defines for timing/benchmarks.
#define TIMEIT_START_AVERAGED(var)
#define TIMEIT_END_AVERAGED(var)
#define RNA_BEGIN(sptr, itemptr, propname)
Definition: RNA_access.h:1248
#define RNA_END
Definition: RNA_access.h:1255
#define C
Definition: RandGen.cpp:39
#define KM_RELEASE
Definition: WM_types.h:243
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:895
static T sum(const btAlignedObjectArray< T > &items)
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
Scene scene
const Depsgraph * depsgraph
static CCL_NAMESPACE_BEGIN const double alpha
uint pos
#define UINT_MAX
Definition: hash_md5.c:58
#define sinf(x)
#define cosf(x)
#define atan2f(x, y)
#define floorf(x)
#define fabsf(x)
#define sqrtf(x)
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static void area(int d1, int d2, int e1, int e2, float weights[2])
static void sample(SocketReader *reader, int x, int y, float color[4])
bool get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
Definition: paint_image.c:768
void(* StrokeRedraw)(const struct bContext *C, struct PaintStroke *stroke, bool final)
Definition: paint_intern.h:60
bool(* StrokeGetLocation)(struct bContext *C, float location[3], const float mouse[2])
Definition: paint_intern.h:55
@ BRUSH_STROKE_NORMAL
Definition: paint_intern.h:311
@ BRUSH_STROKE_INVERT
Definition: paint_intern.h:312
void(* StrokeDone)(const struct bContext *C, struct PaintStroke *stroke)
Definition: paint_intern.h:61
float paint_calc_object_space_radius(struct ViewContext *vc, const float center[3], float pixel_radius)
Definition: paint_utils.c:151
#define PAINT_CURVE_NUM_SEGMENTS
Definition: paint_intern.h:368
void(* StrokeUpdateStep)(struct bContext *C, struct PaintStroke *stroke, struct PointerRNA *itemptr)
Definition: paint_intern.h:57
bool(* StrokeTestStart)(struct bContext *C, struct wmOperator *op, const float mouse[2])
Definition: paint_intern.h:56
bool paint_supports_smooth_stroke(Brush *br, ePaintMode mode)
static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float mouse_in[2], float pressure)
Definition: paint_stroke.c:524
bool paint_supports_dynamic_size(Brush *br, ePaintMode mode)
ViewContext * paint_stroke_view_context(PaintStroke *stroke)
bool paint_poll(bContext *C)
bool paint_supports_dynamic_tex_coords(Brush *br, ePaintMode mode)
static bool paint_tool_require_inbetween_mouse_events(Brush *brush, ePaintMode mode)
Definition: paint_stroke.c:262
static void paint_stroke_sample_average(const PaintStroke *stroke, PaintSample *average)
static void paint_stroke_line_end(bContext *C, wmOperator *op, PaintStroke *stroke, const float mouse[2])
static float paint_space_stroke_spacing(bContext *C, const Scene *scene, PaintStroke *stroke, float size_pressure, float spacing_pressure)
Definition: paint_stroke.c:672
static void stroke_done(bContext *C, wmOperator *op)
Definition: paint_stroke.c:983
bool paint_stroke_flipped(struct PaintStroke *stroke)
#define PAINT_STROKE_MODAL_CANCEL
struct PaintSample PaintSample
static float paint_space_stroke_spacing_variable(bContext *C, const Scene *scene, PaintStroke *stroke, float pressure, float dpressure, float length)
Definition: paint_stroke.c:770
static int paint_space_stroke(bContext *C, wmOperator *op, const float final_mouse[2], float final_pressure)
Definition: paint_stroke.c:802
static bool paint_tool_require_location(Brush *brush, ePaintMode mode)
Definition: paint_stroke.c:224
PaintStroke * paint_stroke_new(bContext *C, wmOperator *op, StrokeGetLocation get_location, StrokeTestStart test_start, StrokeUpdateStep update_step, StrokeRedraw redraw, StrokeDone done, int event_type)
Definition: paint_stroke.c:889
static void paint_line_strokes_spacing(bContext *C, wmOperator *op, PaintStroke *stroke, float spacing, float *length_residue, const float old_pos[2], const float new_pos[2])
void paint_stroke_free(bContext *C, wmOperator *op)
Definition: paint_stroke.c:948
static bool sculpt_is_grab_tool(Brush *br)
void paint_stroke_set_mode_data(PaintStroke *stroke, void *mode_data)
bool paint_space_stroke_enabled(Brush *br, ePaintMode mode)
static bool paint_stroke_use_jitter(ePaintMode mode, Brush *brush, bool invert)
Definition: paint_stroke.c:509
static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2])
static void paint_stroke_add_sample(const Paint *paint, PaintStroke *stroke, float x, float y, float pressure)
static float paint_stroke_integrate_overlap(Brush *br, float factor)
Definition: paint_stroke.c:745
void * paint_stroke_mode_data(struct PaintStroke *stroke)
struct wmKeyMap * paint_stroke_modal_keymap(struct wmKeyConfig *keyconf)
bool paint_stroke_inverted(struct PaintStroke *stroke)
static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *stroke)
bool paint_supports_texture(ePaintMode mode)
static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
Definition: paint_stroke.c:173
static bool paint_stroke_use_dash(Brush *brush)
Definition: paint_stroke.c:503
static bool paint_smooth_stroke(PaintStroke *stroke, const PaintSample *sample, ePaintMode mode, float r_mouse[2], float *r_pressure)
Definition: paint_stroke.c:644
void paint_stroke_cancel(bContext *C, wmOperator *op)
int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
static bool paint_stroke_use_scene_spacing(Brush *brush, ePaintMode mode)
Definition: paint_stroke.c:251
static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata)
Definition: paint_stroke.c:142
static float paint_stroke_overlapped_curve(Brush *br, float x, float spacing)
Definition: paint_stroke.c:725
struct PaintStroke PaintStroke
int paint_stroke_exec(bContext *C, wmOperator *op)
static bool paint_brush_update(bContext *C, Brush *brush, ePaintMode mode, struct PaintStroke *stroke, const float mouse_init[2], float mouse[2], float pressure, float r_location[3], bool *r_location_is_set)
Definition: paint_stroke.c:292
float paint_stroke_distance_get(struct PaintStroke *stroke)
void RNA_collection_clear(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6622
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
Definition: rna_access.c:6272
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:866
int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr)
Definition: rna_access.c:4212
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
Definition: rna_access.c:6378
void RNA_collection_add(PointerRNA *ptr, const char *name, PointerRNA *r_value)
Definition: rna_access.c:6610
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
Definition: rna_access.c:6366
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6413
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
Definition: rna_access.c:6390
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
bool SCULPT_stroke_get_location(bContext *C, float out[3], const float mouse[2])
Definition: sculpt.c:7584
BLI_INLINE bool SCULPT_is_cloth_deform_brush(const Brush *brush)
short regiontype
float vec[3][3]
float jitter
int cloth_deform_type
struct MTex mtex
float smooth_stroke_factor
int smooth_stroke_radius
struct CurveMapping * curve
int dash_samples
int jitter_absolute
char imagepaint_tool
float dash_ratio
char sculpt_tool
struct MTex mask_mtex
float rate
struct PaintCurve * paint_curve
int overlay_flags
const char * name
Definition: RNA_types.h:450
struct ColorSpace * rect_colorspace
float * rect_float
char brush_angle_mode
char brush_map_mode
float random_angle
struct Tex * tex
float imat[4][4]
float obmat[4][4]
PaintCurvePoint * points
float mouse[2]
Definition: paint_stroke.c:71
float pressure
Definition: paint_stroke.c:72
void * mode_data
Definition: paint_stroke.c:76
bool stroke_over_mesh
Definition: paint_stroke.c:98
Brush * brush
Definition: paint_stroke.c:83
ListBase line
Definition: paint_stroke.c:87
StrokeGetLocation get_location
Definition: paint_stroke.c:134
float last_world_space_position[3]
Definition: paint_stroke.c:97
bool constrain_line
Definition: paint_stroke.c:131
struct RNG * rng
Definition: paint_stroke.c:79
wmTimer * timer
Definition: paint_stroke.c:78
float last_pressure
Definition: paint_stroke.c:118
UnifiedPaintSettings * ups
Definition: paint_stroke.c:84
StrokeTestStart test_start
Definition: paint_stroke.c:135
ViewContext vc
Definition: paint_stroke.c:82
float last_tablet_event_pressure
Definition: paint_stroke.c:121
StrokeDone done
Definition: paint_stroke.c:138
bool rake_started
Definition: paint_stroke.c:107
float initial_mouse[2]
Definition: paint_stroke.c:114
void * stroke_cursor
Definition: paint_stroke.c:77
float cached_size_pressure
Definition: paint_stroke.c:116
StrokeRedraw redraw
Definition: paint_stroke.c:137
bool stroke_started
Definition: paint_stroke.c:105
StrokeUpdateStep update_step
Definition: paint_stroke.c:136
float last_mouse_position[2]
Definition: paint_stroke.c:96
float constrained_pos[2]
Definition: paint_stroke.c:132
PaintSample samples[PAINT_MAX_INPUT_SAMPLES]
Definition: paint_stroke.c:91
float stroke_distance
Definition: paint_stroke.c:100
bool stroke_init
Definition: paint_stroke.c:111
int num_input_samples
unsigned char paint_cursor_col[4]
struct CurveMapping * cavity_curve
Definition: rand.cc:48
struct ImageUser iuser
short type
struct Image * ima
struct UnifiedPaintSettings unified_paint_settings
struct ColorSpace * colorspace
struct ARegion * region
Definition: ED_view3d.h:80
struct Object * obact
Definition: ED_view3d.h:78
bToolRef_Runtime * runtime
int ymin
Definition: DNA_vec_types.h:80
int xmin
Definition: DNA_vec_types.h:79
short val
Definition: WM_types.h:579
int mval[2]
Definition: WM_types.h:583
short alt
Definition: WM_types.h:618
short type
Definition: WM_types.h:577
void * customdata
Definition: WM_types.h:631
const void * modal_items
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
struct wmOperatorType * type
struct PointerRNA * ptr
CCL_NAMESPACE_BEGIN ccl_device float invert(float color, float factor)
Definition: svm_invert.h:19
long int PIL_check_seconds_timer_i(void)
Definition: time.c:90
float max
ccl_device_inline float average(const float2 &a)
ccl_device_inline float2 fabs(const float2 &a)
uint len
void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *UNUSED(region))
Definition: wm_draw.c:1025
bool WM_event_is_tablet(const struct wmEvent *event)
float WM_event_tablet_data(const wmEvent *event, int *pen_flip, float tilt[2])
@ TIMER
@ EVT_MODAL_MAP
@ EVT_SPACEKEY
@ MOUSEMOVE
@ NDOF_MOTION
@ INBETWEEN_MOUSEMOVE
@ EVT_RETKEY
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition: wm_keymap.c:914
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition: wm_keymap.c:888
bool WM_paint_cursor_end(wmPaintCursor *handle)
wmPaintCursor * WM_paint_cursor_activate(short space_type, short region_type, bool(*poll)(bContext *C), wmPaintCursorDraw draw, void *customdata)
void WM_event_remove_timer(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *timer)
Definition: wm_window.c:1669
wmTimer * WM_event_add_timer(wmWindowManager *wm, wmWindow *win, int event_type, double timestep)
Definition: wm_window.c:1632