Cleanup: remove redundant doxygen \file argument
[blender.git] / source / blender / editors / gpencil / annotate_paint.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2008/2018, Blender Foundation
17  * This is a new part of Blender
18  */
19
20 /** \file \ingroup edgpencil
21  */
22
23
24 #include <stdio.h>
25 #include <stddef.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <math.h>
29
30 #include "MEM_guardedalloc.h"
31
32 #include "BLI_blenlib.h"
33 #include "BLI_math.h"
34 #include "BLI_utildefines.h"
35 #include "BLI_math_geom.h"
36
37 #include "BLT_translation.h"
38
39 #include "PIL_time.h"
40
41 #include "BKE_colortools.h"
42 #include "BKE_context.h"
43 #include "BKE_global.h"
44 #include "BKE_gpencil.h"
45 #include "BKE_layer.h"
46 #include "BKE_main.h"
47 #include "BKE_report.h"
48 #include "BKE_screen.h"
49 #include "BKE_tracking.h"
50
51 #include "DNA_object_types.h"
52 #include "DNA_scene_types.h"
53 #include "DNA_gpencil_types.h"
54 #include "DNA_windowmanager_types.h"
55
56 #include "UI_view2d.h"
57
58 #include "ED_gpencil.h"
59 #include "ED_screen.h"
60 #include "ED_view3d.h"
61 #include "ED_clip.h"
62
63
64 #include "GPU_immediate.h"
65 #include "GPU_immediate_util.h"
66 #include "GPU_state.h"
67
68 #include "RNA_access.h"
69 #include "RNA_define.h"
70
71 #include "WM_api.h"
72 #include "WM_types.h"
73
74 #include "DEG_depsgraph.h"
75
76 #include "gpencil_intern.h"
77
78 /* ******************************************* */
79 /* 'Globals' and Defines */
80
81 /* values for tGPsdata->status */
82 typedef enum eGPencil_PaintStatus {
83         GP_STATUS_IDLING = 0,   /* stroke isn't in progress yet */
84         GP_STATUS_PAINTING,     /* a stroke is in progress */
85         GP_STATUS_ERROR,        /* something wasn't correctly set up */
86         GP_STATUS_DONE          /* painting done */
87 } eGPencil_PaintStatus;
88
89 /* Return flags for adding points to stroke buffer */
90 typedef enum eGP_StrokeAdd_Result {
91         GP_STROKEADD_INVALID    = -2,       /* error occurred - insufficient info to do so */
92         GP_STROKEADD_OVERFLOW   = -1,       /* error occurred - cannot fit any more points */
93         GP_STROKEADD_NORMAL,                /* point was successfully added */
94         GP_STROKEADD_FULL                   /* cannot add any more points to buffer */
95 } eGP_StrokeAdd_Result;
96
97 /* Runtime flags */
98 typedef enum eGPencil_PaintFlags {
99         GP_PAINTFLAG_FIRSTRUN       = (1 << 0),    /* operator just started */
100         GP_PAINTFLAG_STROKEADDED    = (1 << 1),
101         GP_PAINTFLAG_V3D_ERASER_DEPTH = (1 << 2),
102         GP_PAINTFLAG_SELECTMASK     = (1 << 3),
103 } eGPencil_PaintFlags;
104
105
106 /* Temporary 'Stroke' Operation data
107  *   "p" = op->customdata
108  */
109 typedef struct tGPsdata {
110         Main *bmain;
111         /** current scene from context. */
112         Scene *scene;
113         struct Depsgraph *depsgraph;
114
115         /** window where painting originated. */
116         wmWindow *win;
117         /** area where painting originated. */
118         ScrArea *sa;
119         /** region where painting originated. */
120         ARegion *ar;
121         /** needed for GP_STROKE_2DSPACE. */
122         View2D *v2d;
123         /** for using the camera rect within the 3d view. */
124         rctf *subrect;
125         rctf subrect_data;
126
127         /** settings to pass to gp_points_to_xy(). */
128         GP_SpaceConversion gsc;
129
130         /** pointer to owner of gp-datablock. */
131         PointerRNA ownerPtr;
132         /** gp-datablock layer comes from. */
133         bGPdata *gpd;
134         /** layer we're working on. */
135         bGPDlayer *gpl;
136         /** frame we're working on. */
137         bGPDframe *gpf;
138
139         /** projection-mode flags (toolsettings - eGPencil_Placement_Flags) */
140         char *align_flag;
141
142         /** current status of painting. */
143         eGPencil_PaintStatus status;
144         /** mode for painting. */
145         eGPencil_PaintModes  paintmode;
146         /** flags that can get set during runtime (eGPencil_PaintFlags) */
147         eGPencil_PaintFlags  flags;
148
149         /** radius of influence for eraser. */
150         short radius;
151
152         /** current mouse-position. */
153         float mval[2];
154         /** previous recorded mouse-position. */
155         float mvalo[2];
156
157         /** current stylus pressure. */
158         float pressure;
159         /** previous stylus pressure. */
160         float opressure;
161
162         /* These need to be doubles, as (at least under unix) they are in seconds since epoch,
163          * float (and its 7 digits precision) is definitively not enough here!
164          * double, with its 15 digits precision, ensures us millisecond precision for a few centuries at least.
165          */
166         /** Used when converting to path. */
167         double inittime;
168         /** Used when converting to path. */
169         double curtime;
170         /** Used when converting to path. */
171         double ocurtime;
172
173         /** Inverted transformation matrix applying when converting coords from screen-space
174          * to region space. */
175         float imat[4][4];
176         float mat[4][4];
177
178         /** custom color - hack for enforcing a particular color for track/mask editing. */
179         float custom_color[4];
180
181         /** radial cursor data for drawing eraser. */
182         void *erasercursor;
183
184         /** 1: line horizontal, 2: line vertical, other: not defined, second element position. */
185         short straight[2];
186
187         /** key used for invoking the operator. */
188         short keymodifier;
189 } tGPsdata;
190
191 /* ------ */
192
193 /* Macros for accessing sensitivity thresholds... */
194 /* minimum number of pixels mouse should move before new point created */
195 #define MIN_MANHATTEN_PX    (U.gp_manhattendist)
196 /* minimum length of new segment before new point can be added */
197 #define MIN_EUCLIDEAN_PX    (U.gp_euclideandist)
198
199 static bool gp_stroke_added_check(tGPsdata *p)
200 {
201         return (p->gpf && p->gpf->strokes.last && p->flags & GP_PAINTFLAG_STROKEADDED);
202 }
203
204 static void gp_stroke_added_enable(tGPsdata *p)
205 {
206         BLI_assert(p->gpf->strokes.last != NULL);
207         p->flags |= GP_PAINTFLAG_STROKEADDED;
208 }
209
210 /* ------ */
211 /* Forward defines for some functions... */
212
213 static void gp_session_validatebuffer(tGPsdata *p);
214
215 /* ******************************************* */
216 /* Context Wrangling... */
217
218 /* check if context is suitable for drawing */
219 static bool gpencil_draw_poll(bContext *C)
220 {
221         if (ED_operator_regionactive(C)) {
222                 /* check if current context can support GPencil data */
223                 if (ED_gpencil_data_get_pointers(C, NULL) != NULL) {
224                         /* check if Grease Pencil isn't already running */
225                         if (ED_gpencil_session_active() == 0)
226                                 return 1;
227                         else
228                                 CTX_wm_operator_poll_msg_set(C, "Annotation operator is already active");
229                 }
230                 else {
231                         CTX_wm_operator_poll_msg_set(C, "Failed to find Grease Pencil data to draw into");
232                 }
233         }
234         else {
235                 CTX_wm_operator_poll_msg_set(C, "Active region not set");
236         }
237
238         return 0;
239 }
240
241 /* check if projecting strokes into 3d-geometry in the 3D-View */
242 static bool gpencil_project_check(tGPsdata *p)
243 {
244         bGPdata *gpd = p->gpd;
245         return ((gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) && (*p->align_flag & (GP_PROJECT_DEPTH_VIEW | GP_PROJECT_DEPTH_STROKE)));
246 }
247
248 /* ******************************************* */
249 /* Calculations/Conversions */
250
251 /* Utilities --------------------------------- */
252
253 /* get the reference point for stroke-point conversions */
254 static void gp_get_3d_reference(tGPsdata *p, float vec[3])
255 {
256         const float *fp = p->scene->cursor.location;
257
258         /* use 3D-cursor */
259         copy_v3_v3(vec, fp);
260 }
261
262 /* Stroke Editing ---------------------------- */
263
264 /* check if the current mouse position is suitable for adding a new point */
265 static bool gp_stroke_filtermval(tGPsdata *p, const float mval[2], float pmval[2])
266 {
267         int dx = (int)fabsf(mval[0] - pmval[0]);
268         int dy = (int)fabsf(mval[1] - pmval[1]);
269
270         /* if buffer is empty, just let this go through (i.e. so that dots will work) */
271         if (p->gpd->runtime.sbuffer_size == 0)
272                 return true;
273
274         /* check if mouse moved at least certain distance on both axes (best case)
275          * - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand
276          */
277         else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX))
278                 return true;
279
280         /* check if the distance since the last point is significant enough
281          * - prevents points being added too densely
282          * - distance here doesn't use sqrt to prevent slowness... we should still be safe from overflows though
283          */
284         else if ((dx * dx + dy * dy) > MIN_EUCLIDEAN_PX * MIN_EUCLIDEAN_PX)
285                 return true;
286
287         /* mouse 'didn't move' */
288         else
289                 return false;
290 }
291
292 /* convert screen-coordinates to buffer-coordinates */
293 static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[3], float *depth)
294 {
295         bGPdata *gpd = p->gpd;
296
297         /* in 3d-space - pt->x/y/z are 3 side-by-side floats */
298         if (gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) {
299                 int mval_i[2];
300                 round_v2i_v2fl(mval_i, mval);
301                 if (gpencil_project_check(p) && (ED_view3d_autodist_simple(p->ar, mval_i, out, 0, depth))) {
302                         /* projecting onto 3D-Geometry
303                          * - nothing more needs to be done here, since view_autodist_simple() has already done it
304                          */
305                 }
306                 else {
307                         float mval_prj[2];
308                         float rvec[3], dvec[3];
309                         float zfac;
310
311                         /* Current method just converts each point in screen-coordinates to
312                          * 3D-coordinates using the 3D-cursor as reference. In general, this
313                          * works OK, but it could of course be improved.
314                          *
315                          * TODO:
316                          * - investigate using nearest point(s) on a previous stroke as
317                          *   reference point instead or as offset, for easier stroke matching
318                          */
319
320                         gp_get_3d_reference(p, rvec);
321                         zfac = ED_view3d_calc_zfac(p->ar->regiondata, rvec, NULL);
322
323                         if (ED_view3d_project_float_global(p->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
324                                 float mval_f[2];
325                                 sub_v2_v2v2(mval_f, mval_prj, mval);
326                                 ED_view3d_win_to_delta(p->ar, mval_f, dvec, zfac);
327                                 sub_v3_v3v3(out, rvec, dvec);
328                         }
329                         else {
330                                 zero_v3(out);
331                         }
332                 }
333         }
334
335         /* 2d - on 'canvas' (assume that p->v2d is set) */
336         else if ((gpd->runtime.sbuffer_sflag & GP_STROKE_2DSPACE) && (p->v2d)) {
337                 UI_view2d_region_to_view(p->v2d, mval[0], mval[1], &out[0], &out[1]);
338                 mul_v3_m4v3(out, p->imat, out);
339         }
340
341         /* 2d - relative to screen (viewport area) */
342         else {
343                 if (p->subrect == NULL) { /* normal 3D view */
344                         out[0] = (float)(mval[0]) / (float)(p->ar->winx) * 100;
345                         out[1] = (float)(mval[1]) / (float)(p->ar->winy) * 100;
346                 }
347                 else { /* camera view, use subrect */
348                         out[0] = ((mval[0] - p->subrect->xmin) / BLI_rctf_size_x(p->subrect)) * 100;
349                         out[1] = ((mval[1] - p->subrect->ymin) / BLI_rctf_size_y(p->subrect)) * 100;
350                 }
351         }
352 }
353
354 /* add current stroke-point to buffer (returns whether point was successfully added) */
355 static short gp_stroke_addpoint(
356         tGPsdata *p, const float mval[2], float pressure, double curtime)
357 {
358         bGPdata *gpd = p->gpd;
359         tGPspoint *pt;
360         ToolSettings *ts = p->scene->toolsettings;
361
362         /* check painting mode */
363         if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
364                 /* straight lines only - i.e. only store start and end point in buffer */
365                 if (gpd->runtime.sbuffer_size == 0) {
366                         /* first point in buffer (start point) */
367                         pt = (tGPspoint *)(gpd->runtime.sbuffer);
368
369                         /* store settings */
370                         copy_v2_v2(&pt->x, mval);
371                         /* T44932 - Pressure vals are unreliable, so ignore for now */
372                         pt->pressure = 1.0f;
373                         pt->strength = 1.0f;
374                         pt->time = (float)(curtime - p->inittime);
375
376                         /* increment buffer size */
377                         gpd->runtime.sbuffer_size++;
378                 }
379                 else {
380                         /* just reset the endpoint to the latest value
381                          * - assume that pointers for this are always valid...
382                          */
383                         pt = ((tGPspoint *)(gpd->runtime.sbuffer) + 1);
384
385                         /* store settings */
386                         copy_v2_v2(&pt->x, mval);
387                         /* T44932 - Pressure vals are unreliable, so ignore for now */
388                         pt->pressure = 1.0f;
389                         pt->strength = 1.0f;
390                         pt->time = (float)(curtime - p->inittime);
391
392                         /* now the buffer has 2 points (and shouldn't be allowed to get any larger) */
393                         gpd->runtime.sbuffer_size = 2;
394                 }
395
396                 /* can keep carrying on this way :) */
397                 return GP_STROKEADD_NORMAL;
398         }
399         else if (p->paintmode == GP_PAINTMODE_DRAW) { /* normal drawing */
400                 /* check if still room in buffer */
401                 if (gpd->runtime.sbuffer_size >= GP_STROKE_BUFFER_MAX)
402                         return GP_STROKEADD_OVERFLOW;
403
404                 /* get pointer to destination point */
405                 pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_size);
406
407                 /* store settings */
408                 copy_v2_v2(&pt->x, mval);
409                 pt->pressure = pressure;
410                 /* unused for annotations, but initialise for easier conversions to GP Object */
411                 pt->strength = 1.0f;
412
413                 /* point time */
414                 pt->time = (float)(curtime - p->inittime);
415
416                 /* increment counters */
417                 gpd->runtime.sbuffer_size++;
418
419                 /* check if another operation can still occur */
420                 if (gpd->runtime.sbuffer_size == GP_STROKE_BUFFER_MAX)
421                         return GP_STROKEADD_FULL;
422                 else
423                         return GP_STROKEADD_NORMAL;
424         }
425         else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
426                 /* get pointer to destination point */
427                 pt = (tGPspoint *)(gpd->runtime.sbuffer);
428
429                 /* store settings */
430                 copy_v2_v2(&pt->x, mval);
431                 /* T44932 - Pressure vals are unreliable, so ignore for now */
432                 pt->pressure = 1.0f;
433                 pt->strength = 1.0f;
434                 pt->time = (float)(curtime - p->inittime);
435
436                 /* if there's stroke for this poly line session add (or replace last) point
437                  * to stroke. This allows to draw lines more interactively (see new segment
438                  * during mouse slide, e.g.)
439                  */
440                 if (gp_stroke_added_check(p)) {
441                         bGPDstroke *gps = p->gpf->strokes.last;
442                         bGPDspoint *pts;
443
444                         /* first time point is adding to temporary buffer -- need to allocate new point in stroke */
445                         if (gpd->runtime.sbuffer_size == 0) {
446                                 gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1));
447                                 gps->totpoints++;
448                         }
449
450                         pts = &gps->points[gps->totpoints - 1];
451
452                         /* special case for poly lines: normally,
453                          * depth is needed only when creating new stroke from buffer,
454                          * but poly lines are converting to stroke instantly,
455                          * so initialize depth buffer before converting coordinates
456                          */
457                         if (gpencil_project_check(p)) {
458                                 View3D *v3d = p->sa->spacedata.first;
459
460                                 view3d_region_operator_needs_opengl(p->win, p->ar);
461                                 ED_view3d_autodist_init(
462                                         p->depsgraph, p->ar, v3d, (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
463                         }
464
465                         /* convert screen-coordinates to appropriate coordinates (and store them) */
466                         gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL);
467
468                         /* copy pressure and time */
469                         pts->pressure = pt->pressure;
470                         pts->strength = pt->strength;
471                         pts->time = pt->time;
472
473                         /* force fill recalc */
474                         gps->flag |= GP_STROKE_RECALC_GEOMETRY;
475                 }
476
477                 /* increment counters */
478                 if (gpd->runtime.sbuffer_size == 0)
479                         gpd->runtime.sbuffer_size++;
480
481                 return GP_STROKEADD_NORMAL;
482         }
483
484         /* return invalid state for now... */
485         return GP_STROKEADD_INVALID;
486 }
487
488 /* simplify a stroke (in buffer) before storing it
489  * - applies a reverse Chaikin filter
490  * - code adapted from etch-a-ton branch
491  */
492 static void gp_stroke_simplify(tGPsdata *p)
493 {
494         bGPdata *gpd = p->gpd;
495         tGPspoint *old_points = (tGPspoint *)gpd->runtime.sbuffer;
496         short num_points = gpd->runtime.sbuffer_size;
497         short flag = gpd->runtime.sbuffer_sflag;
498         short i, j;
499
500         /* only simplify if simplification is enabled, and we're not doing a straight line */
501         if (!(U.gp_settings & GP_PAINT_DOSIMPLIFY) || (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT))
502                 return;
503
504         /* don't simplify if less than 4 points in buffer */
505         if ((num_points <= 4) || (old_points == NULL))
506                 return;
507
508         /* clear buffer (but don't free mem yet) so that we can write to it
509          * - firstly set sbuffer to NULL, so a new one is allocated
510          * - secondly, reset flag after, as it gets cleared auto
511          */
512         gpd->runtime.sbuffer = NULL;
513         gp_session_validatebuffer(p);
514         gpd->runtime.sbuffer_sflag = flag;
515
516 /* macro used in loop to get position of new point
517  * - used due to the mixture of datatypes in use here
518  */
519 #define GP_SIMPLIFY_AVPOINT(offs, sfac) \
520         { \
521                 co[0] += (float)(old_points[offs].x * sfac); \
522                 co[1] += (float)(old_points[offs].y * sfac); \
523                 pressure += old_points[offs].pressure * sfac; \
524                 time += old_points[offs].time * sfac; \
525         } (void)0
526
527         /* XXX Here too, do not lose start and end points! */
528         gp_stroke_addpoint(p, &old_points->x, old_points->pressure, p->inittime + (double)old_points->time);
529         for (i = 0, j = 0; i < num_points; i++) {
530                 if (i - j == 3) {
531                         float co[2], pressure, time;
532                         float mco[2];
533
534                         /* initialize values */
535                         co[0] = 0.0f;
536                         co[1] = 0.0f;
537                         pressure = 0.0f;
538                         time = 0.0f;
539
540                         /* using macro, calculate new point */
541                         GP_SIMPLIFY_AVPOINT(j, -0.25f);
542                         GP_SIMPLIFY_AVPOINT(j + 1, 0.75f);
543                         GP_SIMPLIFY_AVPOINT(j + 2, 0.75f);
544                         GP_SIMPLIFY_AVPOINT(j + 3, -0.25f);
545
546                         /* set values for adding */
547                         mco[0] = co[0];
548                         mco[1] = co[1];
549
550                         /* ignore return values on this... assume to be ok for now */
551                         gp_stroke_addpoint(p, mco, pressure, p->inittime + (double)time);
552
553                         j += 2;
554                 }
555         }
556         gp_stroke_addpoint(
557                 p, &old_points[num_points - 1].x, old_points[num_points - 1].pressure,
558                 p->inittime + (double)old_points[num_points - 1].time);
559
560         /* free old buffer */
561         MEM_freeN(old_points);
562 }
563
564 /* make a new stroke from the buffer data */
565 static void gp_stroke_newfrombuffer(tGPsdata *p)
566 {
567         bGPdata *gpd = p->gpd;
568         bGPDlayer *gpl = p->gpl;
569         bGPDstroke *gps;
570         bGPDspoint *pt;
571         tGPspoint *ptc;
572         ToolSettings *ts = p->scene->toolsettings;
573
574         int i, totelem;
575         /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */
576         int depth_margin = (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0;
577
578         /* get total number of points to allocate space for
579          * - drawing straight-lines only requires the endpoints
580          */
581         if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT)
582                 totelem = (gpd->runtime.sbuffer_size >= 2) ? 2 : gpd->runtime.sbuffer_size;
583         else
584                 totelem = gpd->runtime.sbuffer_size;
585
586         /* exit with error if no valid points from this stroke */
587         if (totelem == 0) {
588                 if (G.debug & G_DEBUG)
589                         printf("Error: No valid points in stroke buffer to convert (tot=%d)\n", gpd->runtime.sbuffer_size);
590                 return;
591         }
592
593         /* special case for poly line -- for already added stroke during session
594          * coordinates are getting added to stroke immediately to allow more
595          * interactive behavior
596          */
597         if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
598                 if (gp_stroke_added_check(p)) {
599                         return;
600                 }
601         }
602
603         /* allocate memory for a new stroke */
604         gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
605
606         /* copy appropriate settings for stroke */
607         gps->totpoints = totelem;
608         gps->thickness = gpl->thickness;
609         gps->flag = gpd->runtime.sbuffer_sflag;
610         gps->inittime = p->inittime;
611
612         /* enable recalculation flag by default (only used if hq fill) */
613         gps->flag |= GP_STROKE_RECALC_GEOMETRY;
614
615         /* allocate enough memory for a continuous array for storage points */
616         gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
617         gps->tot_triangles = 0;
618
619         /* set pointer to first non-initialized point */
620         pt = gps->points + (gps->totpoints - totelem);
621
622         /* copy points from the buffer to the stroke */
623         if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
624                 /* straight lines only -> only endpoints */
625                 {
626                         /* first point */
627                         ptc = gpd->runtime.sbuffer;
628
629                         /* convert screen-coordinates to appropriate coordinates (and store them) */
630                         gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
631
632                         /* copy pressure and time */
633                         pt->pressure = ptc->pressure;
634                         pt->strength = ptc->strength;
635                         CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
636                         pt->time = ptc->time;
637
638                         pt++;
639                 }
640
641                 if (totelem == 2) {
642                         /* last point if applicable */
643                         ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_size - 1);
644
645                         /* convert screen-coordinates to appropriate coordinates (and store them) */
646                         gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
647
648                         /* copy pressure and time */
649                         pt->pressure = ptc->pressure;
650                         pt->strength = ptc->strength;
651                         CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
652                         pt->time = ptc->time;
653                 }
654         }
655         else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) {
656                 /* first point */
657                 ptc = gpd->runtime.sbuffer;
658
659                 /* convert screen-coordinates to appropriate coordinates (and store them) */
660                 gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL);
661
662                 /* copy pressure and time */
663                 pt->pressure = ptc->pressure;
664                 pt->strength = ptc->strength;
665                 pt->time = ptc->time;
666         }
667         else {
668                 float *depth_arr = NULL;
669
670                 /* get an array of depths, far depths are blended */
671                 if (gpencil_project_check(p)) {
672                         int mval_i[2], mval_prev[2] = { 0 };
673                         int interp_depth = 0;
674                         int found_depth = 0;
675
676                         depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_size, "depth_points");
677
678                         for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size; i++, ptc++, pt++) {
679                                 round_v2i_v2fl(mval_i, &ptc->x);
680
681                                 if ((ED_view3d_autodist_depth(p->ar, mval_i, depth_margin, depth_arr + i) == 0) &&
682                                     (i && (ED_view3d_autodist_depth_seg(p->ar, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0)))
683                                 {
684                                         interp_depth = true;
685                                 }
686                                 else {
687                                         found_depth = true;
688                                 }
689
690                                 copy_v2_v2_int(mval_prev, mval_i);
691                         }
692
693                         if (found_depth == false) {
694                                 /* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */
695                                 for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--)
696                                         depth_arr[i] = 0.9999f;
697                         }
698                         else {
699                                 if (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE_ENDPOINTS) {
700                                         /* remove all info between the valid endpoints */
701                                         int first_valid = 0;
702                                         int last_valid = 0;
703
704                                         for (i = 0; i < gpd->runtime.sbuffer_size; i++) {
705                                                 if (depth_arr[i] != FLT_MAX)
706                                                         break;
707                                         }
708                                         first_valid = i;
709
710                                         for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) {
711                                                 if (depth_arr[i] != FLT_MAX)
712                                                         break;
713                                         }
714                                         last_valid = i;
715
716                                         /* invalidate non-endpoints, so only blend between first and last */
717                                         for (i = first_valid + 1; i < last_valid; i++)
718                                                 depth_arr[i] = FLT_MAX;
719
720                                         interp_depth = true;
721                                 }
722
723                                 if (interp_depth) {
724                                         interp_sparse_array(depth_arr, gpd->runtime.sbuffer_size, FLT_MAX);
725                                 }
726                         }
727                 }
728
729
730                 pt = gps->points;
731
732                 /* convert all points (normal behavior) */
733                 for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size && ptc; i++, ptc++, pt++) {
734                         /* convert screen-coordinates to appropriate coordinates (and store them) */
735                         gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL);
736
737                         /* copy pressure and time */
738                         pt->pressure = ptc->pressure;
739                         pt->strength = ptc->strength;
740                         CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
741                         pt->time = ptc->time;
742                 }
743
744                 if (depth_arr)
745                         MEM_freeN(depth_arr);
746         }
747
748         /* add stroke to frame */
749         BLI_addtail(&p->gpf->strokes, gps);
750         gp_stroke_added_enable(p);
751 }
752
753 /* --- 'Eraser' for 'Paint' Tool ------ */
754
755 /* helper to free a stroke
756  * NOTE: gps->dvert and gps->triangles should be NULL, but check anyway for good measure
757  */
758 static void gp_free_stroke(bGPDframe *gpf, bGPDstroke *gps)
759 {
760         if (gps->points) {
761                 MEM_freeN(gps->points);
762         }
763
764         if (gps->dvert) {
765                 BKE_gpencil_free_stroke_weights(gps);
766                 MEM_freeN(gps->dvert);
767         }
768
769         if (gps->triangles) {
770                 MEM_freeN(gps->triangles);
771         }
772
773         BLI_freelinkN(&gpf->strokes, gps);
774 }
775
776
777 /* which which point is infront (result should only be used for comparison) */
778 static float view3d_point_depth(const RegionView3D *rv3d, const float co[3])
779 {
780         if (rv3d->is_persp) {
781                 return ED_view3d_calc_zfac(rv3d, co, NULL);
782         }
783         else {
784                 return -dot_v3v3(rv3d->viewinv[2], co);
785         }
786 }
787
788 /* only erase stroke points that are visible (3d view) */
789 static bool gp_stroke_eraser_is_occluded(tGPsdata *p, const bGPDspoint *pt, const int x, const int y)
790 {
791         if ((p->sa->spacetype == SPACE_VIEW3D) &&
792             (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH))
793         {
794                 RegionView3D *rv3d = p->ar->regiondata;
795                 const int mval_i[2] = {x, y};
796                 float mval_3d[3];
797
798                 if (ED_view3d_autodist_simple(p->ar, mval_i, mval_3d, 0, NULL)) {
799                         const float depth_mval = view3d_point_depth(rv3d, mval_3d);
800                         const float depth_pt   = view3d_point_depth(rv3d, &pt->x);
801
802                         if (depth_pt > depth_mval) {
803                                 return true;
804                         }
805                 }
806         }
807         return false;
808 }
809
810 /* eraser tool - evaluation per stroke */
811 /* TODO: this could really do with some optimization (KD-Tree/BVH?) */
812 static void gp_stroke_eraser_dostroke(
813         tGPsdata *p,
814         bGPDframe *gpf, bGPDstroke *gps,
815         const float mval[2], const float mvalo[2],
816         const int radius, const rcti *rect)
817 {
818         bGPDspoint *pt1, *pt2;
819         int pc1[2] = {0};
820         int pc2[2] = {0};
821         int i;
822         int mval_i[2];
823         round_v2i_v2fl(mval_i, mval);
824
825         if (gps->totpoints == 0) {
826                 /* just free stroke */
827                 gp_free_stroke(gpf, gps);
828         }
829         else if (gps->totpoints == 1) {
830                 /* only process if it hasn't been masked out... */
831                 if (!(p->flags & GP_PAINTFLAG_SELECTMASK) || (gps->points->flag & GP_SPOINT_SELECT)) {
832                         gp_point_to_xy(&p->gsc, gps, gps->points, &pc1[0], &pc1[1]);
833
834                         /* do boundbox check first */
835                         if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) {
836                                 /* only check if point is inside */
837                                 if (len_v2v2_int(mval_i, pc1) <= radius) {
838                                         /* free stroke */
839                                         gp_free_stroke(gpf, gps);
840                                 }
841                         }
842                 }
843         }
844         else {
845                 /* Perform culling? */
846                 bool do_cull = false;
847
848                 /* Clear Tags
849                  *
850                  * Note: It's better this way, as we are sure that
851                  * we don't miss anything, though things will be
852                  * slightly slower as a result
853                  */
854                 for (i = 0; i < gps->totpoints; i++) {
855                         bGPDspoint *pt = &gps->points[i];
856                         pt->flag &= ~GP_SPOINT_TAG;
857                 }
858
859                 /* First Pass: Loop over the points in the stroke
860                  *   1) Thin out parts of the stroke under the brush
861                  *   2) Tag "too thin" parts for removal (in second pass)
862                  */
863                 for (i = 0; (i + 1) < gps->totpoints; i++) {
864                         /* get points to work with */
865                         pt1 = gps->points + i;
866                         pt2 = gps->points + i + 1;
867
868                         /* only process if it hasn't been masked out... */
869                         if ((p->flags & GP_PAINTFLAG_SELECTMASK) && !(gps->points->flag & GP_SPOINT_SELECT))
870                                 continue;
871
872                         gp_point_to_xy(&p->gsc, gps, pt1, &pc1[0], &pc1[1]);
873                         gp_point_to_xy(&p->gsc, gps, pt2, &pc2[0], &pc2[1]);
874
875                         /* Check that point segment of the boundbox of the eraser stroke */
876                         if (((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) ||
877                             ((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1])))
878                         {
879                                 /* Check if point segment of stroke had anything to do with
880                                  * eraser region  (either within stroke painted, or on its lines)
881                                  *  - this assumes that linewidth is irrelevant
882                                  */
883                                 if (gp_stroke_inside_circle(mval, mvalo, radius, pc1[0], pc1[1], pc2[0], pc2[1])) {
884                                         if ((gp_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) ||
885                                             (gp_stroke_eraser_is_occluded(p, pt2, pc2[0], pc2[1]) == false))
886                                         {
887                                                 /* Edge is affected - Check individual points now */
888                                                 if (len_v2v2_int(mval_i, pc1) <= radius) {
889                                                         pt1->flag |= GP_SPOINT_TAG;
890                                                 }
891                                                 if (len_v2v2_int(mval_i, pc2) <= radius) {
892                                                         pt2->flag |= GP_SPOINT_TAG;
893                                                 }
894                                                 do_cull = true;
895                                         }
896                                 }
897                         }
898                 }
899
900                 /* Second Pass: Remove any points that are tagged */
901                 if (do_cull) {
902                         gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG, false, 0);
903                 }
904         }
905 }
906
907 /* erase strokes which fall under the eraser strokes */
908 static void gp_stroke_doeraser(tGPsdata *p)
909 {
910         bGPDframe *gpf = p->gpf;
911         bGPDstroke *gps, *gpn;
912         rcti rect;
913
914         /* rect is rectangle of eraser */
915         rect.xmin = p->mval[0] - p->radius;
916         rect.ymin = p->mval[1] - p->radius;
917         rect.xmax = p->mval[0] + p->radius;
918         rect.ymax = p->mval[1] + p->radius;
919
920         if (p->sa->spacetype == SPACE_VIEW3D) {
921                 if (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH) {
922                         View3D *v3d = p->sa->spacedata.first;
923                         view3d_region_operator_needs_opengl(p->win, p->ar);
924                         ED_view3d_autodist_init(p->depsgraph, p->ar, v3d, 0);
925                 }
926         }
927
928         /* loop over strokes of active layer only (session init already took care of ensuring validity),
929          * checking segments for intersections to remove
930          */
931         for (gps = gpf->strokes.first; gps; gps = gpn) {
932                 gpn = gps->next;
933                 /* Not all strokes in the datablock may be valid in the current editor/context
934                  * (e.g. 2D space strokes in the 3D view, if the same datablock is shared)
935                  */
936                 if (ED_gpencil_stroke_can_use_direct(p->sa, gps)) {
937                         gp_stroke_eraser_dostroke(p, gpf, gps, p->mval, p->mvalo, p->radius, &rect);
938                 }
939         }
940 }
941
942 /* ******************************************* */
943 /* Sketching Operator */
944
945 /* clear the session buffers (call this before AND after a paint operation) */
946 static void gp_session_validatebuffer(tGPsdata *p)
947 {
948         bGPdata *gpd = p->gpd;
949
950         /* clear memory of buffer (or allocate it if starting a new session) */
951         if (gpd->runtime.sbuffer) {
952                 /* printf("\t\tGP - reset sbuffer\n"); */
953                 memset(gpd->runtime.sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX);
954         }
955         else {
956                 /* printf("\t\tGP - allocate sbuffer\n"); */
957                 gpd->runtime.sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer");
958         }
959
960         /* reset indices */
961         gpd->runtime.sbuffer_size = 0;
962
963         /* reset flags */
964         gpd->runtime.sbuffer_sflag = 0;
965
966         /* reset inittime */
967         p->inittime = 0.0;
968 }
969
970 /* (re)init new painting data */
971 static bool gp_session_initdata(bContext *C, tGPsdata *p)
972 {
973         Main *bmain = CTX_data_main(C);
974         bGPdata **gpd_ptr = NULL;
975         ScrArea *curarea = CTX_wm_area(C);
976         ARegion *ar = CTX_wm_region(C);
977         ToolSettings *ts = CTX_data_tool_settings(C);
978
979         /* make sure the active view (at the starting time) is a 3d-view */
980         if (curarea == NULL) {
981                 p->status = GP_STATUS_ERROR;
982                 if (G.debug & G_DEBUG)
983                         printf("Error: No active view for painting\n");
984                 return 0;
985         }
986
987         /* pass on current scene and window */
988         p->bmain = CTX_data_main(C);
989         p->scene = CTX_data_scene(C);
990         p->depsgraph = CTX_data_depsgraph(C);
991         p->win = CTX_wm_window(C);
992
993         unit_m4(p->imat);
994         unit_m4(p->mat);
995
996         switch (curarea->spacetype) {
997                 /* supported views first */
998                 case SPACE_VIEW3D:
999                 {
1000                         /* View3D *v3d = curarea->spacedata.first; */
1001                         /* RegionView3D *rv3d = ar->regiondata; */
1002
1003                         /* set current area
1004                          * - must verify that region data is 3D-view (and not something else)
1005                          */
1006                         /* CAUTION: If this is the "toolbar", then this will change on the first stroke */
1007                         p->sa = curarea;
1008                         p->ar = ar;
1009                         p->align_flag = &ts->annotate_v3d_align;
1010
1011                         if (ar->regiondata == NULL) {
1012                                 p->status = GP_STATUS_ERROR;
1013                                 if (G.debug & G_DEBUG)
1014                                         printf("Error: 3D-View active region doesn't have any region data, so cannot be drawable\n");
1015                                 return 0;
1016                         }
1017                         break;
1018                 }
1019                 case SPACE_NODE:
1020                 {
1021                         /* SpaceNode *snode = curarea->spacedata.first; */
1022
1023                         /* set current area */
1024                         p->sa = curarea;
1025                         p->ar = ar;
1026                         p->v2d = &ar->v2d;
1027                         p->align_flag = &ts->gpencil_v2d_align;
1028                         break;
1029                 }
1030                 case SPACE_SEQ:
1031                 {
1032                         SpaceSeq *sseq = curarea->spacedata.first;
1033
1034                         /* set current area */
1035                         p->sa = curarea;
1036                         p->ar = ar;
1037                         p->v2d = &ar->v2d;
1038                         p->align_flag = &ts->gpencil_seq_align;
1039
1040                         /* check that gpencil data is allowed to be drawn */
1041                         if (sseq->mainb == SEQ_DRAW_SEQUENCE) {
1042                                 p->status = GP_STATUS_ERROR;
1043                                 if (G.debug & G_DEBUG)
1044                                         printf("Error: In active view (sequencer), active mode doesn't support Grease Pencil\n");
1045                                 return 0;
1046                         }
1047                         break;
1048                 }
1049                 case SPACE_IMAGE:
1050                 {
1051                         /* SpaceImage *sima = curarea->spacedata.first; */
1052
1053                         /* set the current area */
1054                         p->sa = curarea;
1055                         p->ar = ar;
1056                         p->v2d = &ar->v2d;
1057                         p->align_flag = &ts->gpencil_ima_align;
1058                         break;
1059                 }
1060                 case SPACE_CLIP:
1061                 {
1062                         SpaceClip *sc = curarea->spacedata.first;
1063                         MovieClip *clip = ED_space_clip_get_clip(sc);
1064
1065                         if (clip == NULL) {
1066                                 p->status = GP_STATUS_ERROR;
1067                                 return false;
1068                         }
1069
1070                         /* set the current area */
1071                         p->sa = curarea;
1072                         p->ar = ar;
1073                         p->v2d = &ar->v2d;
1074                         p->align_flag = &ts->gpencil_v2d_align;
1075
1076                         invert_m4_m4(p->imat, sc->unistabmat);
1077
1078                         /* custom color for new layer */
1079                         p->custom_color[0] = 1.0f;
1080                         p->custom_color[1] = 0.0f;
1081                         p->custom_color[2] = 0.5f;
1082                         p->custom_color[3] = 0.9f;
1083
1084                         if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
1085                                 int framenr = ED_space_clip_get_clip_frame_number(sc);
1086                                 MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking);
1087                                 MovieTrackingMarker *marker = track ? BKE_tracking_marker_get(track, framenr) : NULL;
1088
1089                                 if (marker) {
1090                                         p->imat[3][0] -= marker->pos[0];
1091                                         p->imat[3][1] -= marker->pos[1];
1092                                 }
1093                                 else {
1094                                         p->status = GP_STATUS_ERROR;
1095                                         return false;
1096                                 }
1097                         }
1098
1099                         invert_m4_m4(p->mat, p->imat);
1100                         copy_m4_m4(p->gsc.mat, p->mat);
1101                         break;
1102                 }
1103                 /* unsupported views */
1104                 default:
1105                 {
1106                         p->status = GP_STATUS_ERROR;
1107                         if (G.debug & G_DEBUG)
1108                                 printf("Error: Annotations are not supported in this editor\n");
1109                         return 0;
1110                 }
1111         }
1112
1113         /* get gp-data */
1114         gpd_ptr = ED_gpencil_data_get_pointers(C, &p->ownerPtr);
1115         if ((gpd_ptr == NULL) || !ED_gpencil_data_owner_is_annotation(&p->ownerPtr)) {
1116                 p->status = GP_STATUS_ERROR;
1117                 if (G.debug & G_DEBUG)
1118                         printf("Error: Current context doesn't allow for any Annotation data\n");
1119                 return 0;
1120         }
1121         else {
1122                 /* if no existing GPencil block exists, add one */
1123                 if (*gpd_ptr == NULL) {
1124                         bGPdata *gpd = BKE_gpencil_data_addnew(bmain, "Annotations");
1125                         *gpd_ptr = gpd;
1126
1127                         /* mark datablock as being used for annotations */
1128                         gpd->flag |= GP_DATA_ANNOTATIONS;
1129
1130                         /* annotations always in front of all objects */
1131                         gpd->xray_mode = GP_XRAY_FRONT;
1132                 }
1133                 p->gpd = *gpd_ptr;
1134         }
1135
1136         if (ED_gpencil_session_active() == 0) {
1137                 /* initialize undo stack,
1138                  * also, existing undo stack would make buffer drawn
1139                  */
1140                 gpencil_undo_init(p->gpd);
1141         }
1142
1143         /* clear out buffer (stored in gp-data), in case something contaminated it */
1144         gp_session_validatebuffer(p);
1145
1146         return 1;
1147 }
1148
1149 /* init new painting session */
1150 static tGPsdata *gp_session_initpaint(bContext *C)
1151 {
1152         tGPsdata *p = NULL;
1153
1154         /* create new context data */
1155         p = MEM_callocN(sizeof(tGPsdata), "Annotation Drawing Data");
1156
1157         /* Try to initialise context data
1158          * WARNING: This may not always succeed (e.g. using GP in an annotation-only context)
1159          */
1160         if (gp_session_initdata(C, p) == 0) {
1161                 /* Invalid state - Exit
1162                  * NOTE: It should be safe to just free the data, since failing context checks should
1163                  * only happen when no data has been allocated.
1164                  */
1165                 MEM_freeN(p);
1166                 return NULL;
1167         }
1168
1169         /* Radius for eraser circle is defined in userprefs */
1170         /* NOTE: we do this here, so that if we exit immediately,
1171          *       erase size won't get lost
1172          */
1173         p->radius = U.gp_eraser;
1174
1175         /* return context data for running paint operator */
1176         return p;
1177 }
1178
1179 /* cleanup after a painting session */
1180 static void gp_session_cleanup(tGPsdata *p)
1181 {
1182         bGPdata *gpd = (p) ? p->gpd : NULL;
1183
1184         /* error checking */
1185         if (gpd == NULL)
1186                 return;
1187
1188         /* free stroke buffer */
1189         if (gpd->runtime.sbuffer) {
1190                 /* printf("\t\tGP - free sbuffer\n"); */
1191                 MEM_freeN(gpd->runtime.sbuffer);
1192                 gpd->runtime.sbuffer = NULL;
1193         }
1194
1195         /* clear flags */
1196         gpd->runtime.sbuffer_size = 0;
1197         gpd->runtime.sbuffer_sflag = 0;
1198         p->inittime = 0.0;
1199 }
1200
1201 static void gp_session_free(tGPsdata *p)
1202 {
1203         MEM_freeN(p);
1204 }
1205
1206
1207 /* init new stroke */
1208 static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Depsgraph *depsgraph)
1209 {
1210         Scene *scene = p->scene;
1211         ToolSettings *ts = scene->toolsettings;
1212
1213         /* get active layer (or add a new one if non-existent) */
1214         p->gpl = BKE_gpencil_layer_getactive(p->gpd);
1215         if (p->gpl == NULL) {
1216                 /* tag for annotations */
1217                 p->gpd->flag |= GP_DATA_ANNOTATIONS;
1218                 p->gpl = BKE_gpencil_layer_addnew(p->gpd, DATA_("Note"), true);
1219
1220                 if (p->custom_color[3])
1221                         copy_v3_v3(p->gpl->color, p->custom_color);
1222         }
1223         if (p->gpl->flag & GP_LAYER_LOCKED) {
1224                 p->status = GP_STATUS_ERROR;
1225                 if (G.debug & G_DEBUG)
1226                         printf("Error: Cannot paint on locked layer\n");
1227                 return;
1228         }
1229
1230         /* get active frame (add a new one if not matching frame) */
1231         if (paintmode == GP_PAINTMODE_ERASER) {
1232                 /* Eraser mode:
1233                  * 1) Only allow erasing on the active layer (unlike for 3d-art Grease Pencil),
1234                  *    since we won't be exposing layer locking in the UI
1235                  * 2) Ensure that p->gpf refers to the frame used for the active layer
1236                  *    (to avoid problems with other tools which expect it to exist)
1237                  */
1238                 bool has_layer_to_erase = false;
1239
1240                 if (gpencil_layer_is_editable(p->gpl)) {
1241                         /* Ensure that there's stuff to erase here (not including selection mask below)... */
1242                         if (p->gpl->actframe && p->gpl->actframe->strokes.first) {
1243                                 has_layer_to_erase = true;
1244                         }
1245                 }
1246
1247                 /* Ensure active frame is set correctly... */
1248                 p->gpf = p->gpl->actframe;
1249
1250                 /* Restrict eraser to only affecting selected strokes, if the "selection mask" is on
1251                  * (though this is only available in editmode)
1252                  */
1253                 if (p->gpd->flag & GP_DATA_STROKE_EDITMODE) {
1254                         if (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_SELECT_MASK) {
1255                                 p->flags |= GP_PAINTFLAG_SELECTMASK;
1256                         }
1257                 }
1258
1259                 if (has_layer_to_erase == false) {
1260                         p->status = GP_STATUS_ERROR;
1261                         //if (G.debug & G_DEBUG)
1262                                 printf("Error: Eraser will not be affecting anything (gpencil_paint_init)\n");
1263                         return;
1264                 }
1265         }
1266         else {
1267                 /* Drawing Modes - Add a new frame if needed on the active layer */
1268                 short add_frame_mode = GP_GETFRAME_ADD_NEW;
1269
1270                 if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST)
1271                         add_frame_mode = GP_GETFRAME_ADD_COPY;
1272                 else
1273                         add_frame_mode = GP_GETFRAME_ADD_NEW;
1274
1275                 p->gpf = BKE_gpencil_layer_getframe(p->gpl, CFRA, add_frame_mode);
1276
1277                 if (p->gpf == NULL) {
1278                         p->status = GP_STATUS_ERROR;
1279                         if (G.debug & G_DEBUG)
1280                                 printf("Error: No frame created (gpencil_paint_init)\n");
1281                         return;
1282                 }
1283                 else {
1284                         p->gpf->flag |= GP_FRAME_PAINT;
1285                 }
1286         }
1287
1288         /* set 'eraser' for this stroke if using eraser */
1289         p->paintmode = paintmode;
1290         if (p->paintmode == GP_PAINTMODE_ERASER) {
1291                 p->gpd->runtime.sbuffer_sflag |= GP_STROKE_ERASER;
1292
1293                 /* check if we should respect depth while erasing */
1294                 if (p->sa->spacetype == SPACE_VIEW3D) {
1295                         if (p->gpl->flag & GP_LAYER_NO_XRAY) {
1296                                 p->flags |= GP_PAINTFLAG_V3D_ERASER_DEPTH;
1297                         }
1298                 }
1299         }
1300         else {
1301                 /* disable eraser flags - so that we can switch modes during a session */
1302                 p->gpd->runtime.sbuffer_sflag &= ~GP_STROKE_ERASER;
1303
1304                 if (p->sa->spacetype == SPACE_VIEW3D) {
1305                         if (p->gpl->flag & GP_LAYER_NO_XRAY) {
1306                                 p->flags &= ~GP_PAINTFLAG_V3D_ERASER_DEPTH;
1307                         }
1308                 }
1309         }
1310
1311         /* set 'initial run' flag, which is only used to denote when a new stroke is starting */
1312         p->flags |= GP_PAINTFLAG_FIRSTRUN;
1313
1314
1315         /* when drawing in the camera view, in 2D space, set the subrect */
1316         p->subrect = NULL;
1317         if ((*p->align_flag & GP_PROJECT_VIEWSPACE) == 0) {
1318                 if (p->sa->spacetype == SPACE_VIEW3D) {
1319                         View3D *v3d = p->sa->spacedata.first;
1320                         RegionView3D *rv3d = p->ar->regiondata;
1321
1322                         /* for camera view set the subrect */
1323                         if (rv3d->persp == RV3D_CAMOB) {
1324                                 /* no shift */
1325                                 ED_view3d_calc_camera_border(p->scene, depsgraph, p->ar, v3d, rv3d, &p->subrect_data, true);
1326                                 p->subrect = &p->subrect_data;
1327                         }
1328                 }
1329         }
1330
1331         /* init stroke point space-conversion settings... */
1332         p->gsc.gpd = p->gpd;
1333         p->gsc.gpl = p->gpl;
1334
1335         p->gsc.sa = p->sa;
1336         p->gsc.ar = p->ar;
1337         p->gsc.v2d = p->v2d;
1338
1339         p->gsc.subrect_data = p->subrect_data;
1340         p->gsc.subrect = p->subrect;
1341
1342         copy_m4_m4(p->gsc.mat, p->mat);
1343
1344
1345         /* check if points will need to be made in view-aligned space */
1346         if (*p->align_flag & GP_PROJECT_VIEWSPACE) {
1347                 switch (p->sa->spacetype) {
1348                         case SPACE_VIEW3D:
1349                         {
1350                                 p->gpd->runtime.sbuffer_sflag |= GP_STROKE_3DSPACE;
1351                                 break;
1352                         }
1353                         case SPACE_NODE:
1354                         {
1355                                 p->gpd->runtime.sbuffer_sflag |= GP_STROKE_2DSPACE;
1356                                 break;
1357                         }
1358                         case SPACE_SEQ:
1359                         {
1360                                 p->gpd->runtime.sbuffer_sflag |= GP_STROKE_2DSPACE;
1361                                 break;
1362                         }
1363                         case SPACE_IMAGE:
1364                         {
1365                                 SpaceImage *sima = (SpaceImage *)p->sa->spacedata.first;
1366
1367                                 /* only set these flags if the image editor doesn't have an image active,
1368                                  * otherwise user will be confused by strokes not appearing after they're drawn
1369                                  *
1370                                  * Admittedly, this is a bit hacky, but it works much nicer from an ergonomic standpoint!
1371                                  */
1372                                 if (ELEM(NULL, sima, sima->image)) {
1373                                         /* make strokes be drawn in screen space */
1374                                         p->gpd->runtime.sbuffer_sflag &= ~GP_STROKE_2DSPACE;
1375                                         *(p->align_flag) &= ~GP_PROJECT_VIEWSPACE;
1376                                 }
1377                                 else {
1378                                         p->gpd->runtime.sbuffer_sflag |= GP_STROKE_2DSPACE;
1379                                 }
1380                                 break;
1381                         }
1382                         case SPACE_CLIP:
1383                         {
1384                                 p->gpd->runtime.sbuffer_sflag |= GP_STROKE_2DSPACE;
1385                                 break;
1386                         }
1387                 }
1388         }
1389 }
1390
1391 /* finish off a stroke (clears buffer, but doesn't finish the paint operation) */
1392 static void gp_paint_strokeend(tGPsdata *p)
1393 {
1394         ToolSettings *ts = p->scene->toolsettings;
1395         /* for surface sketching, need to set the right OpenGL context stuff so that
1396          * the conversions will project the values correctly...
1397          */
1398         if (gpencil_project_check(p)) {
1399                 View3D *v3d = p->sa->spacedata.first;
1400
1401                 /* need to restore the original projection settings before packing up */
1402                 view3d_region_operator_needs_opengl(p->win, p->ar);
1403                 ED_view3d_autodist_init(p->depsgraph, p->ar, v3d, (ts->annotate_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
1404         }
1405
1406         /* check if doing eraser or not */
1407         if ((p->gpd->runtime.sbuffer_sflag & GP_STROKE_ERASER) == 0) {
1408                 /* simplify stroke before transferring? */
1409                 gp_stroke_simplify(p);
1410
1411                 /* transfer stroke to frame */
1412                 gp_stroke_newfrombuffer(p);
1413         }
1414
1415         /* clean up buffer now */
1416         gp_session_validatebuffer(p);
1417 }
1418
1419 /* finish off stroke painting operation */
1420 static void gp_paint_cleanup(tGPsdata *p)
1421 {
1422         /* p->gpd==NULL happens when stroke failed to initialize,
1423          * for example when GP is hidden in current space (sergey)
1424          */
1425         if (p->gpd) {
1426                 /* finish off a stroke */
1427                 gp_paint_strokeend(p);
1428         }
1429
1430         /* "unlock" frame */
1431         if (p->gpf)
1432                 p->gpf->flag &= ~GP_FRAME_PAINT;
1433 }
1434
1435 /* ------------------------------- */
1436
1437 /* Helper callback for drawing the cursor itself */
1438 static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
1439 {
1440         tGPsdata *p = (tGPsdata *)p_ptr;
1441
1442         if (p->paintmode == GP_PAINTMODE_ERASER) {
1443                 GPUVertFormat *format = immVertexFormat();
1444                 const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1445                 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1446
1447                 GPU_line_smooth(true);
1448                 GPU_blend(true);
1449                 GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
1450
1451                 immUniformColor4ub(255, 100, 100, 20);
1452                 imm_draw_circle_fill_2d(shdr_pos, x, y, p->radius, 40);
1453
1454                 immUnbindProgram();
1455
1456                 immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
1457
1458                 float viewport_size[4];
1459                 GPU_viewport_size_get_f(viewport_size);
1460                 immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
1461
1462                 immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
1463                 immUniform1i("colors_len", 0);  /* "simple" mode */
1464                 immUniform1f("dash_width", 12.0f);
1465                 immUniform1f("dash_factor", 0.5f);
1466
1467                 imm_draw_circle_wire_2d(
1468                         shdr_pos, x, y, p->radius,
1469                         /* XXX Dashed shader gives bad results with sets of small segments currently,
1470                          *     temp hack around the issue. :( */
1471                         max_ii(8, p->radius / 2));  /* was fixed 40 */
1472
1473                 immUnbindProgram();
1474
1475                 GPU_blend(false);
1476                 GPU_line_smooth(false);
1477         }
1478 }
1479
1480 /* Turn brush cursor in 3D view on/off */
1481 static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short enable)
1482 {
1483         if (p->erasercursor && !enable) {
1484                 /* clear cursor */
1485                 WM_paint_cursor_end(CTX_wm_manager(C), p->erasercursor);
1486                 p->erasercursor = NULL;
1487         }
1488         else if (enable && !p->erasercursor) {
1489                 /* enable cursor */
1490                 p->erasercursor = WM_paint_cursor_activate(
1491                         CTX_wm_manager(C),
1492                         SPACE_TYPE_ANY, RGN_TYPE_ANY,
1493                         NULL, /* XXX */
1494                         gpencil_draw_eraser, p);
1495         }
1496 }
1497
1498 /* Check if tablet eraser is being used (when processing events) */
1499 static bool gpencil_is_tablet_eraser_active(const wmEvent *event)
1500 {
1501         if (event->tablet_data) {
1502                 const wmTabletData *wmtab = event->tablet_data;
1503                 return (wmtab->Active == EVT_TABLET_ERASER);
1504         }
1505
1506         return false;
1507 }
1508
1509 /* ------------------------------- */
1510
1511 static void gpencil_draw_exit(bContext *C, wmOperator *op)
1512 {
1513         tGPsdata *p = op->customdata;
1514
1515         /* restore cursor to indicate end of drawing */
1516         WM_cursor_modal_restore(CTX_wm_window(C));
1517
1518         /* don't assume that operator data exists at all */
1519         if (p) {
1520                 /* check size of buffer before cleanup, to determine if anything happened here */
1521                 if (p->paintmode == GP_PAINTMODE_ERASER) {
1522                         /* turn off radial brush cursor */
1523                         gpencil_draw_toggle_eraser_cursor(C, p, false);
1524                 }
1525
1526                 /* always store the new eraser size to be used again next time
1527                  * NOTE: Do this even when not in eraser mode, as eraser may
1528                  *       have been toggled at some point.
1529                  */
1530                 U.gp_eraser = p->radius;
1531
1532                 /* clear undo stack */
1533                 gpencil_undo_finish();
1534
1535                 /* cleanup */
1536                 gp_paint_cleanup(p);
1537                 gp_session_cleanup(p);
1538                 gp_session_free(p);
1539                 p = NULL;
1540         }
1541
1542         op->customdata = NULL;
1543 }
1544
1545 static void gpencil_draw_cancel(bContext *C, wmOperator *op)
1546 {
1547         /* this is just a wrapper around exit() */
1548         gpencil_draw_exit(C, op);
1549 }
1550
1551 /* ------------------------------- */
1552
1553
1554 static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
1555 {
1556         tGPsdata *p;
1557         eGPencil_PaintModes paintmode = RNA_enum_get(op->ptr, "mode");
1558
1559         /* check context */
1560         p = op->customdata = gp_session_initpaint(C);
1561         if ((p == NULL) || (p->status == GP_STATUS_ERROR)) {
1562                 /* something wasn't set correctly in context */
1563                 gpencil_draw_exit(C, op);
1564                 return 0;
1565         }
1566
1567         /* init painting data */
1568         gp_paint_initstroke(p, paintmode, CTX_data_depsgraph(C));
1569         if (p->status == GP_STATUS_ERROR) {
1570                 gpencil_draw_exit(C, op);
1571                 return 0;
1572         }
1573
1574         if (event != NULL) {
1575                 p->keymodifier = event->keymodifier;
1576         }
1577         else {
1578                 p->keymodifier = -1;
1579         }
1580
1581         /* everything is now setup ok */
1582         return 1;
1583 }
1584
1585
1586 /* ------------------------------- */
1587
1588 /* ensure that the correct cursor icon is set */
1589 static void gpencil_draw_cursor_set(tGPsdata *p)
1590 {
1591         if (p->paintmode == GP_PAINTMODE_ERASER)
1592                 WM_cursor_modal_set(p->win, BC_CROSSCURSOR);  /* XXX need a better cursor */
1593         else
1594                 WM_cursor_modal_set(p->win, BC_PAINTBRUSHCURSOR);
1595 }
1596
1597 /* update UI indicators of status, including cursor and header prints */
1598 static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p)
1599 {
1600         /* header prints */
1601         switch (p->status) {
1602                 case GP_STATUS_PAINTING:
1603                         switch (p->paintmode) {
1604                                 case GP_PAINTMODE_DRAW_POLY:
1605                                         /* Provide usage tips, since this is modal, and unintuitive without hints */
1606                                         ED_workspace_status_text(C, IFACE_("Annotation Create Poly: LMB click to place next stroke vertex | "
1607                                                                           "ESC/Enter to end  (or click outside this area)"));
1608                                         break;
1609                                 default:
1610                                         /* Do nothing - the others are self explanatory, exit quickly once the mouse is released
1611                                          * Showing any text would just be annoying as it would flicker.
1612                                          */
1613                                         break;
1614                         }
1615                         break;
1616
1617                 case GP_STATUS_IDLING:
1618                         /* print status info */
1619                         switch (p->paintmode) {
1620                                 case GP_PAINTMODE_ERASER:
1621                                         ED_workspace_status_text(C, IFACE_("Annotation Eraser: Hold and drag LMB or RMB to erase | "
1622                                                                           "ESC/Enter to end  (or click outside this area)"));
1623                                         break;
1624                                 case GP_PAINTMODE_DRAW_STRAIGHT:
1625                                         ED_workspace_status_text(C, IFACE_("Annotation Line Draw: Hold and drag LMB to draw | "
1626                                                                           "ESC/Enter to end  (or click outside this area)"));
1627                                         break;
1628                                 case GP_PAINTMODE_DRAW:
1629                                         ED_workspace_status_text(C, IFACE_("Annotation Freehand Draw: Hold and drag LMB to draw | "
1630                                                                           "E/ESC/Enter to end  (or click outside this area)"));
1631                                         break;
1632                                 case GP_PAINTMODE_DRAW_POLY:
1633                                         ED_workspace_status_text(C, IFACE_("Annotation Create Poly: LMB click to place next stroke vertex | "
1634                                                                           "ESC/Enter to end  (or click outside this area)"));
1635                                         break;
1636
1637                                 default: /* unhandled future cases */
1638                                         ED_workspace_status_text(C, IFACE_("Annotation Session: ESC/Enter to end   (or click outside this area)"));
1639                                         break;
1640                         }
1641                         break;
1642
1643                 case GP_STATUS_ERROR:
1644                 case GP_STATUS_DONE:
1645                         /* clear status string */
1646                         ED_workspace_status_text(C, NULL);
1647                         break;
1648         }
1649 }
1650
1651 /* ------------------------------- */
1652
1653 /* create a new stroke point at the point indicated by the painting context */
1654 static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph)
1655 {
1656         /* handle drawing/erasing -> test for erasing first */
1657         if (p->paintmode == GP_PAINTMODE_ERASER) {
1658                 /* do 'live' erasing now */
1659                 gp_stroke_doeraser(p);
1660
1661                 /* store used values */
1662                 p->mvalo[0] = p->mval[0];
1663                 p->mvalo[1] = p->mval[1];
1664                 p->opressure = p->pressure;
1665         }
1666         /* only add current point to buffer if mouse moved (even though we got an event, it might be just noise) */
1667         else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) {
1668                 /* try to add point */
1669                 short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime);
1670
1671                 /* handle errors while adding point */
1672                 if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) {
1673                         /* finish off old stroke */
1674                         gp_paint_strokeend(p);
1675                         /* And start a new one!!! Else, projection errors! */
1676                         gp_paint_initstroke(p, p->paintmode, depsgraph);
1677
1678                         /* start a new stroke, starting from previous point */
1679                         /* XXX Must manually reset inittime... */
1680                         /* XXX We only need to reuse previous point if overflow! */
1681                         if (ok == GP_STROKEADD_OVERFLOW) {
1682                                 p->inittime = p->ocurtime;
1683                                 gp_stroke_addpoint(p, p->mvalo, p->opressure, p->ocurtime);
1684                         }
1685                         else {
1686                                 p->inittime = p->curtime;
1687                         }
1688                         gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime);
1689                 }
1690                 else if (ok == GP_STROKEADD_INVALID) {
1691                         /* the painting operation cannot continue... */
1692                         BKE_report(op->reports, RPT_ERROR, "Cannot paint stroke");
1693                         p->status = GP_STATUS_ERROR;
1694
1695                         if (G.debug & G_DEBUG)
1696                                 printf("Error: Grease-Pencil Paint - Add Point Invalid\n");
1697                         return;
1698                 }
1699
1700                 /* store used values */
1701                 p->mvalo[0] = p->mval[0];
1702                 p->mvalo[1] = p->mval[1];
1703                 p->opressure = p->pressure;
1704                 p->ocurtime = p->curtime;
1705         }
1706 }
1707
1708 /* handle draw event */
1709 static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event, Depsgraph *depsgraph)
1710 {
1711         tGPsdata *p = op->customdata;
1712         PointerRNA itemptr;
1713         float mousef[2];
1714         int tablet = 0;
1715
1716         /* convert from window-space to area-space mouse coordinates
1717          * NOTE: float to ints conversions,
1718          * +1 factor is probably used to ensure a bit more accurate rounding...
1719          */
1720         p->mval[0] = event->mval[0] + 1;
1721         p->mval[1] = event->mval[1] + 1;
1722
1723         /* verify key status for straight lines */
1724         if ((event->ctrl > 0) || (event->alt > 0)) {
1725                 if (p->straight[0] == 0) {
1726                         int dx = abs((int)(p->mval[0] - p->mvalo[0]));
1727                         int dy = abs((int)(p->mval[1] - p->mvalo[1]));
1728                         if ((dx > 0) || (dy > 0)) {
1729                                 /* check mouse direction to replace the other coordinate with previous values */
1730                                 if (dx >= dy) {
1731                                         /* horizontal */
1732                                         p->straight[0] = 1;
1733                                         p->straight[1] = p->mval[1]; /* save y */
1734                                 }
1735                                 else {
1736                                         /* vertical */
1737                                         p->straight[0] = 2;
1738                                         p->straight[1] = p->mval[0]; /* save x */
1739                                 }
1740                         }
1741                 }
1742         }
1743         else {
1744                 p->straight[0] = 0;
1745         }
1746
1747         p->curtime = PIL_check_seconds_timer();
1748
1749         /* handle pressure sensitivity (which is supplied by tablets) */
1750         if (event->tablet_data) {
1751                 const wmTabletData *wmtab = event->tablet_data;
1752
1753                 tablet = (wmtab->Active != EVT_TABLET_NONE);
1754                 p->pressure = wmtab->Pressure;
1755
1756                 /* Hack for pressure sensitive eraser on D+RMB when using a tablet:
1757                  * The pen has to float over the tablet surface, resulting in
1758                  * zero pressure (T47101). Ignore pressure values if floating
1759                  * (i.e. "effectively zero" pressure), and only when the "active"
1760                  * end is the stylus (i.e. the default when not eraser)
1761                  */
1762                 if (p->paintmode == GP_PAINTMODE_ERASER) {
1763                         if ((wmtab->Active != EVT_TABLET_ERASER) && (p->pressure < 0.001f)) {
1764                                 p->pressure = 1.0f;
1765                         }
1766                 }
1767         }
1768         else {
1769                 /* No tablet data -> No pressure info is available */
1770                 p->pressure = 1.0f;
1771         }
1772
1773         /* special exception for start of strokes (i.e. maybe for just a dot) */
1774         if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
1775                 p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
1776
1777                 p->mvalo[0] = p->mval[0];
1778                 p->mvalo[1] = p->mval[1];
1779                 p->opressure = p->pressure;
1780                 p->inittime = p->ocurtime = p->curtime;
1781                 p->straight[0] = 0;
1782                 p->straight[1] = 0;
1783
1784                 /* special exception here for too high pressure values on first touch in
1785                  * windows for some tablets, then we just skip first touch...
1786                  */
1787                 if (tablet && (p->pressure >= 0.99f))
1788                         return;
1789         }
1790
1791         /* check if alt key is pressed and limit to straight lines */
1792         if ((p->paintmode != GP_PAINTMODE_ERASER) && (p->straight[0] != 0)) {
1793                 if (p->straight[0] == 1) {
1794                         /* horizontal */
1795                         p->mval[1] = p->straight[1]; /* replace y */
1796                 }
1797                 else {
1798                         /* vertical */
1799                         p->mval[0] = p->straight[1]; /* replace x */
1800                 }
1801         }
1802
1803         /* fill in stroke data (not actually used directly by gpencil_draw_apply) */
1804         RNA_collection_add(op->ptr, "stroke", &itemptr);
1805
1806         mousef[0] = p->mval[0];
1807         mousef[1] = p->mval[1];
1808         RNA_float_set_array(&itemptr, "mouse", mousef);
1809         RNA_float_set(&itemptr, "pressure", p->pressure);
1810         RNA_boolean_set(&itemptr, "is_start", (p->flags & GP_PAINTFLAG_FIRSTRUN) != 0);
1811
1812         RNA_float_set(&itemptr, "time", p->curtime - p->inittime);
1813
1814         /* apply the current latest drawing point */
1815         gpencil_draw_apply(op, p, depsgraph);
1816
1817         /* force refresh */
1818         /* just active area for now, since doing whole screen is too slow */
1819         ED_region_tag_redraw(p->ar);
1820 }
1821
1822 /* ------------------------------- */
1823
1824 /* operator 'redo' (i.e. after changing some properties, but also for repeat last) */
1825 static int gpencil_draw_exec(bContext *C, wmOperator *op)
1826 {
1827         tGPsdata *p = NULL;
1828         Depsgraph *depsgraph = CTX_data_depsgraph(C);
1829
1830         /* printf("GPencil - Starting Re-Drawing\n"); */
1831
1832         /* try to initialize context data needed while drawing */
1833         if (!gpencil_draw_init(C, op, NULL)) {
1834                 if (op->customdata) MEM_freeN(op->customdata);
1835                 /* printf("\tGP - no valid data\n"); */
1836                 return OPERATOR_CANCELLED;
1837         }
1838         else
1839                 p = op->customdata;
1840
1841         /* printf("\tGP - Start redrawing stroke\n"); */
1842
1843         /* loop over the stroke RNA elements recorded (i.e. progress of mouse movement),
1844          * setting the relevant values in context at each step, then applying
1845          */
1846         RNA_BEGIN (op->ptr, itemptr, "stroke")
1847         {
1848                 float mousef[2];
1849
1850                 /* printf("\t\tGP - stroke elem\n"); */
1851
1852                 /* get relevant data for this point from stroke */
1853                 RNA_float_get_array(&itemptr, "mouse", mousef);
1854                 p->mval[0] = (int)mousef[0];
1855                 p->mval[1] = (int)mousef[1];
1856                 p->pressure = RNA_float_get(&itemptr, "pressure");
1857                 p->curtime = (double)RNA_float_get(&itemptr, "time") + p->inittime;
1858
1859                 if (RNA_boolean_get(&itemptr, "is_start")) {
1860                         /* if first-run flag isn't set already (i.e. not true first stroke),
1861                          * then we must terminate the previous one first before continuing
1862                          */
1863                         if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) {
1864                                 /* TODO: both of these ops can set error-status, but we probably don't need to worry */
1865                                 gp_paint_strokeend(p);
1866                                 gp_paint_initstroke(p, p->paintmode, depsgraph);
1867                         }
1868                 }
1869
1870                 /* if first run, set previous data too */
1871                 if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
1872                         p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
1873
1874                         p->mvalo[0] = p->mval[0];
1875                         p->mvalo[1] = p->mval[1];
1876                         p->opressure = p->pressure;
1877                         p->ocurtime = p->curtime;
1878                 }
1879
1880                 /* apply this data as necessary now (as per usual) */
1881                 gpencil_draw_apply(op, p, depsgraph);
1882         }
1883         RNA_END;
1884
1885         /* printf("\tGP - done\n"); */
1886
1887         /* cleanup */
1888         gpencil_draw_exit(C, op);
1889
1890         /* refreshes */
1891         WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
1892
1893         /* done */
1894         return OPERATOR_FINISHED;
1895 }
1896
1897 /* ------------------------------- */
1898
1899 /* start of interactive drawing part of operator */
1900 static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1901 {
1902         Object *ob = CTX_data_active_object(C);
1903         ScrArea *sa = CTX_wm_area(C);
1904         Scene *scene = CTX_data_scene(C);
1905         tGPsdata *p = NULL;
1906
1907         /* support for tablets eraser pen */
1908         if (gpencil_is_tablet_eraser_active(event)) {
1909                 RNA_enum_set(op->ptr, "mode", GP_PAINTMODE_ERASER);
1910         }
1911
1912         /* if try to do annotations with a gp object selected, first
1913          * unselect the object to avoid conflicts.
1914          * The solution is not perfect but we can keep running the annotations while
1915          * found a better solution.
1916          */
1917         if (sa && sa->spacetype == SPACE_VIEW3D) {
1918                 if ((ob != NULL) && (ob->type == OB_GPENCIL)) {
1919                         ob->mode = OB_MODE_OBJECT;
1920                         bGPdata *gpd = (bGPdata *)ob->data;
1921                         ED_gpencil_setup_modes(C, gpd, 0);
1922                         DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
1923
1924                         ViewLayer *view_layer = CTX_data_view_layer(C);
1925                         BKE_view_layer_base_deselect_all(view_layer);
1926                         view_layer->basact = NULL;
1927                         DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
1928                         WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
1929                 }
1930         }
1931
1932         if (G.debug & G_DEBUG)
1933                 printf("GPencil - Starting Drawing\n");
1934
1935         /* try to initialize context data needed while drawing */
1936         if (!gpencil_draw_init(C, op, event)) {
1937                 if (op->customdata)
1938                         MEM_freeN(op->customdata);
1939                 if (G.debug & G_DEBUG)
1940                         printf("\tGP - no valid data\n");
1941                 return OPERATOR_CANCELLED;
1942         }
1943         else
1944                 p = op->customdata;
1945
1946         /* TODO: set any additional settings that we can take from the events?
1947          * TODO? if tablet is erasing, force eraser to be on? */
1948
1949         /* TODO: move cursor setting stuff to stroke-start so that paintmode can be changed midway... */
1950
1951         /* if eraser is on, draw radial aid */
1952         if (p->paintmode == GP_PAINTMODE_ERASER) {
1953                 gpencil_draw_toggle_eraser_cursor(C, p, true);
1954         }
1955         /* set cursor
1956          * NOTE: This may change later (i.e. intentionally via brush toggle,
1957          *       or unintentionally if the user scrolls outside the area)...
1958          */
1959         gpencil_draw_cursor_set(p);
1960
1961         /* only start drawing immediately if we're allowed to do so... */
1962         if (RNA_boolean_get(op->ptr, "wait_for_input") == false) {
1963                 /* hotkey invoked - start drawing */
1964                 /* printf("\tGP - set first spot\n"); */
1965                 p->status = GP_STATUS_PAINTING;
1966
1967                 /* handle the initial drawing - i.e. for just doing a simple dot */
1968                 gpencil_draw_apply_event(op, event, CTX_data_depsgraph(C));
1969                 op->flag |= OP_IS_MODAL_CURSOR_REGION;
1970         }
1971         else {
1972                 /* toolbar invoked - don't start drawing yet... */
1973                 /* printf("\tGP - hotkey invoked... waiting for click-drag\n"); */
1974                 op->flag |= OP_IS_MODAL_CURSOR_REGION;
1975         }
1976
1977         WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
1978         /* add a modal handler for this operator, so that we can then draw continuous strokes */
1979         WM_event_add_modal_handler(C, op);
1980         return OPERATOR_RUNNING_MODAL;
1981 }
1982
1983 /* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
1984 static bool gpencil_area_exists(bContext *C, ScrArea *sa_test)
1985 {
1986         bScreen *sc = CTX_wm_screen(C);
1987         return (BLI_findindex(&sc->areabase, sa_test) != -1);
1988 }
1989
1990 static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
1991 {
1992         tGPsdata *p = op->customdata;
1993
1994         /* we must check that we're still within the area that we're set up to work from
1995          * otherwise we could crash (see bug #20586)
1996          */
1997         if (CTX_wm_area(C) != p->sa) {
1998                 printf("\t\t\tGP - wrong area execution abort!\n");
1999                 p->status = GP_STATUS_ERROR;
2000         }
2001
2002         /* printf("\t\tGP - start stroke\n"); */
2003
2004         /* we may need to set up paint env again if we're resuming */
2005         /* XXX: watch it with the paintmode! in future,
2006          *      it'd be nice to allow changing paint-mode when in sketching-sessions */
2007
2008         if (gp_session_initdata(C, p))
2009                 gp_paint_initstroke(p, p->paintmode, CTX_data_depsgraph(C));
2010
2011         if (p->status != GP_STATUS_ERROR) {
2012                 p->status = GP_STATUS_PAINTING;
2013                 op->flag &= ~OP_IS_MODAL_CURSOR_REGION;
2014         }
2015
2016         return op->customdata;
2017 }
2018
2019 static void gpencil_stroke_end(wmOperator *op)
2020 {
2021         tGPsdata *p = op->customdata;
2022
2023         gp_paint_cleanup(p);
2024
2025         gpencil_undo_push(p->gpd);
2026
2027         gp_session_cleanup(p);
2028
2029         p->status = GP_STATUS_IDLING;
2030         op->flag |= OP_IS_MODAL_CURSOR_REGION;
2031
2032         p->gpd = NULL;
2033         p->gpl = NULL;
2034         p->gpf = NULL;
2035 }
2036
2037 /* events handling during interactive drawing part of operator */
2038 static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
2039 {
2040         tGPsdata *p = op->customdata;
2041         /* default exit state - pass through to support MMB view nav, etc. */
2042         int estate = OPERATOR_PASS_THROUGH;
2043
2044         /* if (event->type == NDOF_MOTION)
2045          *    return OPERATOR_PASS_THROUGH;
2046          * -------------------------------
2047          * [mce] Not quite what I was looking
2048          * for, but a good start! GP continues to
2049          * draw on the screen while the 3D mouse
2050          * moves the viewpoint. Problem is that
2051          * the stroke is converted to 3D only after
2052          * it is finished. This approach should work
2053          * better in tools that immediately apply
2054          * in 3D space.
2055          */
2056
2057         if (p->status == GP_STATUS_IDLING) {
2058                 ARegion *ar = CTX_wm_region(C);
2059                 p->ar = ar;
2060         }
2061
2062         /* we don't pass on key events, GP is used with key-modifiers - prevents Dkey to insert drivers */
2063         if (ISKEYBOARD(event->type)) {
2064                 if (ELEM(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY, ZKEY)) {
2065                         /* allow some keys:
2066                          *   - for frame changing [#33412]
2067                          *   - for undo (during sketching sessions)
2068                          */
2069                 }
2070                 else if (ELEM(event->type, PAD0, PAD1, PAD2, PAD3, PAD4, PAD5, PAD6, PAD7, PAD8, PAD9)) {
2071                         /* allow numpad keys so that camera/view manipulations can still take place
2072                          * - PAD0 in particular is really important for Grease Pencil drawing,
2073                          *   as animators may be working "to camera", so having this working
2074                          *   is essential for ensuring that they can quickly return to that view
2075                          */
2076                 }
2077                 else if ((event->type == BKEY) && (event->val == KM_RELEASE)) {
2078                         /* Add Blank Frame
2079                          * - Since this operator is non-modal, we can just call it here, and keep going...
2080                          * - This operator is especially useful when animating
2081                          */
2082                         WM_operator_name_call(C, "GPENCIL_OT_blank_frame_add", WM_OP_EXEC_DEFAULT, NULL);
2083                         estate = OPERATOR_RUNNING_MODAL;
2084                 }
2085                 else {
2086                         estate = OPERATOR_RUNNING_MODAL;
2087                 }
2088         }
2089
2090         //printf("\tGP - handle modal event...\n");
2091
2092         /* exit painting mode (and/or end current stroke)
2093          * NOTE: cannot do RIGHTMOUSE (as is standard for canceling) as that would break polyline [#32647]
2094          */
2095         if (ELEM(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY, EKEY)) {
2096                 /* exit() ends the current stroke before cleaning up */
2097                 /* printf("\t\tGP - end of paint op + end of stroke\n"); */
2098                 p->status = GP_STATUS_DONE;
2099                 estate = OPERATOR_FINISHED;
2100         }
2101
2102         /* toggle painting mode upon mouse-button movement
2103          *  - LEFTMOUSE  = standard drawing (all) / straight line drawing (all) / polyline (toolbox only)
2104          *  - RIGHTMOUSE = polyline (hotkey) / eraser (all)
2105          *    (Disabling RIGHTMOUSE case here results in bugs like [#32647])
2106          * also making sure we have a valid event value, to not exit too early
2107          */
2108         if (ELEM(event->type, LEFTMOUSE, RIGHTMOUSE) && (ELEM(event->val, KM_PRESS, KM_RELEASE))) {
2109                 /* if painting, end stroke */
2110                 if (p->status == GP_STATUS_PAINTING) {
2111                         int sketch = 0;
2112
2113                         /* basically, this should be mouse-button up = end stroke
2114                          * BUT, polyline drawing is an exception -- all knots should be added during one session
2115                          */
2116                         sketch |= (p->paintmode == GP_PAINTMODE_DRAW_POLY);
2117
2118                         if (sketch) {
2119                                 /* end stroke only, and then wait to resume painting soon */
2120                                 /* printf("\t\tGP - end stroke only\n"); */
2121                                 gpencil_stroke_end(op);
2122
2123                                 /* If eraser mode is on, turn it off after the stroke finishes
2124                                  * NOTE: This just makes it nicer to work with drawing sessions
2125                                  */
2126                                 if (p->paintmode == GP_PAINTMODE_ERASER) {
2127                                         p->paintmode = RNA_enum_get(op->ptr, "mode");
2128
2129                                         /* if the original mode was *still* eraser,
2130                                          * we'll let it say for now, since this gives
2131                                          * users an opportunity to have visual feedback
2132                                          * when adjusting eraser size
2133                                          */
2134                                         if (p->paintmode != GP_PAINTMODE_ERASER) {
2135                                                 /* turn off cursor...
2136                                                  * NOTE: this should be enough for now
2137                                                  *       Just hiding this makes it seem like
2138                                                  *       you can paint again...
2139                                                  */
2140                                                 gpencil_draw_toggle_eraser_cursor(C, p, false);
2141                                         }
2142                                 }
2143
2144                                 /* we've just entered idling state, so this event was processed (but no others yet) */
2145                                 estate = OPERATOR_RUNNING_MODAL;
2146
2147                                 /* stroke could be smoothed, send notifier to refresh screen */
2148                                 WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
2149                         }
2150                         else {
2151                                 /* printf("\t\tGP - end of stroke + op\n"); */
2152                                 p->status = GP_STATUS_DONE;
2153                                 estate = OPERATOR_FINISHED;
2154                         }
2155                 }
2156                 else if (event->val == KM_PRESS) {
2157                         bool in_bounds = false;
2158
2159                         /* Check if we're outside the bounds of the active region
2160                          * NOTE: An exception here is that if launched from the toolbar,
2161                          *       whatever region we're now in should become the new region
2162                          */
2163                         if ((p->ar) && (p->ar->regiontype == RGN_TYPE_TOOLS)) {
2164                                 /* Change to whatever region is now under the mouse */
2165                                 ARegion *current_region = BKE_area_find_region_xy(p->sa, RGN_TYPE_ANY, event->x, event->y);
2166
2167                                 if (G.debug & G_DEBUG) {
2168                                         printf("found alternative region %p (old was %p) - at %d %d (sa: %d %d -> %d %d)\n",
2169                                                 current_region, p->ar, event->x, event->y,
2170                                                 p->sa->totrct.xmin, p->sa->totrct.ymin, p->sa->totrct.xmax, p->sa->totrct.ymax);
2171                                 }
2172
2173                                 if (current_region) {
2174                                         /* Assume that since we found the cursor in here, it is in bounds
2175                                          * and that this should be the region that we begin drawing in
2176                                          */
2177                                         p->ar = current_region;
2178                                         in_bounds = true;
2179                                 }
2180                                 else {
2181                                         /* Out of bounds, or invalid in some other way */
2182                                         p->status = GP_STATUS_ERROR;
2183                                         estate = OPERATOR_CANCELLED;
2184
2185                                         if (G.debug & G_DEBUG)
2186                                                 printf("%s: Region under cursor is out of bounds, so cannot be drawn on\n", __func__);
2187                                 }
2188                         }
2189                         else if (p->ar) {
2190                                 rcti region_rect;
2191
2192                                 /* Perform bounds check using  */
2193                                 ED_region_visible_rect(p->ar, &region_rect);
2194                                 in_bounds = BLI_rcti_isect_pt_v(&region_rect, event->mval);
2195                         }
2196                         else {
2197                                 /* No region */
2198                                 p->status = GP_STATUS_ERROR;
2199                                 estate = OPERATOR_CANCELLED;
2200
2201                                 if (G.debug & G_DEBUG)
2202                                         printf("%s: No active region found in GP Paint session data\n", __func__);
2203                         }
2204
2205                         if (in_bounds) {
2206                                 /* Switch paintmode (temporarily if need be) based on which button was used
2207                                  * NOTE: This is to make it more convenient to erase strokes when using drawing sessions
2208                                  */
2209                                 if ((event->type == RIGHTMOUSE) || gpencil_is_tablet_eraser_active(event)) {
2210                                         /* turn on eraser */
2211                                         p->paintmode = GP_PAINTMODE_ERASER;
2212                                 }
2213                                 else if (event->type == LEFTMOUSE) {
2214                                         /* restore drawmode to default */
2215                                         p->paintmode = RNA_enum_get(op->ptr, "mode");
2216                                 }
2217
2218                                 gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER);
2219
2220                                 /* not painting, so start stroke (this should be mouse-button down) */
2221                                 p = gpencil_stroke_begin(C, op);
2222
2223                                 if (p->status == GP_STATUS_ERROR) {
2224                                         estate = OPERATOR_CANCELLED;
2225                                 }
2226                         }
2227                         else if (p->status != GP_STATUS_ERROR) {
2228                                 /* User clicked outside bounds of window while idling, so exit paintmode
2229                                  * NOTE: Don't enter this case if an error occurred while finding the
2230                                  *       region (as above)
2231                                  */
2232                                 p->status = GP_STATUS_DONE;
2233                                 estate = OPERATOR_FINISHED;
2234                         }
2235                 }
2236                 else if (event->val == KM_RELEASE) {
2237                         p->status = GP_STATUS_IDLING;
2238                         op->flag |= OP_IS_MODAL_CURSOR_REGION;
2239                 }
2240         }
2241
2242         /* handle mode-specific events */
2243         if (p->status == GP_STATUS_PAINTING) {
2244                 /* handle painting mouse-movements? */
2245                 if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) {
2246                         /* handle drawing event */
2247                         /* printf("\t\tGP - add point\n"); */
2248                         gpencil_draw_apply_event(op, event, CTX_data_depsgraph(C));
2249
2250                         /* finish painting operation if anything went wrong just now */
2251                         if (p->status == GP_STATUS_ERROR) {
2252                                 printf("\t\t\t\tGP - add error done!\n");
2253                                 estate = OPERATOR_CANCELLED;
2254                         }
2255                         else {
2256                                 /* event handled, so just tag as running modal */
2257                                 /* printf("\t\t\t\tGP - add point handled!\n"); */
2258                                 estate = OPERATOR_RUNNING_MODAL;
2259                         }
2260                 }
2261                 /* eraser size */
2262                 else if ((p->paintmode == GP_PAINTMODE_ERASER) &&
2263                          ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE, PADPLUSKEY, PADMINUS))
2264                 {
2265                         /* just resize the brush (local version)
2266                          * TODO: fix the hardcoded size jumps (set to make a visible difference) and hardcoded keys
2267                          */
2268                         /* printf("\t\tGP - resize eraser\n"); */
2269                         switch (event->type) {
2270                                 case WHEELDOWNMOUSE: /* larger */
2271                                 case PADPLUSKEY:
2272                                         p->radius += 5;
2273                                         break;
2274
2275                                 case WHEELUPMOUSE: /* smaller */
2276                                 case PADMINUS:
2277                                         p->radius -= 5;
2278
2279                                         if (p->radius <= 0)
2280                                                 p->radius = 1;
2281                                         break;
2282                         }
2283
2284                         /* force refresh */
2285                         /* just active area for now, since doing whole screen is too slow */
2286                         ED_region_tag_redraw(p->ar);
2287
2288                         /* event handled, so just tag as running modal */
2289                         estate = OPERATOR_RUNNING_MODAL;
2290                 }
2291                 /* there shouldn't be any other events, but just in case there are, let's swallow them
2292                  * (i.e. to prevent problems with undo)
2293                  */
2294                 else {
2295                         /* swallow event to save ourselves trouble */
2296                         estate = OPERATOR_RUNNING_MODAL;
2297                 }
2298         }
2299
2300         /* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */
2301         if (0 == gpencil_area_exists(C, p->sa))
2302                 estate = OPERATOR_CANCELLED;
2303         else {
2304                 /* update status indicators - cursor, header, etc. */
2305                 gpencil_draw_status_indicators(C, p);
2306                 /* cursor may have changed outside our control - T44084 */
2307                 gpencil_draw_cursor_set(p);
2308         }
2309
2310         /* process last operations before exiting */
2311         switch (estate) {
2312                 case OPERATOR_FINISHED:
2313                         /* one last flush before we're done */
2314                         gpencil_draw_exit(C, op);
2315                         WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
2316                         break;
2317
2318                 case OPERATOR_CANCELLED:
2319                         gpencil_draw_exit(C, op);
2320                         break;
2321
2322                 case OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH:
2323                         /* event doesn't need to be handled */
2324 #if 0
2325                         printf("unhandled event -> %d (mmb? = %d | mmv? = %d)\n",
2326                                event->type, event->type == MIDDLEMOUSE, event->type==MOUSEMOVE);
2327 #endif
2328                         break;
2329         }
2330
2331         /* return status code */
2332         return estate;
2333 }
2334
2335 /* ------------------------------- */
2336
2337 static const EnumPropertyItem prop_gpencil_drawmodes[] = {
2338         {GP_PAINTMODE_DRAW, "DRAW", 0, "Draw Freehand", "Draw freehand stroke(s)"},
2339         {GP_PAINTMODE_DRAW_STRAIGHT, "DRAW_STRAIGHT", 0, "Draw Straight Lines", "Draw straight line segment(s)"},
2340         {GP_PAINTMODE_DRAW_POLY, "DRAW_POLY", 0, "Draw Poly Line", "Click to place endpoints of straight line segments (connected)"},
2341         {GP_PAINTMODE_ERASER, "ERASER", 0, "Eraser", "Erase Annotation strokes"},
2342         {0, NULL, 0, NULL, NULL},
2343 };
2344
2345 void GPENCIL_OT_annotate(wmOperatorType *ot)
2346 {
2347         PropertyRNA *prop;
2348
2349         /* identifiers */
2350         ot->name = "Annotation Draw";
2351         ot->idname = "GPENCIL_OT_annotate";
2352         ot->description = "Make annotations on the active data";
2353
2354         /* api callbacks */
2355         ot->exec = gpencil_draw_exec;
2356         ot->invoke = gpencil_draw_invoke;
2357         ot->modal = gpencil_draw_modal;
2358         ot->cancel = gpencil_draw_cancel;
2359         ot->poll = gpencil_draw_poll;
2360
2361         /* flags */
2362         ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
2363
2364         /* settings for drawing */
2365         ot->prop = RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements");
2366
2367         prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
2368         RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
2369
2370         /* NOTE: wait for input is enabled by default,
2371          * so that all UI code can work properly without needing users to know about this */
2372         prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "Wait for first click instead of painting immediately");
2373         RNA_def_property_flag(prop, PROP_SKIP_SAVE);
2374 }