Cleanup: style, use braces for editors
[blender.git] / source / blender / editors / gpencil / gpencil_utils.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) 2014, Blender Foundation
17  */
18
19 /** \file
20  * \ingroup edgpencil
21  */
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <stddef.h>
27 #include <math.h>
28
29 #include "MEM_guardedalloc.h"
30
31 #include "BLI_math.h"
32 #include "BLI_blenlib.h"
33 #include "BLI_ghash.h"
34 #include "BLI_utildefines.h"
35 #include "BLT_translation.h"
36 #include "BLI_rand.h"
37
38 #include "DNA_meshdata_types.h"
39 #include "DNA_gpencil_types.h"
40 #include "DNA_brush_types.h"
41 #include "DNA_object_types.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_screen_types.h"
44 #include "DNA_space_types.h"
45 #include "DNA_view3d_types.h"
46
47 #include "BKE_action.h"
48 #include "BKE_colortools.h"
49 #include "BKE_deform.h"
50 #include "BKE_main.h"
51 #include "BKE_brush.h"
52 #include "BKE_context.h"
53 #include "BKE_gpencil.h"
54 #include "BKE_object.h"
55 #include "BKE_paint.h"
56 #include "BKE_material.h"
57 #include "BKE_tracking.h"
58
59 #include "WM_api.h"
60 #include "WM_toolsystem.h"
61
62 #include "RNA_access.h"
63 #include "RNA_define.h"
64 #include "RNA_enum_types.h"
65
66 #include "UI_resources.h"
67 #include "UI_view2d.h"
68
69 #include "ED_gpencil.h"
70 #include "ED_clip.h"
71 #include "ED_view3d.h"
72 #include "ED_object.h"
73 #include "ED_screen.h"
74 #include "ED_select_utils.h"
75
76 #include "GPU_immediate.h"
77 #include "GPU_immediate_util.h"
78 #include "GPU_state.h"
79
80 #include "DEG_depsgraph.h"
81 #include "DEG_depsgraph_query.h"
82
83 #include "gpencil_intern.h"
84
85 /* ******************************************************** */
86 /* Context Wrangling... */
87
88 /**
89  * Get pointer to active Grease Pencil datablock,
90  * and an RNA-pointer to trace back to whatever owns it,
91  * when context info is not available.
92  */
93 bGPdata **ED_gpencil_data_get_pointers_direct(
94     ID *screen_id, ScrArea *sa, Scene *scene, Object *ob, PointerRNA *r_ptr)
95 {
96   /* if there's an active area, check if the particular editor may
97    * have defined any special Grease Pencil context for editing...
98    */
99   if (sa) {
100     SpaceLink *sl = sa->spacedata.first;
101
102     switch (sa->spacetype) {
103       /* XXX: Should we reduce reliance on context.gpencil_data for these cases? */
104       case SPACE_PROPERTIES: /* properties */
105       case SPACE_INFO:       /* header info (needed after workspaces merge) */
106       {
107         if (ob && (ob->type == OB_GPENCIL)) {
108           /* GP Object */
109           if (r_ptr) {
110             RNA_id_pointer_create(&ob->id, r_ptr);
111           }
112           return (bGPdata **)&ob->data;
113         }
114         else {
115           return NULL;
116         }
117
118         break;
119       }
120
121       case SPACE_TOPBAR: /* Topbar (needed after topbar merge) */
122       case SPACE_VIEW3D: /* 3D-View */
123       {
124         if (ob && (ob->type == OB_GPENCIL)) {
125           /* GP Object */
126           if (r_ptr) {
127             RNA_id_pointer_create(&ob->id, r_ptr);
128           }
129           return (bGPdata **)&ob->data;
130         }
131         else {
132           /* Annotations */
133           /* XXX: */
134           if (r_ptr) {
135             RNA_id_pointer_create(&scene->id, r_ptr);
136           }
137           return &scene->gpd;
138         }
139
140         break;
141       }
142       case SPACE_NODE: /* Nodes Editor */
143       {
144         SpaceNode *snode = (SpaceNode *)sl;
145
146         /* return the GP data for the active node block/node */
147         if (snode && snode->nodetree) {
148           /* for now, as long as there's an active node tree,
149            * default to using that in the Nodes Editor */
150           if (r_ptr) {
151             RNA_id_pointer_create(&snode->nodetree->id, r_ptr);
152           }
153           return &snode->nodetree->gpd;
154         }
155
156         /* even when there is no node-tree, don't allow this to flow to scene */
157         return NULL;
158       }
159       case SPACE_SEQ: /* Sequencer */
160       {
161         SpaceSeq *sseq = (SpaceSeq *)sl;
162
163         /* For now, Grease Pencil data is associated with the space
164          * (actually preview region only). */
165         /* XXX our convention for everything else is to link to data though... */
166         if (r_ptr) {
167           RNA_pointer_create(screen_id, &RNA_SpaceSequenceEditor, sseq, r_ptr);
168         }
169         return &sseq->gpd;
170       }
171       case SPACE_IMAGE: /* Image/UV Editor */
172       {
173         SpaceImage *sima = (SpaceImage *)sl;
174
175         /* for now, Grease Pencil data is associated with the space... */
176         /* XXX our convention for everything else is to link to data though... */
177         if (r_ptr) {
178           RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, r_ptr);
179         }
180         return &sima->gpd;
181       }
182       case SPACE_CLIP: /* Nodes Editor */
183       {
184         SpaceClip *sc = (SpaceClip *)sl;
185         MovieClip *clip = ED_space_clip_get_clip(sc);
186
187         if (clip) {
188           if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) {
189             MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking);
190
191             if (!track) {
192               return NULL;
193             }
194
195             if (r_ptr) {
196               RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, r_ptr);
197             }
198             return &track->gpd;
199           }
200           else {
201             if (r_ptr) {
202               RNA_id_pointer_create(&clip->id, r_ptr);
203             }
204             return &clip->gpd;
205           }
206         }
207         break;
208       }
209       default: /* unsupported space */
210         return NULL;
211     }
212   }
213
214   return NULL;
215 }
216
217 /* Get pointer to active Grease Pencil datablock,
218  * and an RNA-pointer to trace back to whatever owns it. */
219 bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *r_ptr)
220 {
221   ID *screen_id = (ID *)CTX_wm_screen(C);
222   Scene *scene = CTX_data_scene(C);
223   ScrArea *sa = CTX_wm_area(C);
224   Object *ob = CTX_data_active_object(C);
225
226   return ED_gpencil_data_get_pointers_direct(screen_id, sa, scene, ob, r_ptr);
227 }
228
229 /* -------------------------------------------------------- */
230
231 /* Get the active Grease Pencil datablock, when context is not available */
232 bGPdata *ED_gpencil_data_get_active_direct(ID *screen_id, ScrArea *sa, Scene *scene, Object *ob)
233 {
234   bGPdata **gpd_ptr = ED_gpencil_data_get_pointers_direct(screen_id, sa, scene, ob, NULL);
235   return (gpd_ptr) ? *(gpd_ptr) : NULL;
236 }
237
238 /**
239  * Get the active Grease Pencil datablock
240  * \note This is the original (bmain) copy of the datablock, stored in files.
241  * Do not use for reading evaluated copies of GP Objects data
242  */
243 bGPdata *ED_gpencil_data_get_active(const bContext *C)
244 {
245   bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
246   return (gpd_ptr) ? *(gpd_ptr) : NULL;
247 }
248
249 /**
250  * Get the evaluated copy of the active Grease Pencil datablock (where applicable)
251  * - For the 3D View (i.e. "GP Objects"), this gives the evaluated copy of the GP datablock
252  *   (i.e. a copy of the active GP datablock for the active object, where modifiers have been
253  *   applied). This is needed to correctly work with "Copy-on-Write".
254  * - For all other editors (i.e. "GP Annotations"), this just gives the active datablock
255  *   like for #ED_gpencil_data_get_active()
256  */
257 bGPdata *ED_gpencil_data_get_active_evaluated(const bContext *C)
258 {
259   ID *screen_id = (ID *)CTX_wm_screen(C);
260   ScrArea *sa = CTX_wm_area(C);
261
262   const Depsgraph *depsgraph = CTX_data_depsgraph(C);
263   Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
264   Object *ob = CTX_data_active_object(C);
265   Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
266
267 #if 0
268   if (ob && ob->type == OB_GPENCIL) {
269     BLI_assert(ob_eval->data == DEG_get_evaluated_id(ob->data));
270   }
271 #endif
272   return ED_gpencil_data_get_active_direct(screen_id, sa, scene_eval, ob_eval);
273 }
274
275 /* -------------------------------------------------------- */
276
277 /**
278  * Utility to check whether the r_ptr output of ED_gpencil_data_get_pointers()
279  * is for annotation usage.
280  */
281 bool ED_gpencil_data_owner_is_annotation(PointerRNA *owner_ptr)
282 {
283   /* Key Assumption: If the pointer is an object, we're dealing with a GP Object's data.
284    * Otherwise, the GP datablock is being used for annotations (i.e. everywhere else)
285    */
286   return ((owner_ptr) && (owner_ptr->type != &RNA_Object));
287 }
288
289 /* ******************************************************** */
290 /* Keyframe Indicator Checks */
291
292 /* Check whether there's an active GP keyframe on the current frame */
293 bool ED_gpencil_has_keyframe_v3d(Scene *UNUSED(scene), Object *ob, int cfra)
294 {
295   if (ob && ob->data && (ob->type == OB_GPENCIL)) {
296     bGPDlayer *gpl = BKE_gpencil_layer_getactive(ob->data);
297     if (gpl) {
298       if (gpl->actframe) {
299         // XXX: assumes that frame has been fetched already
300         return (gpl->actframe->framenum == cfra);
301       }
302       else {
303         /* XXX: disabled as could be too much of a penalty */
304         /* return BKE_gpencil_layer_find_frame(gpl, cfra); */
305       }
306     }
307   }
308
309   return false;
310 }
311
312 /* ******************************************************** */
313 /* Poll Callbacks */
314
315 /* poll callback for adding data/layers - special */
316 bool gp_add_poll(bContext *C)
317 {
318   /* the base line we have is that we have somewhere to add Grease Pencil data */
319   return ED_gpencil_data_get_pointers(C, NULL) != NULL;
320 }
321
322 /* poll callback for checking if there is an active layer */
323 bool gp_active_layer_poll(bContext *C)
324 {
325   bGPdata *gpd = ED_gpencil_data_get_active(C);
326   bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
327
328   return (gpl != NULL);
329 }
330
331 /* poll callback for checking if there is an active brush */
332 bool gp_active_brush_poll(bContext *C)
333 {
334   ToolSettings *ts = CTX_data_tool_settings(C);
335   Paint *paint = &ts->gp_paint->paint;
336   if (paint) {
337     return (paint->brush != NULL);
338   }
339   else {
340     return false;
341   }
342 }
343
344 /* ******************************************************** */
345 /* Dynamic Enums of GP Layers */
346 /* NOTE: These include an option to create a new layer and use that... */
347
348 /* Just existing layers */
349 const EnumPropertyItem *ED_gpencil_layers_enum_itemf(bContext *C,
350                                                      PointerRNA *UNUSED(ptr),
351                                                      PropertyRNA *UNUSED(prop),
352                                                      bool *r_free)
353 {
354   bGPdata *gpd = CTX_data_gpencil_data(C);
355   bGPDlayer *gpl;
356   EnumPropertyItem *item = NULL, item_tmp = {0};
357   int totitem = 0;
358   int i = 0;
359
360   if (ELEM(NULL, C, gpd)) {
361     return DummyRNA_DEFAULT_items;
362   }
363
364   /* Existing layers */
365   for (gpl = gpd->layers.first; gpl; gpl = gpl->next, i++) {
366     item_tmp.identifier = gpl->info;
367     item_tmp.name = gpl->info;
368     item_tmp.value = i;
369
370     if (gpl->flag & GP_LAYER_ACTIVE) {
371       item_tmp.icon = ICON_GREASEPENCIL;
372     }
373     else {
374       item_tmp.icon = ICON_NONE;
375     }
376
377     RNA_enum_item_add(&item, &totitem, &item_tmp);
378   }
379
380   RNA_enum_item_end(&item, &totitem);
381   *r_free = true;
382
383   return item;
384 }
385
386 /* Existing + Option to add/use new layer */
387 const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C,
388                                                               PointerRNA *UNUSED(ptr),
389                                                               PropertyRNA *UNUSED(prop),
390                                                               bool *r_free)
391 {
392   bGPdata *gpd = CTX_data_gpencil_data(C);
393   bGPDlayer *gpl;
394   EnumPropertyItem *item = NULL, item_tmp = {0};
395   int totitem = 0;
396   int i = 0;
397
398   if (ELEM(NULL, C, gpd)) {
399     return DummyRNA_DEFAULT_items;
400   }
401
402   /* Create new layer */
403   /* TODO: have some way of specifying that we don't want this? */
404   {
405     /* "New Layer" entry */
406     item_tmp.identifier = "__CREATE__";
407     item_tmp.name = "New Layer";
408     item_tmp.value = -1;
409     item_tmp.icon = ICON_ADD;
410     RNA_enum_item_add(&item, &totitem, &item_tmp);
411
412     /* separator */
413     RNA_enum_item_add_separator(&item, &totitem);
414   }
415   const int tot = BLI_listbase_count(&gpd->layers);
416   /* Existing layers */
417   for (gpl = gpd->layers.last, i = 0; gpl; gpl = gpl->prev, i++) {
418     item_tmp.identifier = gpl->info;
419     item_tmp.name = gpl->info;
420     item_tmp.value = tot - i - 1;
421
422     if (gpl->flag & GP_LAYER_ACTIVE) {
423       item_tmp.icon = ICON_GREASEPENCIL;
424     }
425     else {
426       item_tmp.icon = ICON_NONE;
427     }
428
429     RNA_enum_item_add(&item, &totitem, &item_tmp);
430   }
431
432   RNA_enum_item_end(&item, &totitem);
433   *r_free = true;
434
435   return item;
436 }
437
438 /* ******************************************************** */
439 /* Brush Tool Core */
440
441 /**
442  * Check whether a given stroke segment is inside a circular brush
443  *
444  * \param mval: The current screen-space coordinates (midpoint) of the brush
445  * \param mvalo: The previous screen-space coordinates (midpoint) of the brush (NOT CURRENTLY USED)
446  * \param rad: The radius of the brush
447  *
448  * \param x0, y0: The screen-space x and y coordinates of the start of the stroke segment
449  * \param x1, y1: The screen-space x and y coordinates of the end of the stroke segment
450  */
451 bool gp_stroke_inside_circle(
452     const float mval[2], const float UNUSED(mvalo[2]), int rad, int x0, int y0, int x1, int y1)
453 {
454   /* simple within-radius check for now */
455   const float screen_co_a[2] = {x0, y0};
456   const float screen_co_b[2] = {x1, y1};
457
458   if (edge_inside_circle(mval, rad, screen_co_a, screen_co_b)) {
459     return true;
460   }
461
462   /* not inside */
463   return false;
464 }
465
466 /* ******************************************************** */
467 /* Stroke Validity Testing */
468
469 /* Check whether given stroke can be edited given the supplied context */
470 /* TODO: do we need additional flags for screenspace vs dataspace? */
471 bool ED_gpencil_stroke_can_use_direct(const ScrArea *sa, const bGPDstroke *gps)
472 {
473   /* sanity check */
474   if (ELEM(NULL, sa, gps)) {
475     return false;
476   }
477
478   /* filter stroke types by flags + spacetype */
479   if (gps->flag & GP_STROKE_3DSPACE) {
480     /* 3D strokes - only in 3D view */
481     return ((sa->spacetype == SPACE_VIEW3D) || (sa->spacetype == SPACE_PROPERTIES));
482   }
483   else if (gps->flag & GP_STROKE_2DIMAGE) {
484     /* Special "image" strokes - only in Image Editor */
485     return (sa->spacetype == SPACE_IMAGE);
486   }
487   else if (gps->flag & GP_STROKE_2DSPACE) {
488     /* 2D strokes (dataspace) - for any 2D view (i.e. everything other than 3D view) */
489     return (sa->spacetype != SPACE_VIEW3D);
490   }
491   else {
492     /* view aligned - anything goes */
493     return true;
494   }
495 }
496
497 /* Check whether given stroke can be edited in the current context */
498 bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps)
499 {
500   ScrArea *sa = CTX_wm_area(C);
501   return ED_gpencil_stroke_can_use_direct(sa, gps);
502 }
503
504 /* Check whether given stroke can be edited for the current color */
505 bool ED_gpencil_stroke_color_use(Object *ob, const bGPDlayer *gpl, const bGPDstroke *gps)
506 {
507   /* check if the color is editable */
508   MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
509
510   if (gp_style != NULL) {
511     if (gp_style->flag & GP_STYLE_COLOR_HIDE) {
512       return false;
513     }
514     if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) && (gp_style->flag & GP_STYLE_COLOR_LOCKED)) {
515       return false;
516     }
517   }
518
519   return true;
520 }
521
522 /* ******************************************************** */
523 /* Space Conversion */
524
525 /**
526  * Init settings for stroke point space conversions
527  *
528  * \param r_gsc: [out] The space conversion settings struct, populated with necessary params
529  */
530 void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc)
531 {
532   ScrArea *sa = CTX_wm_area(C);
533   ARegion *ar = CTX_wm_region(C);
534
535   /* zero out the storage (just in case) */
536   memset(r_gsc, 0, sizeof(GP_SpaceConversion));
537   unit_m4(r_gsc->mat);
538
539   /* store settings */
540   r_gsc->scene = CTX_data_scene(C);
541   r_gsc->ob = CTX_data_active_object(C);
542
543   r_gsc->sa = sa;
544   r_gsc->ar = ar;
545   r_gsc->v2d = &ar->v2d;
546
547   /* init region-specific stuff */
548   if (sa->spacetype == SPACE_VIEW3D) {
549     wmWindow *win = CTX_wm_window(C);
550     Scene *scene = CTX_data_scene(C);
551     struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
552     View3D *v3d = (View3D *)CTX_wm_space_data(C);
553     RegionView3D *rv3d = ar->regiondata;
554
555     /* init 3d depth buffers */
556     view3d_operator_needs_opengl(C);
557
558     view3d_region_operator_needs_opengl(win, ar);
559     ED_view3d_autodist_init(depsgraph, ar, v3d, 0);
560
561     /* for camera view set the subrect */
562     if (rv3d->persp == RV3D_CAMOB) {
563       ED_view3d_calc_camera_border(
564           scene, CTX_data_depsgraph(C), ar, v3d, rv3d, &r_gsc->subrect_data, true);
565       r_gsc->subrect = &r_gsc->subrect_data;
566     }
567   }
568 }
569
570 /**
571  * Convert point to parent space
572  *
573  * \param pt: Original point
574  * \param diff_mat: Matrix with the difference between original parent matrix
575  * \param[out] r_pt: Pointer to new point after apply matrix
576  */
577 void gp_point_to_parent_space(const bGPDspoint *pt, const float diff_mat[4][4], bGPDspoint *r_pt)
578 {
579   float fpt[3];
580
581   mul_v3_m4v3(fpt, diff_mat, &pt->x);
582   copy_v3_v3(&r_pt->x, fpt);
583 }
584
585 /**
586  * Change position relative to parent object
587  */
588 void gp_apply_parent(
589     Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps)
590 {
591   bGPDspoint *pt;
592   int i;
593
594   /* undo matrix */
595   float diff_mat[4][4];
596   float inverse_diff_mat[4][4];
597   float fpt[3];
598
599   ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
600   invert_m4_m4(inverse_diff_mat, diff_mat);
601
602   for (i = 0; i < gps->totpoints; i++) {
603     pt = &gps->points[i];
604     mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x);
605     copy_v3_v3(&pt->x, fpt);
606   }
607 }
608
609 /**
610  * Change point position relative to parent object
611  */
612 void gp_apply_parent_point(
613     Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDspoint *pt)
614 {
615   /* undo matrix */
616   float diff_mat[4][4];
617   float inverse_diff_mat[4][4];
618   float fpt[3];
619
620   ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
621   invert_m4_m4(inverse_diff_mat, diff_mat);
622
623   mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x);
624   copy_v3_v3(&pt->x, fpt);
625 }
626
627 /**
628  * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D)
629  *
630  * \param[out] r_x  The screen-space x-coordinate of the point
631  * \param[out] r_y  The screen-space y-coordinate of the point
632  *
633  * \warning This assumes that the caller has already checked
634  * whether the stroke in question can be drawn.
635  */
636 void gp_point_to_xy(
637     const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt, int *r_x, int *r_y)
638 {
639   const ARegion *ar = gsc->ar;
640   const View2D *v2d = gsc->v2d;
641   const rctf *subrect = gsc->subrect;
642   int xyval[2];
643
644   /* sanity checks */
645   BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D));
646   BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D));
647
648   if (gps->flag & GP_STROKE_3DSPACE) {
649     if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
650       *r_x = xyval[0];
651       *r_y = xyval[1];
652     }
653     else {
654       *r_x = V2D_IS_CLIPPED;
655       *r_y = V2D_IS_CLIPPED;
656     }
657   }
658   else if (gps->flag & GP_STROKE_2DSPACE) {
659     float vec[3] = {pt->x, pt->y, 0.0f};
660     mul_m4_v3(gsc->mat, vec);
661     UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], r_x, r_y);
662   }
663   else {
664     if (subrect == NULL) {
665       /* normal 3D view (or view space) */
666       *r_x = (int)(pt->x / 100 * ar->winx);
667       *r_y = (int)(pt->y / 100 * ar->winy);
668     }
669     else {
670       /* camera view, use subrect */
671       *r_x = (int)((pt->x / 100) * BLI_rctf_size_x(subrect)) + subrect->xmin;
672       *r_y = (int)((pt->y / 100) * BLI_rctf_size_y(subrect)) + subrect->ymin;
673     }
674   }
675 }
676
677 /**
678  * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D).
679  *
680  * Just like #gp_point_to_xy(), except the resulting coordinates are floats not ints.
681  * Use this version to solve "stair-step" artifacts which may arise when
682  * roundtripping the calculations.
683  *
684  * \param r_x[out]: The screen-space x-coordinate of the point.
685  * \param r_y[out]: The screen-space y-coordinate of the point.
686  *
687  * \warning This assumes that the caller has already checked
688  * whether the stroke in question can be drawn.
689  */
690 void gp_point_to_xy_fl(const GP_SpaceConversion *gsc,
691                        const bGPDstroke *gps,
692                        const bGPDspoint *pt,
693                        float *r_x,
694                        float *r_y)
695 {
696   const ARegion *ar = gsc->ar;
697   const View2D *v2d = gsc->v2d;
698   const rctf *subrect = gsc->subrect;
699   float xyval[2];
700
701   /* sanity checks */
702   BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D));
703   BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D));
704
705   if (gps->flag & GP_STROKE_3DSPACE) {
706     if (ED_view3d_project_float_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
707       *r_x = xyval[0];
708       *r_y = xyval[1];
709     }
710     else {
711       *r_x = 0.0f;
712       *r_y = 0.0f;
713     }
714   }
715   else if (gps->flag & GP_STROKE_2DSPACE) {
716     float vec[3] = {pt->x, pt->y, 0.0f};
717     int t_x, t_y;
718
719     mul_m4_v3(gsc->mat, vec);
720     UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y);
721
722     if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) {
723       /* XXX: Or should we just always use the values as-is? */
724       *r_x = 0.0f;
725       *r_y = 0.0f;
726     }
727     else {
728       *r_x = (float)t_x;
729       *r_y = (float)t_y;
730     }
731   }
732   else {
733     if (subrect == NULL) {
734       /* normal 3D view (or view space) */
735       *r_x = (pt->x / 100.0f * ar->winx);
736       *r_y = (pt->y / 100.0f * ar->winy);
737     }
738     else {
739       /* camera view, use subrect */
740       *r_x = ((pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
741       *r_y = ((pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
742     }
743   }
744 }
745
746 /**
747  * generic based on gp_point_to_xy_fl
748  */
749 void gp_point_3d_to_xy(const GP_SpaceConversion *gsc,
750                        const short flag,
751                        const float pt[3],
752                        float xy[2])
753 {
754   const ARegion *ar = gsc->ar;
755   const View2D *v2d = gsc->v2d;
756   const rctf *subrect = gsc->subrect;
757   float xyval[2];
758
759   /* sanity checks */
760   BLI_assert((gsc->sa->spacetype == SPACE_VIEW3D));
761
762   if (flag & GP_STROKE_3DSPACE) {
763     if (ED_view3d_project_float_global(ar, pt, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
764       xy[0] = xyval[0];
765       xy[1] = xyval[1];
766     }
767     else {
768       xy[0] = 0.0f;
769       xy[1] = 0.0f;
770     }
771   }
772   else if (flag & GP_STROKE_2DSPACE) {
773     float vec[3] = {pt[0], pt[1], 0.0f};
774     int t_x, t_y;
775
776     mul_m4_v3(gsc->mat, vec);
777     UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y);
778
779     if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) {
780       /* XXX: Or should we just always use the values as-is? */
781       xy[0] = 0.0f;
782       xy[1] = 0.0f;
783     }
784     else {
785       xy[0] = (float)t_x;
786       xy[1] = (float)t_y;
787     }
788   }
789   else {
790     if (subrect == NULL) {
791       /* normal 3D view (or view space) */
792       xy[0] = (pt[0] / 100.0f * ar->winx);
793       xy[1] = (pt[1] / 100.0f * ar->winy);
794     }
795     else {
796       /* camera view, use subrect */
797       xy[0] = ((pt[0] / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
798       xy[1] = ((pt[1] / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
799     }
800   }
801 }
802
803 /**
804  * Project screenspace coordinates to 3D-space
805  *
806  * For use with editing tools where it is easier to perform the operations in 2D,
807  * and then later convert the transformed points back to 3D.
808  *
809  * \param screen_co: The screenspace 2D coordinates to convert to
810  * \param r_out: The resulting 3D coordinates of the input point
811  *
812  * \note We include this as a utility function, since the standard method
813  * involves quite a few steps, which are invariably always the same
814  * for all GPencil operations. So, it's nicer to just centralize these.
815  *
816  * \warning Assumes that it is getting called in a 3D view only.
817  */
818 bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc,
819                        Scene *scene,
820                        const float screen_co[2],
821                        float r_out[3])
822 {
823   const RegionView3D *rv3d = gsc->ar->regiondata;
824   float rvec[3];
825
826   ED_gp_get_drawing_reference(
827       scene, gsc->ob, gsc->gpl, scene->toolsettings->gpencil_v3d_align, rvec);
828
829   float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
830
831   float mval_f[2], mval_prj[2];
832   float dvec[3];
833
834   copy_v2_v2(mval_f, screen_co);
835
836   if (ED_view3d_project_float_global(gsc->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
837       V3D_PROJ_RET_OK) {
838     sub_v2_v2v2(mval_f, mval_prj, mval_f);
839     ED_view3d_win_to_delta(gsc->ar, mval_f, dvec, zfac);
840     sub_v3_v3v3(r_out, rvec, dvec);
841
842     return true;
843   }
844   else {
845     zero_v3(r_out);
846
847     return false;
848   }
849 }
850
851 /**
852  * Convert tGPspoint (temporary 2D/screenspace point data used by GP modal operators)
853  * to 3D coordinates.
854  *
855  * \param point2D: The screenspace 2D point data to convert.
856  * \param depth: Depth array (via #ED_view3d_autodist_depth()).
857  * \param[out] r_out: The resulting 2D point data.
858  */
859 void gp_stroke_convertcoords_tpoint(Scene *scene,
860                                     ARegion *ar,
861                                     Object *ob,
862                                     bGPDlayer *gpl,
863                                     const tGPspoint *point2D,
864                                     float *depth,
865                                     float r_out[3])
866 {
867   ToolSettings *ts = scene->toolsettings;
868
869   int mval_i[2];
870   round_v2i_v2fl(mval_i, &point2D->x);
871
872   if ((depth != NULL) && (ED_view3d_autodist_simple(ar, mval_i, r_out, 0, depth))) {
873     /* projecting onto 3D-Geometry
874      * - nothing more needs to be done here, since view_autodist_simple() has already done it
875      */
876   }
877   else {
878     float mval_f[2] = {point2D->x, point2D->y};
879     float mval_prj[2];
880     float rvec[3], dvec[3];
881     float zfac;
882
883     /* Current method just converts each point in screen-coordinates to
884      * 3D-coordinates using the 3D-cursor as reference.
885      */
886     ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, rvec);
887     zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL);
888
889     if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
890       sub_v2_v2v2(mval_f, mval_prj, mval_f);
891       ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
892       sub_v3_v3v3(r_out, rvec, dvec);
893     }
894     else {
895       zero_v3(r_out);
896     }
897   }
898 }
899
900 /**
901  * Get drawing reference point for conversion or projection of the stroke
902  * \param[out] r_vec : Reference point found
903  */
904 void ED_gp_get_drawing_reference(
905     const Scene *scene, const Object *ob, bGPDlayer *UNUSED(gpl), char align_flag, float r_vec[3])
906 {
907   const float *fp = scene->cursor.location;
908
909   /* if using a gpencil object at cursor mode, can use the location of the object */
910   if (align_flag & GP_PROJECT_VIEWSPACE) {
911     if (ob && (ob->type == OB_GPENCIL)) {
912       /* fallback (no strokes) - use cursor or object location */
913       if (align_flag & GP_PROJECT_CURSOR) {
914         /* use 3D-cursor */
915         copy_v3_v3(r_vec, fp);
916       }
917       else {
918         /* use object location */
919         copy_v3_v3(r_vec, ob->obmat[3]);
920       }
921     }
922   }
923   else {
924     /* use 3D-cursor */
925     copy_v3_v3(r_vec, fp);
926   }
927 }
928
929 void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke *gps)
930 {
931   Scene *scene = CTX_data_scene(C);
932   Depsgraph *depsgraph = CTX_data_depsgraph(C);
933   Object *ob = CTX_data_active_object(C);
934   bGPdata *gpd = (bGPdata *)ob->data;
935   GP_SpaceConversion gsc = {NULL};
936
937   bGPDspoint *pt;
938   int i;
939   float diff_mat[4][4];
940   float inverse_diff_mat[4][4];
941
942   /* init space conversion stuff */
943   gp_point_conversion_init(C, &gsc);
944
945   ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat);
946   invert_m4_m4(inverse_diff_mat, diff_mat);
947
948   /* Adjust each point */
949   for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
950     float xy[2];
951
952     bGPDspoint pt2;
953     gp_point_to_parent_space(pt, diff_mat, &pt2);
954     gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]);
955
956     /* Planar - All on same plane parallel to the viewplane */
957     gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
958
959     /* Unapply parent corrections */
960     mul_m4_v3(inverse_diff_mat, &pt->x);
961   }
962 }
963
964 /**
965  * Reproject all points of the stroke to a plane locked to axis to avoid stroke offset
966  */
967 void ED_gp_project_stroke_to_plane(const Scene *scene,
968                                    const Object *ob,
969                                    const RegionView3D *rv3d,
970                                    bGPDstroke *gps,
971                                    const float origin[3],
972                                    const int axis)
973 {
974   const ToolSettings *ts = scene->toolsettings;
975   const View3DCursor *cursor = &scene->cursor;
976   float plane_normal[3];
977   float vn[3];
978
979   float ray[3];
980   float rpoint[3];
981
982   /* normal vector for a plane locked to axis */
983   zero_v3(plane_normal);
984   if (axis < 0) {
985     /* if the axis is not locked, need a vector to the view direction
986      * in order to get the right size of the stroke.
987      */
988     ED_view3d_global_to_vector(rv3d, origin, plane_normal);
989   }
990   else if (axis < 3) {
991     plane_normal[axis] = 1.0f;
992     /* if object, apply object rotation */
993     if (ob && (ob->type == OB_GPENCIL)) {
994       float mat[4][4];
995       copy_m4_m4(mat, ob->obmat);
996
997       /* move origin to cursor */
998       if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
999         copy_v3_v3(mat[3], cursor->location);
1000       }
1001
1002       mul_mat3_m4_v3(mat, plane_normal);
1003     }
1004   }
1005   else {
1006     float scale[3] = {1.0f, 1.0f, 1.0f};
1007     plane_normal[2] = 1.0f;
1008     float mat[4][4];
1009     loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, scale);
1010
1011     /* move origin to object */
1012     if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
1013       copy_v3_v3(mat[3], ob->obmat[3]);
1014     }
1015
1016     mul_mat3_m4_v3(mat, plane_normal);
1017   }
1018
1019   /* Reproject the points in the plane */
1020   for (int i = 0; i < gps->totpoints; i++) {
1021     bGPDspoint *pt = &gps->points[i];
1022
1023     /* get a vector from the point with the current view direction of the viewport */
1024     ED_view3d_global_to_vector(rv3d, &pt->x, vn);
1025
1026     /* calculate line extreme point to create a ray that cross the plane */
1027     mul_v3_fl(vn, -50.0f);
1028     add_v3_v3v3(ray, &pt->x, vn);
1029
1030     /* if the line never intersect, the point is not changed */
1031     if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
1032       copy_v3_v3(&pt->x, rpoint);
1033     }
1034   }
1035 }
1036
1037 /**
1038  * Reproject given point to a plane locked to axis to avoid stroke offset
1039  * \param[in,out] pt: Point to affect
1040  */
1041 void ED_gp_project_point_to_plane(const Scene *scene,
1042                                   const Object *ob,
1043                                   const RegionView3D *rv3d,
1044                                   const float origin[3],
1045                                   const int axis,
1046                                   bGPDspoint *pt)
1047 {
1048   const ToolSettings *ts = scene->toolsettings;
1049   const View3DCursor *cursor = &scene->cursor;
1050   float plane_normal[3];
1051   float vn[3];
1052
1053   float ray[3];
1054   float rpoint[3];
1055
1056   /* normal vector for a plane locked to axis */
1057   zero_v3(plane_normal);
1058   if (axis < 0) {
1059     /* if the axis is not locked, need a vector to the view direction
1060      * in order to get the right size of the stroke.
1061      */
1062     ED_view3d_global_to_vector(rv3d, origin, plane_normal);
1063   }
1064   else if (axis < 3) {
1065     plane_normal[axis] = 1.0f;
1066     /* if object, apply object rotation */
1067     if (ob && (ob->type == OB_GPENCIL)) {
1068       float mat[4][4];
1069       copy_m4_m4(mat, ob->obmat);
1070
1071       /* move origin to cursor */
1072       if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
1073         copy_v3_v3(mat[3], cursor->location);
1074       }
1075
1076       mul_mat3_m4_v3(mat, plane_normal);
1077     }
1078   }
1079   else {
1080     float scale[3] = {1.0f, 1.0f, 1.0f};
1081     plane_normal[2] = 1.0f;
1082     float mat[4][4];
1083     loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, scale);
1084
1085     /* move origin to object */
1086     if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
1087       copy_v3_v3(mat[3], ob->obmat[3]);
1088     }
1089
1090     mul_mat3_m4_v3(mat, plane_normal);
1091   }
1092
1093   /* Reproject the points in the plane */
1094   /* get a vector from the point with the current view direction of the viewport */
1095   ED_view3d_global_to_vector(rv3d, &pt->x, vn);
1096
1097   /* calculate line extrem point to create a ray that cross the plane */
1098   mul_v3_fl(vn, -50.0f);
1099   add_v3_v3v3(ray, &pt->x, vn);
1100
1101   /* if the line never intersect, the point is not changed */
1102   if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
1103     copy_v3_v3(&pt->x, rpoint);
1104   }
1105 }
1106
1107 /* ******************************************************** */
1108 /* Stroke Operations */
1109
1110 /* XXX: Check if these functions duplicate stuff in blenkernel,
1111  * and/or whether we should just deduplicate. */
1112
1113 /**
1114  * Subdivide a stroke once, by adding a point half way between each pair of existing points
1115  * \param gps: Stroke data
1116  * \param subdivide: Number of times to subdivide
1117  */
1118 void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide)
1119 {
1120   bGPDspoint *temp_points;
1121   int totnewpoints, oldtotpoints;
1122   int i2;
1123
1124   /* loop as many times as levels */
1125   for (int s = 0; s < subdivide; s++) {
1126     totnewpoints = gps->totpoints - 1;
1127     /* duplicate points in a temp area */
1128     temp_points = MEM_dupallocN(gps->points);
1129     oldtotpoints = gps->totpoints;
1130
1131     /* resize the points arrays */
1132     gps->totpoints += totnewpoints;
1133     gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
1134     if (gps->dvert != NULL) {
1135       gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
1136     }
1137     gps->flag |= GP_STROKE_RECALC_GEOMETRY;
1138
1139     /* move points from last to first to new place */
1140     i2 = gps->totpoints - 1;
1141     for (int i = oldtotpoints - 1; i > 0; i--) {
1142       bGPDspoint *pt = &temp_points[i];
1143       bGPDspoint *pt_final = &gps->points[i2];
1144
1145       copy_v3_v3(&pt_final->x, &pt->x);
1146       pt_final->pressure = pt->pressure;
1147       pt_final->strength = pt->strength;
1148       pt_final->time = pt->time;
1149       pt_final->flag = pt->flag;
1150       pt_final->uv_fac = pt->uv_fac;
1151       pt_final->uv_rot = pt->uv_rot;
1152
1153       if (gps->dvert != NULL) {
1154         MDeformVert *dvert = &gps->dvert[i];
1155         MDeformVert *dvert_final = &gps->dvert[i2];
1156
1157         dvert_final->totweight = dvert->totweight;
1158         dvert_final->dw = dvert->dw;
1159       }
1160
1161       i2 -= 2;
1162     }
1163     /* interpolate mid points */
1164     i2 = 1;
1165     for (int i = 0; i < oldtotpoints - 1; i++) {
1166       bGPDspoint *pt = &temp_points[i];
1167       bGPDspoint *next = &temp_points[i + 1];
1168       bGPDspoint *pt_final = &gps->points[i2];
1169
1170       /* add a half way point */
1171       interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
1172       pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f);
1173       pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
1174       CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
1175       pt_final->time = interpf(pt->time, next->time, 0.5f);
1176       pt_final->uv_fac = interpf(pt->uv_fac, next->uv_fac, 0.5f);
1177       pt_final->uv_rot = interpf(pt->uv_rot, next->uv_rot, 0.5f);
1178
1179       if (gps->dvert != NULL) {
1180         MDeformVert *dvert_final = &gps->dvert[i2];
1181         dvert_final->totweight = 0;
1182         dvert_final->dw = NULL;
1183       }
1184
1185       i2 += 2;
1186     }
1187
1188     MEM_SAFE_FREE(temp_points);
1189
1190     /* move points to smooth stroke */
1191     /* duplicate points in a temp area with the new subdivide data */
1192     temp_points = MEM_dupallocN(gps->points);
1193
1194     /* extreme points are not changed */
1195     for (int i = 0; i < gps->totpoints - 2; i++) {
1196       bGPDspoint *pt = &temp_points[i];
1197       bGPDspoint *next = &temp_points[i + 1];
1198       bGPDspoint *pt_final = &gps->points[i + 1];
1199
1200       /* move point */
1201       interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
1202     }
1203     /* free temp memory */
1204     MEM_SAFE_FREE(temp_points);
1205   }
1206 }
1207
1208 /**
1209  * Add randomness to stroke
1210  * \param gps: Stroke data
1211  * \param brush: Brush data
1212  */
1213 void gp_randomize_stroke(bGPDstroke *gps, Brush *brush, RNG *rng)
1214 {
1215   bGPDspoint *pt1, *pt2, *pt3;
1216   float v1[3];
1217   float v2[3];
1218   if (gps->totpoints < 3) {
1219     return;
1220   }
1221
1222   /* get two vectors using 3 points */
1223   pt1 = &gps->points[0];
1224   pt2 = &gps->points[1];
1225   pt3 = &gps->points[(int)(gps->totpoints * 0.75)];
1226
1227   sub_v3_v3v3(v1, &pt2->x, &pt1->x);
1228   sub_v3_v3v3(v2, &pt3->x, &pt2->x);
1229   normalize_v3(v1);
1230   normalize_v3(v2);
1231
1232   /* get normal vector to plane created by two vectors */
1233   float normal[3];
1234   cross_v3_v3v3(normal, v1, v2);
1235   normalize_v3(normal);
1236
1237   /* get orthogonal vector to plane to rotate random effect */
1238   float ortho[3];
1239   cross_v3_v3v3(ortho, v1, normal);
1240   normalize_v3(ortho);
1241
1242   /* Read all points and apply shift vector (first and last point not modified) */
1243   for (int i = 1; i < gps->totpoints - 1; i++) {
1244     bGPDspoint *pt = &gps->points[i];
1245     /* get vector with shift (apply a division because random is too sensitive */
1246     const float fac = BLI_rng_get_float(rng) * (brush->gpencil_settings->draw_random_sub / 10.0f);
1247     float svec[3];
1248     copy_v3_v3(svec, ortho);
1249     if (BLI_rng_get_float(rng) > 0.5f) {
1250       mul_v3_fl(svec, -fac);
1251     }
1252     else {
1253       mul_v3_fl(svec, fac);
1254     }
1255
1256     /* apply shift */
1257     add_v3_v3(&pt->x, svec);
1258   }
1259 }
1260
1261 /* ******************************************************** */
1262 /* Layer Parenting  - Compute Parent Transforms */
1263
1264 /* calculate difference matrix */
1265 void ED_gpencil_parent_location(const Depsgraph *depsgraph,
1266                                 Object *obact,
1267                                 bGPdata *UNUSED(gpd),
1268                                 bGPDlayer *gpl,
1269                                 float diff_mat[4][4])
1270 {
1271   Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact;
1272   Object *obparent = gpl->parent;
1273   Object *obparent_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obparent) :
1274                                               obparent;
1275
1276   /* if not layer parented, try with object parented */
1277   if (obparent_eval == NULL) {
1278     if (ob_eval != NULL) {
1279       if (ob_eval->type == OB_GPENCIL) {
1280         copy_m4_m4(diff_mat, ob_eval->obmat);
1281         return;
1282       }
1283     }
1284     /* not gpencil object */
1285     unit_m4(diff_mat);
1286     return;
1287   }
1288   else {
1289     if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
1290       mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
1291       add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
1292       return;
1293     }
1294     else if (gpl->partype == PARBONE) {
1295       bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr);
1296       if (pchan) {
1297         float tmp_mat[4][4];
1298         mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat);
1299         mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse);
1300         add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
1301       }
1302       else {
1303         /* if bone not found use object (armature) */
1304         mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
1305         add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
1306       }
1307       return;
1308     }
1309     else {
1310       unit_m4(diff_mat); /* not defined type */
1311     }
1312   }
1313 }
1314
1315 /* reset parent matrix for all layers */
1316 void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata *gpd)
1317 {
1318   bGPDspoint *pt;
1319   int i;
1320   float diff_mat[4][4];
1321   float cur_mat[4][4];
1322   float gpl_loc[3];
1323   zero_v3(gpl_loc);
1324
1325   for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1326     if (gpl->parent != NULL) {
1327       /* calculate new matrix */
1328       if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
1329         invert_m4_m4(cur_mat, gpl->parent->obmat);
1330         copy_v3_v3(gpl_loc, obact->obmat[3]);
1331       }
1332       else if (gpl->partype == PARBONE) {
1333         bPoseChannel *pchan = BKE_pose_channel_find_name(gpl->parent->pose, gpl->parsubstr);
1334         if (pchan) {
1335           float tmp_mat[4][4];
1336           mul_m4_m4m4(tmp_mat, gpl->parent->obmat, pchan->pose_mat);
1337           invert_m4_m4(cur_mat, tmp_mat);
1338           copy_v3_v3(gpl_loc, obact->obmat[3]);
1339         }
1340       }
1341
1342       /* only redo if any change */
1343       if (!equals_m4m4(gpl->inverse, cur_mat)) {
1344         /* first apply current transformation to all strokes */
1345         ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
1346         /* undo local object */
1347         sub_v3_v3(diff_mat[3], gpl_loc);
1348
1349         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1350           for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1351             for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1352               mul_m4_v3(diff_mat, &pt->x);
1353             }
1354           }
1355         }
1356         /* set new parent matrix */
1357         copy_m4_m4(gpl->inverse, cur_mat);
1358       }
1359     }
1360   }
1361 }
1362 /* ******************************************************** */
1363 /* GP Object Stuff */
1364
1365 /* Helper function to create new OB_GPENCIL Object */
1366 Object *ED_gpencil_add_object(bContext *C,
1367                               Scene *UNUSED(scene),
1368                               const float loc[3],
1369                               ushort local_view_bits)
1370 {
1371   float rot[3] = {0.0f};
1372
1373   Object *ob = ED_object_add_type(C, OB_GPENCIL, NULL, loc, rot, false, local_view_bits);
1374
1375   /* create default brushes and colors */
1376   ED_gpencil_add_defaults(C, ob);
1377
1378   return ob;
1379 }
1380
1381 /* Helper function to create default colors and drawing brushes */
1382 void ED_gpencil_add_defaults(bContext *C, Object *ob)
1383 {
1384   Main *bmain = CTX_data_main(C);
1385   ToolSettings *ts = CTX_data_tool_settings(C);
1386
1387   BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
1388   Paint *paint = &ts->gp_paint->paint;
1389   /* if not exist, create a new one */
1390   if (paint->brush == NULL) {
1391     /* create new brushes */
1392     BKE_brush_gpencil_presets(C);
1393   }
1394
1395   /* ensure a color exists and is assigned to object */
1396   BKE_gpencil_object_material_ensure_from_active_input_toolsettings(bmain, ob, ts);
1397
1398   /* ensure multiframe falloff curve */
1399   if (ts->gp_sculpt.cur_falloff == NULL) {
1400     ts->gp_sculpt.cur_falloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
1401     CurveMapping *gp_falloff_curve = ts->gp_sculpt.cur_falloff;
1402     curvemapping_initialize(gp_falloff_curve);
1403     curvemap_reset(gp_falloff_curve->cm,
1404                    &gp_falloff_curve->clipr,
1405                    CURVE_PRESET_GAUSS,
1406                    CURVEMAP_SLOPE_POSITIVE);
1407   }
1408 }
1409
1410 /* ******************************************************** */
1411 /* Vertex Groups */
1412
1413 /* assign points to vertex group */
1414 void ED_gpencil_vgroup_assign(bContext *C, Object *ob, float weight)
1415 {
1416   bGPdata *gpd = (bGPdata *)ob->data;
1417   const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
1418   const int def_nr = ob->actdef - 1;
1419   if (!BLI_findlink(&ob->defbase, def_nr)) {
1420     return;
1421   }
1422
1423   CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
1424     bGPDframe *init_gpf = gpl->actframe;
1425     bGPDstroke *gps = NULL;
1426     if (is_multiedit) {
1427       init_gpf = gpl->frames.first;
1428     }
1429
1430     for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
1431       if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
1432         if (gpf == NULL) {
1433           continue;
1434         }
1435
1436         for (gps = gpf->strokes.first; gps; gps = gps->next) {
1437
1438           /* skip strokes that are invalid for current view */
1439           if (ED_gpencil_stroke_can_use(C, gps) == false) {
1440             continue;
1441           }
1442
1443           if (gps->flag & GP_STROKE_SELECT) {
1444             /* verify the weight array is created */
1445             BKE_gpencil_dvert_ensure(gps);
1446
1447             for (int i = 0; i < gps->totpoints; i++) {
1448               bGPDspoint *pt = &gps->points[i];
1449               MDeformVert *dvert = &gps->dvert[i];
1450               if (pt->flag & GP_SPOINT_SELECT) {
1451                 MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
1452                 if (dw) {
1453                   dw->weight = weight;
1454                 }
1455               }
1456             }
1457           }
1458         }
1459       }
1460
1461       /* if not multiedit, exit loop*/
1462       if (!is_multiedit) {
1463         break;
1464       }
1465     }
1466   }
1467   CTX_DATA_END;
1468 }
1469
1470 /* remove points from vertex group */
1471 void ED_gpencil_vgroup_remove(bContext *C, Object *ob)
1472 {
1473   bGPdata *gpd = (bGPdata *)ob->data;
1474   const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
1475   const int def_nr = ob->actdef - 1;
1476   if (!BLI_findlink(&ob->defbase, def_nr)) {
1477     return;
1478   }
1479
1480   CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
1481     bGPDframe *init_gpf = gpl->actframe;
1482     bGPDstroke *gps = NULL;
1483     if (is_multiedit) {
1484       init_gpf = gpl->frames.first;
1485     }
1486
1487     for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
1488       if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
1489         if (gpf == NULL) {
1490           continue;
1491         }
1492
1493         for (gps = gpf->strokes.first; gps; gps = gps->next) {
1494
1495           /* skip strokes that are invalid for current view */
1496           if (ED_gpencil_stroke_can_use(C, gps) == false) {
1497             continue;
1498           }
1499
1500           for (int i = 0; i < gps->totpoints; i++) {
1501             bGPDspoint *pt = &gps->points[i];
1502             if (gps->dvert == NULL) {
1503               continue;
1504             }
1505             MDeformVert *dvert = &gps->dvert[i];
1506
1507             if ((pt->flag & GP_SPOINT_SELECT) && (dvert->totweight > 0)) {
1508               MDeformWeight *dw = defvert_find_index(dvert, def_nr);
1509               if (dw != NULL) {
1510                 defvert_remove_group(dvert, dw);
1511               }
1512             }
1513           }
1514         }
1515       }
1516
1517       /* if not multiedit, exit loop*/
1518       if (!is_multiedit) {
1519         break;
1520       }
1521     }
1522   }
1523   CTX_DATA_END;
1524 }
1525
1526 /* select points of vertex group */
1527 void ED_gpencil_vgroup_select(bContext *C, Object *ob)
1528 {
1529   bGPdata *gpd = (bGPdata *)ob->data;
1530   const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
1531   const int def_nr = ob->actdef - 1;
1532   if (!BLI_findlink(&ob->defbase, def_nr)) {
1533     return;
1534   }
1535
1536   CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
1537     bGPDframe *init_gpf = gpl->actframe;
1538     bGPDstroke *gps = NULL;
1539     if (is_multiedit) {
1540       init_gpf = gpl->frames.first;
1541     }
1542
1543     for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
1544       if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
1545         if (gpf == NULL) {
1546           continue;
1547         }
1548
1549         for (gps = gpf->strokes.first; gps; gps = gps->next) {
1550
1551           /* skip strokes that are invalid for current view */
1552           if (ED_gpencil_stroke_can_use(C, gps) == false) {
1553             continue;
1554           }
1555
1556           for (int i = 0; i < gps->totpoints; i++) {
1557             bGPDspoint *pt = &gps->points[i];
1558             if (gps->dvert == NULL) {
1559               continue;
1560             }
1561             MDeformVert *dvert = &gps->dvert[i];
1562
1563             if (defvert_find_index(dvert, def_nr) != NULL) {
1564               pt->flag |= GP_SPOINT_SELECT;
1565               gps->flag |= GP_STROKE_SELECT;
1566             }
1567           }
1568         }
1569       }
1570
1571       /* if not multiedit, exit loop*/
1572       if (!is_multiedit) {
1573         break;
1574       }
1575     }
1576   }
1577   CTX_DATA_END;
1578 }
1579
1580 /* unselect points of vertex group */
1581 void ED_gpencil_vgroup_deselect(bContext *C, Object *ob)
1582 {
1583   bGPdata *gpd = (bGPdata *)ob->data;
1584   const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
1585   const int def_nr = ob->actdef - 1;
1586   if (!BLI_findlink(&ob->defbase, def_nr)) {
1587     return;
1588   }
1589
1590   CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
1591     bGPDframe *init_gpf = gpl->actframe;
1592     bGPDstroke *gps = NULL;
1593     if (is_multiedit) {
1594       init_gpf = gpl->frames.first;
1595     }
1596
1597     for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
1598       if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
1599         if (gpf == NULL) {
1600           continue;
1601         }
1602
1603         for (gps = gpf->strokes.first; gps; gps = gps->next) {
1604
1605           /* skip strokes that are invalid for current view */
1606           if (ED_gpencil_stroke_can_use(C, gps) == false) {
1607             continue;
1608           }
1609
1610           for (int i = 0; i < gps->totpoints; i++) {
1611             bGPDspoint *pt = &gps->points[i];
1612             if (gps->dvert == NULL) {
1613               continue;
1614             }
1615             MDeformVert *dvert = &gps->dvert[i];
1616
1617             if (defvert_find_index(dvert, def_nr) != NULL) {
1618               pt->flag &= ~GP_SPOINT_SELECT;
1619             }
1620           }
1621         }
1622       }
1623
1624       /* if not multiedit, exit loop*/
1625       if (!is_multiedit) {
1626         break;
1627       }
1628     }
1629   }
1630   CTX_DATA_END;
1631 }
1632
1633 /* ******************************************************** */
1634 /* Cursor drawing */
1635
1636 /* check if cursor is in drawing region */
1637 static bool gp_check_cursor_region(bContext *C, int mval_i[2])
1638 {
1639   ARegion *ar = CTX_wm_region(C);
1640   ScrArea *sa = CTX_wm_area(C);
1641   Object *ob = CTX_data_active_object(C);
1642
1643   if ((ob == NULL) ||
1644       (!ELEM(ob->mode, OB_MODE_PAINT_GPENCIL, OB_MODE_SCULPT_GPENCIL, OB_MODE_WEIGHT_GPENCIL))) {
1645     return false;
1646   }
1647
1648   /* TODO: add more spacetypes */
1649   if (!ELEM(sa->spacetype, SPACE_VIEW3D)) {
1650     return false;
1651   }
1652   if ((ar) && (ar->regiontype != RGN_TYPE_WINDOW)) {
1653     return false;
1654   }
1655   else if (ar) {
1656     return BLI_rcti_isect_pt_v(&ar->winrct, mval_i);
1657   }
1658   else {
1659     return false;
1660   }
1661 }
1662
1663 /* draw eraser cursor */
1664 void ED_gpencil_brush_draw_eraser(Brush *brush, int x, int y)
1665 {
1666   short radius = (short)brush->size;
1667
1668   GPUVertFormat *format = immVertexFormat();
1669   const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1670   immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1671
1672   GPU_line_smooth(true);
1673   GPU_blend(true);
1674   glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1675
1676   immUniformColor4ub(255, 100, 100, 20);
1677   imm_draw_circle_fill_2d(shdr_pos, x, y, radius, 40);
1678
1679   immUnbindProgram();
1680
1681   immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
1682
1683   float viewport_size[4];
1684   glGetFloatv(GL_VIEWPORT, viewport_size);
1685   immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
1686
1687   immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
1688   immUniform1i("colors_len", 0); /* "simple" mode */
1689   immUniform1f("dash_width", 12.0f);
1690   immUniform1f("dash_factor", 0.5f);
1691
1692   imm_draw_circle_wire_2d(
1693       shdr_pos,
1694       x,
1695       y,
1696       radius,
1697       /* XXX Dashed shader gives bad results with sets of small segments currently,
1698        *     temp hack around the issue. :( */
1699       max_ii(8, radius / 2)); /* was fixed 40 */
1700
1701   immUnbindProgram();
1702
1703   GPU_blend(false);
1704   GPU_line_smooth(false);
1705 }
1706
1707 static bool gp_brush_cursor_poll(bContext *C)
1708 {
1709   if (WM_toolsystem_active_tool_is_brush(C)) {
1710     return true;
1711   }
1712   return false;
1713 }
1714
1715 /* Helper callback for drawing the cursor itself */
1716 static void gp_brush_cursor_draw(bContext *C, int x, int y, void *customdata)
1717 {
1718   Scene *scene = CTX_data_scene(C);
1719   Object *ob = CTX_data_active_object(C);
1720   ARegion *ar = CTX_wm_region(C);
1721
1722   GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
1723   bGPdata *gpd = ED_gpencil_data_get_active(C);
1724   GP_Sculpt_Data *gp_brush = NULL;
1725   Brush *brush = NULL;
1726   Material *ma = NULL;
1727   MaterialGPencilStyle *gp_style = NULL;
1728   float *last_mouse_position = customdata;
1729
1730   if ((gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE)) {
1731     gp_brush = &gset->brush[gset->weighttype];
1732   }
1733   else {
1734     gp_brush = &gset->brush[gset->brushtype];
1735   }
1736
1737   /* default radius and color */
1738   float color[3] = {1.0f, 1.0f, 1.0f};
1739   float darkcolor[3];
1740   float radius = 3.0f;
1741
1742   int mval_i[2] = {x, y};
1743   /* check if cursor is in drawing region and has valid datablock */
1744   if ((!gp_check_cursor_region(C, mval_i)) || (gpd == NULL)) {
1745     return;
1746   }
1747
1748   /* for paint use paint brush size and color */
1749   if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
1750     brush = scene->toolsettings->gp_paint->paint.brush;
1751     if ((brush == NULL) || (brush->gpencil_settings == NULL)) {
1752       return;
1753     }
1754
1755     /* while drawing hide */
1756     if ((gpd->runtime.sbuffer_size > 0) &&
1757         ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
1758         ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0)) {
1759       return;
1760     }
1761
1762     if ((brush->gpencil_settings->flag & GP_BRUSH_ENABLE_CURSOR) == 0) {
1763       return;
1764     }
1765
1766     /* eraser has special shape and use a different shader program */
1767     if (brush->gpencil_tool == GPAINT_TOOL_ERASE) {
1768       ED_gpencil_brush_draw_eraser(brush, x, y);
1769       return;
1770     }
1771
1772     /* get current drawing color */
1773     ma = BKE_gpencil_object_material_get_from_brush(ob, brush);
1774
1775     if (ma) {
1776       gp_style = ma->gp_style;
1777
1778       /* after some testing, display the size of the brush is not practical because
1779        * is too disruptive and the size of cursor does not change with zoom factor.
1780        * The decision was to use a fix size, instead of brush->thickness value.
1781        */
1782       if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) &&
1783           ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
1784           ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) &&
1785           (brush->gpencil_tool == GPAINT_TOOL_DRAW)) {
1786         radius = 2.0f;
1787         copy_v3_v3(color, gp_style->stroke_rgba);
1788       }
1789       else {
1790         radius = 5.0f;
1791         copy_v3_v3(color, brush->add_col);
1792       }
1793     }
1794   }
1795
1796   /* for sculpt use sculpt brush size */
1797   if (GPENCIL_SCULPT_OR_WEIGHT_MODE(gpd)) {
1798     if (gp_brush) {
1799       if ((gp_brush->flag & GP_SCULPT_FLAG_ENABLE_CURSOR) == 0) {
1800         return;
1801       }
1802
1803       radius = gp_brush->size;
1804       if (gp_brush->flag & (GP_SCULPT_FLAG_INVERT | GP_SCULPT_FLAG_TMP_INVERT)) {
1805         copy_v3_v3(color, gp_brush->curcolor_sub);
1806       }
1807       else {
1808         copy_v3_v3(color, gp_brush->curcolor_add);
1809       }
1810     }
1811   }
1812
1813   /* draw icon */
1814   GPUVertFormat *format = immVertexFormat();
1815   uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1816   immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1817
1818   GPU_line_smooth(true);
1819   GPU_blend(true);
1820
1821   /* Inner Ring: Color from UI panel */
1822   immUniformColor4f(color[0], color[1], color[2], 0.8f);
1823   if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) &&
1824       ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
1825       ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) &&
1826       (brush->gpencil_tool == GPAINT_TOOL_DRAW)) {
1827     imm_draw_circle_fill_2d(pos, x, y, radius, 40);
1828   }
1829   else {
1830     imm_draw_circle_wire_2d(pos, x, y, radius, 40);
1831   }
1832
1833   /* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */
1834   mul_v3_v3fl(darkcolor, color, 0.40f);
1835   immUniformColor4f(darkcolor[0], darkcolor[1], darkcolor[2], 0.8f);
1836   imm_draw_circle_wire_2d(pos, x, y, radius + 1, 40);
1837
1838   GPU_blend(false);
1839   GPU_line_smooth(false);
1840
1841   /* Draw line for lazy mouse */
1842   if ((last_mouse_position) && (brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP)) {
1843     GPU_line_smooth(true);
1844     GPU_blend(true);
1845
1846     copy_v3_v3(color, brush->add_col);
1847     immUniformColor4f(color[0], color[1], color[2], 0.8f);
1848
1849     immBegin(GPU_PRIM_LINES, 2);
1850     immVertex2f(pos, x, y);
1851     immVertex2f(
1852         pos, last_mouse_position[0] + ar->winrct.xmin, last_mouse_position[1] + ar->winrct.ymin);
1853     immEnd();
1854
1855     GPU_blend(false);
1856     GPU_line_smooth(false);
1857   }
1858
1859   immUnbindProgram();
1860 }
1861
1862 /* Turn brush cursor in on/off */
1863 void ED_gpencil_toggle_brush_cursor(bContext *C, bool enable, void *customdata)
1864 {
1865   Scene *scene = CTX_data_scene(C);
1866   GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
1867   float *lastpost = customdata;
1868
1869   if (gset->paintcursor && !enable) {
1870     /* clear cursor */
1871     WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
1872     gset->paintcursor = NULL;
1873   }
1874   else if (enable) {
1875     /* in some situations cursor could be duplicated, so it is better disable first if exist */
1876     if (gset->paintcursor) {
1877       /* clear cursor */
1878       WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
1879       gset->paintcursor = NULL;
1880     }
1881     /* enable cursor */
1882     gset->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C),
1883                                                  SPACE_TYPE_ANY,
1884                                                  RGN_TYPE_ANY,
1885                                                  gp_brush_cursor_poll,
1886                                                  gp_brush_cursor_draw,
1887                                                  (lastpost) ? customdata : NULL);
1888   }
1889 }
1890
1891 /* verify if is using the right brush */
1892 static void gpencil_verify_brush_type(bContext *C, int newmode)
1893 {
1894   ToolSettings *ts = CTX_data_tool_settings(C);
1895   GP_Sculpt_Settings *gset = &ts->gp_sculpt;
1896
1897   switch (newmode) {
1898     case OB_MODE_SCULPT_GPENCIL:
1899       gset->flag &= ~GP_SCULPT_SETT_FLAG_WEIGHT_MODE;
1900       if ((gset->brushtype < 0) || (gset->brushtype >= GP_SCULPT_TYPE_WEIGHT)) {
1901         gset->brushtype = GP_SCULPT_TYPE_PUSH;
1902       }
1903       break;
1904     case OB_MODE_WEIGHT_GPENCIL:
1905       gset->flag |= GP_SCULPT_SETT_FLAG_WEIGHT_MODE;
1906       if ((gset->weighttype < GP_SCULPT_TYPE_WEIGHT) || (gset->weighttype >= GP_SCULPT_TYPE_MAX)) {
1907         gset->weighttype = GP_SCULPT_TYPE_WEIGHT;
1908       }
1909       break;
1910     default:
1911       break;
1912   }
1913 }
1914
1915 /* set object modes */
1916 void ED_gpencil_setup_modes(bContext *C, bGPdata *gpd, int newmode)
1917 {
1918   if (!gpd) {
1919     return;
1920   }
1921
1922   switch (newmode) {
1923     case OB_MODE_EDIT_GPENCIL:
1924       gpd->flag |= GP_DATA_STROKE_EDITMODE;
1925       gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
1926       gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
1927       gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
1928       ED_gpencil_toggle_brush_cursor(C, false, NULL);
1929       break;
1930     case OB_MODE_PAINT_GPENCIL:
1931       gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
1932       gpd->flag |= GP_DATA_STROKE_PAINTMODE;
1933       gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
1934       gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
1935       ED_gpencil_toggle_brush_cursor(C, true, NULL);
1936       break;
1937     case OB_MODE_SCULPT_GPENCIL:
1938       gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
1939       gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
1940       gpd->flag |= GP_DATA_STROKE_SCULPTMODE;
1941       gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
1942       gpencil_verify_brush_type(C, OB_MODE_SCULPT_GPENCIL);
1943       ED_gpencil_toggle_brush_cursor(C, true, NULL);
1944       break;
1945     case OB_MODE_WEIGHT_GPENCIL:
1946       gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
1947       gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
1948       gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
1949       gpd->flag |= GP_DATA_STROKE_WEIGHTMODE;
1950       gpencil_verify_brush_type(C, OB_MODE_WEIGHT_GPENCIL);
1951       ED_gpencil_toggle_brush_cursor(C, true, NULL);
1952       break;
1953     default:
1954       gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
1955       gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
1956       gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
1957       gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
1958       ED_gpencil_toggle_brush_cursor(C, false, NULL);
1959       break;
1960   }
1961 }
1962
1963 /* helper to convert 2d to 3d for simple drawing buffer */
1964 static void gpencil_stroke_convertcoords(ARegion *ar,
1965                                          const tGPspoint *point2D,
1966                                          float origin[3],
1967                                          float out[3])
1968 {
1969   float mval_f[2] = {(float)point2D->x, (float)point2D->y};
1970   float mval_prj[2];
1971   float rvec[3], dvec[3];
1972   float zfac;
1973
1974   copy_v3_v3(rvec, origin);
1975
1976   zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL);
1977
1978   if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
1979     sub_v2_v2v2(mval_f, mval_prj, mval_f);
1980     ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
1981     sub_v3_v3v3(out, rvec, dvec);
1982   }
1983   else {
1984     zero_v3(out);
1985   }
1986 }
1987
1988 /* convert 2d tGPspoint to 3d bGPDspoint */
1989 void ED_gpencil_tpoint_to_point(ARegion *ar, float origin[3], const tGPspoint *tpt, bGPDspoint *pt)
1990 {
1991   float p3d[3];
1992   /* conversion to 3d format */
1993   gpencil_stroke_convertcoords(ar, tpt, origin, p3d);
1994   copy_v3_v3(&pt->x, p3d);
1995
1996   pt->pressure = tpt->pressure;
1997   pt->strength = tpt->strength;
1998   pt->uv_fac = tpt->uv_fac;
1999   pt->uv_rot = tpt->uv_rot;
2000 }
2001
2002 /* texture coordinate utilities */
2003 void ED_gpencil_calc_stroke_uv(Object *ob, bGPDstroke *gps)
2004 {
2005   if (gps == NULL) {
2006     return;
2007   }
2008   MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
2009   float pixsize;
2010   if (gp_style) {
2011     pixsize = gp_style->texture_pixsize / 1000000.0f;
2012   }
2013   else {
2014     /* use this value by default */
2015     pixsize = 0.0001f;
2016   }
2017   pixsize = MAX2(pixsize, 0.0000001f);
2018
2019   bGPDspoint *pt = NULL;
2020   bGPDspoint *ptb = NULL;
2021   int i;
2022   float totlen = 0.0f;
2023
2024   /* first read all points and calc distance */
2025   for (i = 0; i < gps->totpoints; i++) {
2026     pt = &gps->points[i];
2027     /* first point */
2028     if (i == 0) {
2029       pt->uv_fac = 0.0f;
2030       continue;
2031     }
2032
2033     ptb = &gps->points[i - 1];
2034     totlen += len_v3v3(&pt->x, &ptb->x) / pixsize;
2035     pt->uv_fac = totlen;
2036   }
2037
2038   /* normalize the distance using a factor */
2039   float factor;
2040
2041   /* if image, use texture width */
2042   if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) &&
2043       (gp_style->sima)) {
2044     factor = gp_style->sima->gen_x;
2045   }
2046   else if (totlen == 0) {
2047     return;
2048   }
2049   else {
2050     factor = totlen;
2051   }
2052
2053   for (i = 0; i < gps->totpoints; i++) {
2054     pt = &gps->points[i];
2055     pt->uv_fac /= factor;
2056   }
2057 }
2058
2059 /* recalc uv for any stroke using the material */
2060 void ED_gpencil_update_color_uv(Main *bmain, Material *mat)
2061 {
2062   Material *gps_ma = NULL;
2063   /* read all strokes  */
2064   for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
2065     if (ob->type == OB_GPENCIL) {
2066       bGPdata *gpd = ob->data;
2067       if (gpd == NULL) {
2068         continue;
2069       }
2070
2071       for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
2072         /* only editable and visible layers are considered */
2073         if (gpencil_layer_is_editable(gpl)) {
2074           for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
2075             for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
2076               /* check if it is editable */
2077               if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
2078                 continue;
2079               }
2080               gps_ma = give_current_material(ob, gps->mat_nr + 1);
2081               /* update */
2082               if ((gps_ma) && (gps_ma == mat)) {
2083                 ED_gpencil_calc_stroke_uv(ob, gps);
2084               }
2085             }
2086           }
2087         }
2088       }
2089       DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
2090     }
2091   }
2092 }
2093
2094 static bool gpencil_check_collision(bGPDstroke *gps,
2095                                     bGPDstroke **gps_array,
2096                                     GHash *all_2d,
2097                                     int totstrokes,
2098                                     float p2d_a1[2],
2099                                     float p2d_a2[2],
2100                                     float r_hit[2])
2101 {
2102   bool hit = false;
2103   /* check segment with all segments of all strokes */
2104   for (int s = 0; s < totstrokes; s++) {
2105     bGPDstroke *gps_iter = gps_array[s];
2106     if (gps_iter->totpoints < 2) {
2107       continue;
2108     }
2109     /* get stroke 2d version */
2110     float(*points2d)[2] = BLI_ghash_lookup(all_2d, gps_iter);
2111
2112     for (int i2 = 0; i2 < gps_iter->totpoints - 1; i2++) {
2113       float p2d_b1[2], p2d_b2[2];
2114       copy_v2_v2(p2d_b1, points2d[i2]);
2115       copy_v2_v2(p2d_b2, points2d[i2 + 1]);
2116
2117       /* don't self check */
2118       if (gps == gps_iter) {
2119         if (equals_v2v2(p2d_a1, p2d_b1) || equals_v2v2(p2d_a1, p2d_b2)) {
2120           continue;
2121         }
2122         if (equals_v2v2(p2d_a2, p2d_b1) || equals_v2v2(p2d_a2, p2d_b2)) {
2123           continue;
2124         }
2125       }
2126       /* check collision */
2127       int check = isect_seg_seg_v2_point(p2d_a1, p2d_a2, p2d_b1, p2d_b2, r_hit);
2128       if (check > 0) {
2129         hit = true;
2130         break;
2131       }
2132     }
2133
2134     if (hit) {
2135       break;
2136     }
2137   }
2138
2139   if (!hit) {
2140     zero_v2(r_hit);
2141   }
2142
2143   return hit;
2144 }
2145
2146 static void gp_copy_points(bGPDstroke *gps, bGPDspoint *pt, bGPDspoint *pt_final, int i, int i2)
2147 {
2148   /* don't copy same point */
2149   if (i == i2) {
2150     return;
2151   }
2152
2153   copy_v3_v3(&pt_final->x, &pt->x);
2154   pt_final->pressure = pt->pressure;
2155   pt_final->strength = pt->strength;
2156   pt_final->time = pt->time;
2157   pt_final->flag = pt->flag;
2158   pt_final->uv_fac = pt->uv_fac;
2159   pt_final->uv_rot = pt->uv_rot;
2160
2161   if (gps->dvert != NULL) {
2162     MDeformVert *dvert = &gps->dvert[i];
2163     MDeformVert *dvert_final = &gps->dvert[i2];
2164     MEM_SAFE_FREE(dvert_final->dw);
2165
2166     dvert_final->totweight = dvert->totweight;
2167     if (dvert->dw == NULL) {
2168       dvert_final->dw = NULL;
2169       dvert_final->totweight = 0;
2170     }
2171     else {
2172       dvert_final->dw = MEM_dupallocN(dvert->dw);
2173     }
2174   }
2175 }
2176
2177 static void gp_insert_point(
2178     bGPDstroke *gps, bGPDspoint *a_pt, bGPDspoint *b_pt, float co_a[3], float co_b[3])
2179 {
2180   bGPDspoint *temp_points;
2181   int totnewpoints, oldtotpoints;
2182
2183   totnewpoints = gps->totpoints;
2184   if (a_pt) {
2185     totnewpoints++;
2186   }
2187   if (b_pt) {
2188     totnewpoints++;
2189   }
2190
2191   /* duplicate points in a temp area */
2192   temp_points = MEM_dupallocN(gps->points);
2193   oldtotpoints = gps->totpoints;
2194
2195   /* look index of base points because memory is changed when resize points array */
2196   int a_idx = -1;
2197   int b_idx = -1;
2198   for (int i = 0; i < oldtotpoints; i++) {
2199     bGPDspoint *pt = &gps->points[i];
2200     if (pt == a_pt) {
2201       a_idx = i;
2202     }
2203     if (pt == b_pt) {
2204       b_idx = i;
2205     }
2206   }
2207
2208   /* resize the points arrays */
2209   gps->totpoints = totnewpoints;
2210   gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
2211   if (gps->dvert != NULL) {
2212     gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
2213   }
2214   gps->flag |= GP_STROKE_RECALC_GEOMETRY;
2215
2216   /* copy all points */
2217   int i2 = 0;
2218   for (int i = 0; i < oldtotpoints; i++) {
2219     bGPDspoint *pt = &temp_points[i];
2220     bGPDspoint *pt_final = &gps->points[i2];
2221     gp_copy_points(gps, pt, pt_final, i, i2);
2222
2223     /* create new point duplicating point and copy location */
2224     if ((i == a_idx) || (i == b_idx)) {
2225       i2++;
2226       pt_final = &gps->points[i2];
2227       gp_copy_points(gps, pt, pt_final, i, i2);
2228       copy_v3_v3(&pt_final->x, (i == a_idx) ? co_a : co_b);
2229
2230       /* unselect */
2231       pt_final->flag &= ~GP_SPOINT_SELECT;
2232       /* tag to avoid more checking with this point */
2233       pt_final->flag |= GP_SPOINT_TAG;
2234     }
2235
2236     i2++;
2237   }
2238
2239   MEM_SAFE_FREE(temp_points);
2240 }
2241
2242 static float gp_calc_factor(float p2d_a1[2], float p2d_a2[2], float r_hit2d[2])
2243 {
2244   float dist1 = len_squared_v2v2(p2d_a1, p2d_a2);
2245   float dist2 = len_squared_v2v2(p2d_a1, r_hit2d);
2246   float f = dist1 > 0.0f ? dist2 / dist1 : 0.0f;
2247
2248   /* apply a correction factor */
2249   float v1[2];
2250   interp_v2_v2v2(v1, p2d_a1, p2d_a2, f);
2251   float dist3 = len_squared_v2v2(p2d_a1, v1);
2252   float f1 = dist1 > 0.0f ? dist3 / dist1 : 0.0f;
2253   f = f + (f - f1);
2254
2255   return f;
2256 }
2257
2258 /* extend selection to stroke intersections */
2259 int ED_gpencil_select_stroke_segment(bGPDlayer *gpl,
2260                                      bGPDstroke *gps,
2261                                      bGPDspoint *pt,
2262                                      bool select,
2263                                      bool insert,
2264                                      const float scale,
2265                                      float r_hita[3],
2266                                      float r_hitb[3])
2267 {
2268   const float min_factor = 0.0015f;
2269   bGPDspoint *pta1 = NULL;
2270   bGPDspoint *pta2 = NULL;
2271   float f = 0.0f;
2272   int i2 = 0;
2273
2274   bGPDframe *gpf = gpl->actframe;
2275   if (gpf == NULL) {
2276     return 0;
2277   }
2278
2279   int memsize = BLI_listbase_count(&gpf->strokes);
2280   bGPDstroke **gps_array = MEM_callocN(sizeof(bGPDstroke *) * memsize, __func__);
2281
2282   /* save points */
2283   bGPDspoint *oldpoints = MEM_dupallocN(gps->points);
2284
2285   /* Save list of strokes to check */
2286   int totstrokes = 0;
2287   for (bGPDstroke *gps_iter = gpf->strokes.first; gps_iter; gps_iter = gps_iter->next) {
2288     if (gps_iter->totpoints < 2) {
2289       continue;
2290     }
2291     gps_array[totstrokes] = gps_iter;
2292     totstrokes++;
2293   }
2294
2295   if (totstrokes == 0) {
2296     return 0;
2297   }
2298
2299   /* look for index of the current point */
2300   int cur_idx = -1;
2301   for (int i = 0; i < gps->totpoints; i++) {
2302     pta1 = &gps->points[i];
2303     if (pta1 == pt) {
2304       cur_idx = i;
2305       break;
2306     }
2307   }
2308   if (cur_idx < 0) {
2309     return 0;
2310   }
2311
2312   /* convert all gps points to 2d and save in a hash to avoid recalculation  */
2313   int direction = 0;
2314   float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints,
2315                                     "GP Stroke temp 2d points");
2316   BKE_gpencil_stroke_2d_flat_ref(
2317       gps->points, gps->totpoints, gps->points, gps->totpoints, points2d, scale, &direction);
2318
2319   GHash *all_2d = BLI_ghash_ptr_new(__func__);
2320
2321   for (int s = 0; s < totstrokes; s++) {
2322     bGPDstroke *gps_iter = gps_array[s];
2323     float(*points2d_iter)[2] = MEM_mallocN(sizeof(*points2d_iter) * gps_iter->totpoints, __func__);
2324
2325     /* the extremes of the stroke are scaled to improve collision detection
2326      * for near lines */
2327     BKE_gpencil_stroke_2d_flat_ref(gps->points,
2328                                    gps->totpoints,
2329                                    gps_iter->points,
2330                                    gps_iter->totpoints,
2331                                    points2d_iter,
2332                                    scale,
2333                                    &direction);
2334     BLI_ghash_insert(all_2d, gps_iter, points2d_iter);
2335   }
2336
2337   bool hit_a = false;
2338   bool hit_b = false;
2339   float p2d_a1[2] = {0.0f, 0.0f};
2340   float p2d_a2[2] = {0.0f, 0.0f};
2341   float r_hit2d[2];
2342   bGPDspoint *hit_pointa = NULL;
2343   bGPDspoint *hit_pointb = NULL;
2344
2345   /* analyze points before current */
2346   if (cur_idx > 0) {
2347     for (int i = cur_idx; i >= 0; i--) {
2348       pta1 = &gps->points[i];
2349       copy_v2_v2(p2d_a1, points2d[i]);
2350
2351       i2 = i - 1;
2352       CLAMP_MIN(i2, 0);
2353       pta2 = &gps->points[i2];
2354       copy_v2_v2(p2d_a2, points2d[i2]);
2355
2356       hit_a = gpencil_check_collision(gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d);
2357
2358       if (select) {
2359         pta1->flag |= GP_SPOINT_SELECT;
2360       }
2361       else {
2362         pta1->flag &= ~GP_SPOINT_SELECT;
2363       }
2364
2365       if (hit_a) {
2366         f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d);
2367         interp_v3_v3v3(r_hita, &pta1->x, &pta2->x, f);
2368         if (f > min_factor) {
2369           hit_pointa = pta2; /* first point is second (inverted loop) */
2370         }
2371         else {
2372           pta1->flag &= ~GP_SPOINT_SELECT;
2373         }
2374         break;
2375       }
2376     }
2377   }
2378
2379   /* analyze points after current */
2380   for (int i = cur_idx; i < gps->totpoints; i++) {
2381     pta1 = &gps->points[i];
2382     copy_v2_v2(p2d_a1, points2d[i]);
2383
2384     i2 = i + 1;
2385     CLAMP_MAX(i2, gps->totpoints - 1);
2386     pta2 = &gps->points[i2];
2387     copy_v2_v2(p2d_a2, points2d[i2]);
2388
2389     hit_b = gpencil_check_collision(gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d);
2390
2391     if (select) {
2392       pta1->flag |= GP_SPOINT_SELECT;
2393     }
2394     else {
2395       pta1->flag &= ~GP_SPOINT_SELECT;
2396     }
2397
2398     if (hit_b) {
2399       f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d);
2400       interp_v3_v3v3(r_hitb, &pta1->x, &pta2->x, f);
2401       if (f > min_factor) {
2402         hit_pointb = pta1;
2403       }
2404       else {
2405         pta1->flag &= ~GP_SPOINT_SELECT;
2406       }
2407       break;
2408     }
2409   }
2410
2411   /* insert new point in the collision points */
2412   if (insert) {
2413     gp_insert_point(gps, hit_pointa, hit_pointb, r_hita, r_hitb);
2414   }
2415
2416   /* free memory */
2417   if (all_2d) {
2418     GHashIterator gh_iter;
2419     GHASH_ITER (gh_iter, all_2d) {
2420       float(*p2d)[2] = BLI_ghashIterator_getValue(&gh_iter);
2421       MEM_SAFE_FREE(p2d);
2422     }
2423     BLI_ghash_free(all_2d, NULL, NULL);
2424   }
2425
2426   /* if no hit, reset selection flag */
2427   if ((!hit_a) && (!hit_b)) {
2428     for (int i = 0; i < gps->totpoints; i++) {
2429       pta1 = &gps->points[i];
2430       pta2 = &oldpoints[i];
2431       pta1->flag = pta2->flag;
2432     }
2433   }
2434
2435   MEM_SAFE_FREE(points2d);
2436   MEM_SAFE_FREE(gps_array);
2437   MEM_SAFE_FREE(oldpoints);
2438
2439   /* return type of hit */
2440   if ((hit_a) && (hit_b)) {
2441     return 3;
2442   }
2443   else if (hit_a) {
2444     return 1;
2445   }
2446   else if (hit_b) {
2447     return 2;
2448   }
2449   else {
2450     return 0;
2451   }
2452 }
2453
2454 void ED_gpencil_select_toggle_all(bContext *C, int action)
2455 {
2456   /* for "toggle", test for existing selected strokes */
2457   if (action == SEL_TOGGLE) {
2458     action = SEL_SELECT;
2459
2460     CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
2461       if (gps->flag & GP_STROKE_SELECT) {
2462         action = SEL_DESELECT;
2463         break;  // XXX: this only gets out of the inner loop...
2464       }
2465     }
2466     CTX_DATA_END;
2467   }
2468
2469   /* if deselecting, we need to deselect strokes across all frames
2470    * - Currently, an exception is only given for deselection
2471    *   Selecting and toggling should only affect what's visible,
2472    *   while deselecting helps clean up unintended/forgotten
2473    *   stuff on other frames
2474    */
2475   if (action == SEL_DESELECT) {
2476     /* deselect strokes across editable layers
2477      * NOTE: we limit ourselves to editable layers, since once a layer is "locked/hidden
2478      *       nothing should be able to touch it
2479      */
2480     CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
2481       bGPDframe *gpf;
2482
2483       /* deselect all strokes on all frames */
2484       for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
2485         bGPDstroke *gps;
2486
2487         for (gps = gpf->strokes.first; gps; gps = gps->next) {
2488           bGPDspoint *pt;
2489           int i;
2490
2491           /* only edit strokes that are valid in this view... */
2492           if (ED_gpencil_stroke_can_use(C, gps)) {
2493             for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
2494               pt->flag &= ~GP_SPOINT_SELECT;
2495             }
2496
2497             gps->flag &= ~GP_STROKE_SELECT;
2498           }
2499         }
2500       }
2501     }
2502     CTX_DATA_END;
2503   }
2504   else {
2505     /* select or deselect all strokes */
2506     CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
2507       bGPDspoint *pt;
2508       int i;
2509       bool selected = false;
2510
2511       /* Change selection status of all points, then make the stroke match */
2512       for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
2513         switch (action) {
2514           case SEL_SELECT:
2515             pt->flag |= GP_SPOINT_SELECT;
2516             break;
2517           //case SEL_DESELECT:
2518           //  pt->flag &= ~GP_SPOINT_SELECT;
2519           //  break;
2520           case SEL_INVERT:
2521             pt->flag ^= GP_SPOINT_SELECT;
2522             break;
2523         }
2524
2525         if (pt->flag & GP_SPOINT_SELECT) {
2526           selected = true;
2527         }
2528       }
2529
2530       /* Change status of stroke */
2531       if (selected) {
2532         gps->flag |= GP_STROKE_SELECT;
2533       }
2534       else {
2535         gps->flag &= ~GP_STROKE_SELECT;
2536       }
2537     }
2538     CTX_DATA_END;
2539   }
2540 }