ab9c3bb17da559356bc9074602c7d24af0ee2ba1
[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_ensure_evaluated_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_ensure_evaluated_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(scene, depsgraph, ar, v3d, rv3d, &r_gsc->subrect_data, true);
564       r_gsc->subrect = &r_gsc->subrect_data;
565     }
566   }
567 }
568
569 /**
570  * Convert point to parent space
571  *
572  * \param pt: Original point
573  * \param diff_mat: Matrix with the difference between original parent matrix
574  * \param[out] r_pt: Pointer to new point after apply matrix
575  */
576 void gp_point_to_parent_space(const bGPDspoint *pt, const float diff_mat[4][4], bGPDspoint *r_pt)
577 {
578   float fpt[3];
579
580   mul_v3_m4v3(fpt, diff_mat, &pt->x);
581   copy_v3_v3(&r_pt->x, fpt);
582 }
583
584 /**
585  * Change position relative to parent object
586  */
587 void gp_apply_parent(
588     Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps)
589 {
590   bGPDspoint *pt;
591   int i;
592
593   /* undo matrix */
594   float diff_mat[4][4];
595   float inverse_diff_mat[4][4];
596   float fpt[3];
597
598   ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
599   invert_m4_m4(inverse_diff_mat, diff_mat);
600
601   for (i = 0; i < gps->totpoints; i++) {
602     pt = &gps->points[i];
603     mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x);
604     copy_v3_v3(&pt->x, fpt);
605   }
606 }
607
608 /**
609  * Change point position relative to parent object
610  */
611 void gp_apply_parent_point(
612     Depsgraph *depsgraph, Object *obact, bGPdata *gpd, bGPDlayer *gpl, bGPDspoint *pt)
613 {
614   /* undo matrix */
615   float diff_mat[4][4];
616   float inverse_diff_mat[4][4];
617   float fpt[3];
618
619   ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
620   invert_m4_m4(inverse_diff_mat, diff_mat);
621
622   mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x);
623   copy_v3_v3(&pt->x, fpt);
624 }
625
626 /**
627  * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D)
628  *
629  * \param[out] r_x  The screen-space x-coordinate of the point
630  * \param[out] r_y  The screen-space y-coordinate of the point
631  *
632  * \warning This assumes that the caller has already checked
633  * whether the stroke in question can be drawn.
634  */
635 void gp_point_to_xy(
636     const GP_SpaceConversion *gsc, const bGPDstroke *gps, const bGPDspoint *pt, int *r_x, int *r_y)
637 {
638   const ARegion *ar = gsc->ar;
639   const View2D *v2d = gsc->v2d;
640   const rctf *subrect = gsc->subrect;
641   int xyval[2];
642
643   /* sanity checks */
644   BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D));
645   BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D));
646
647   if (gps->flag & GP_STROKE_3DSPACE) {
648     if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
649       *r_x = xyval[0];
650       *r_y = xyval[1];
651     }
652     else {
653       *r_x = V2D_IS_CLIPPED;
654       *r_y = V2D_IS_CLIPPED;
655     }
656   }
657   else if (gps->flag & GP_STROKE_2DSPACE) {
658     float vec[3] = {pt->x, pt->y, 0.0f};
659     mul_m4_v3(gsc->mat, vec);
660     UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], r_x, r_y);
661   }
662   else {
663     if (subrect == NULL) {
664       /* normal 3D view (or view space) */
665       *r_x = (int)(pt->x / 100 * ar->winx);
666       *r_y = (int)(pt->y / 100 * ar->winy);
667     }
668     else {
669       /* camera view, use subrect */
670       *r_x = (int)((pt->x / 100) * BLI_rctf_size_x(subrect)) + subrect->xmin;
671       *r_y = (int)((pt->y / 100) * BLI_rctf_size_y(subrect)) + subrect->ymin;
672     }
673   }
674 }
675
676 /**
677  * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D).
678  *
679  * Just like #gp_point_to_xy(), except the resulting coordinates are floats not ints.
680  * Use this version to solve "stair-step" artifacts which may arise when
681  * roundtripping the calculations.
682  *
683  * \param r_x[out]: The screen-space x-coordinate of the point.
684  * \param r_y[out]: The screen-space y-coordinate of the point.
685  *
686  * \warning This assumes that the caller has already checked
687  * whether the stroke in question can be drawn.
688  */
689 void gp_point_to_xy_fl(const GP_SpaceConversion *gsc,
690                        const bGPDstroke *gps,
691                        const bGPDspoint *pt,
692                        float *r_x,
693                        float *r_y)
694 {
695   const ARegion *ar = gsc->ar;
696   const View2D *v2d = gsc->v2d;
697   const rctf *subrect = gsc->subrect;
698   float xyval[2];
699
700   /* sanity checks */
701   BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D));
702   BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D));
703
704   if (gps->flag & GP_STROKE_3DSPACE) {
705     if (ED_view3d_project_float_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
706       *r_x = xyval[0];
707       *r_y = xyval[1];
708     }
709     else {
710       *r_x = 0.0f;
711       *r_y = 0.0f;
712     }
713   }
714   else if (gps->flag & GP_STROKE_2DSPACE) {
715     float vec[3] = {pt->x, pt->y, 0.0f};
716     int t_x, t_y;
717
718     mul_m4_v3(gsc->mat, vec);
719     UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y);
720
721     if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) {
722       /* XXX: Or should we just always use the values as-is? */
723       *r_x = 0.0f;
724       *r_y = 0.0f;
725     }
726     else {
727       *r_x = (float)t_x;
728       *r_y = (float)t_y;
729     }
730   }
731   else {
732     if (subrect == NULL) {
733       /* normal 3D view (or view space) */
734       *r_x = (pt->x / 100.0f * ar->winx);
735       *r_y = (pt->y / 100.0f * ar->winy);
736     }
737     else {
738       /* camera view, use subrect */
739       *r_x = ((pt->x / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
740       *r_y = ((pt->y / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
741     }
742   }
743 }
744
745 /**
746  * generic based on gp_point_to_xy_fl
747  */
748 void gp_point_3d_to_xy(const GP_SpaceConversion *gsc,
749                        const short flag,
750                        const float pt[3],
751                        float xy[2])
752 {
753   const ARegion *ar = gsc->ar;
754   const View2D *v2d = gsc->v2d;
755   const rctf *subrect = gsc->subrect;
756   float xyval[2];
757
758   /* sanity checks */
759   BLI_assert((gsc->sa->spacetype == SPACE_VIEW3D));
760
761   if (flag & GP_STROKE_3DSPACE) {
762     if (ED_view3d_project_float_global(ar, pt, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
763       xy[0] = xyval[0];
764       xy[1] = xyval[1];
765     }
766     else {
767       xy[0] = 0.0f;
768       xy[1] = 0.0f;
769     }
770   }
771   else if (flag & GP_STROKE_2DSPACE) {
772     float vec[3] = {pt[0], pt[1], 0.0f};
773     int t_x, t_y;
774
775     mul_m4_v3(gsc->mat, vec);
776     UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y);
777
778     if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) {
779       /* XXX: Or should we just always use the values as-is? */
780       xy[0] = 0.0f;
781       xy[1] = 0.0f;
782     }
783     else {
784       xy[0] = (float)t_x;
785       xy[1] = (float)t_y;
786     }
787   }
788   else {
789     if (subrect == NULL) {
790       /* normal 3D view (or view space) */
791       xy[0] = (pt[0] / 100.0f * ar->winx);
792       xy[1] = (pt[1] / 100.0f * ar->winy);
793     }
794     else {
795       /* camera view, use subrect */
796       xy[0] = ((pt[0] / 100.0f) * BLI_rctf_size_x(subrect)) + subrect->xmin;
797       xy[1] = ((pt[1] / 100.0f) * BLI_rctf_size_y(subrect)) + subrect->ymin;
798     }
799   }
800 }
801
802 /**
803  * Project screenspace coordinates to 3D-space
804  *
805  * For use with editing tools where it is easier to perform the operations in 2D,
806  * and then later convert the transformed points back to 3D.
807  *
808  * \param screen_co: The screenspace 2D coordinates to convert to
809  * \param r_out: The resulting 3D coordinates of the input point
810  *
811  * \note We include this as a utility function, since the standard method
812  * involves quite a few steps, which are invariably always the same
813  * for all GPencil operations. So, it's nicer to just centralize these.
814  *
815  * \warning Assumes that it is getting called in a 3D view only.
816  */
817 bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc,
818                        Scene *scene,
819                        const float screen_co[2],
820                        float r_out[3])
821 {
822   const RegionView3D *rv3d = gsc->ar->regiondata;
823   float rvec[3];
824
825   ED_gp_get_drawing_reference(
826       scene, gsc->ob, gsc->gpl, scene->toolsettings->gpencil_v3d_align, rvec);
827
828   float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL);
829
830   float mval_f[2], mval_prj[2];
831   float dvec[3];
832
833   copy_v2_v2(mval_f, screen_co);
834
835   if (ED_view3d_project_float_global(gsc->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) ==
836       V3D_PROJ_RET_OK) {
837     sub_v2_v2v2(mval_f, mval_prj, mval_f);
838     ED_view3d_win_to_delta(gsc->ar, mval_f, dvec, zfac);
839     sub_v3_v3v3(r_out, rvec, dvec);
840
841     return true;
842   }
843   else {
844     zero_v3(r_out);
845
846     return false;
847   }
848 }
849
850 /**
851  * Convert tGPspoint (temporary 2D/screenspace point data used by GP modal operators)
852  * to 3D coordinates.
853  *
854  * \param point2D: The screenspace 2D point data to convert.
855  * \param depth: Depth array (via #ED_view3d_autodist_depth()).
856  * \param[out] r_out: The resulting 2D point data.
857  */
858 void gp_stroke_convertcoords_tpoint(Scene *scene,
859                                     ARegion *ar,
860                                     Object *ob,
861                                     bGPDlayer *gpl,
862                                     const tGPspoint *point2D,
863                                     float *depth,
864                                     float r_out[3])
865 {
866   ToolSettings *ts = scene->toolsettings;
867
868   int mval_i[2];
869   round_v2i_v2fl(mval_i, &point2D->x);
870
871   if ((depth != NULL) && (ED_view3d_autodist_simple(ar, mval_i, r_out, 0, depth))) {
872     /* projecting onto 3D-Geometry
873      * - nothing more needs to be done here, since view_autodist_simple() has already done it
874      */
875   }
876   else {
877     float mval_f[2] = {point2D->x, point2D->y};
878     float mval_prj[2];
879     float rvec[3], dvec[3];
880     float zfac;
881
882     /* Current method just converts each point in screen-coordinates to
883      * 3D-coordinates using the 3D-cursor as reference.
884      */
885     ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, rvec);
886     zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL);
887
888     if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
889       sub_v2_v2v2(mval_f, mval_prj, mval_f);
890       ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
891       sub_v3_v3v3(r_out, rvec, dvec);
892     }
893     else {
894       zero_v3(r_out);
895     }
896   }
897 }
898
899 /**
900  * Get drawing reference point for conversion or projection of the stroke
901  * \param[out] r_vec : Reference point found
902  */
903 void ED_gp_get_drawing_reference(
904     const Scene *scene, const Object *ob, bGPDlayer *UNUSED(gpl), char align_flag, float r_vec[3])
905 {
906   const float *fp = scene->cursor.location;
907
908   /* if using a gpencil object at cursor mode, can use the location of the object */
909   if (align_flag & GP_PROJECT_VIEWSPACE) {
910     if (ob && (ob->type == OB_GPENCIL)) {
911       /* fallback (no strokes) - use cursor or object location */
912       if (align_flag & GP_PROJECT_CURSOR) {
913         /* use 3D-cursor */
914         copy_v3_v3(r_vec, fp);
915       }
916       else {
917         /* use object location */
918         copy_v3_v3(r_vec, ob->obmat[3]);
919       }
920     }
921   }
922   else {
923     /* use 3D-cursor */
924     copy_v3_v3(r_vec, fp);
925   }
926 }
927
928 void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke *gps)
929 {
930   Scene *scene = CTX_data_scene(C);
931   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
932   Object *ob = CTX_data_active_object(C);
933   bGPdata *gpd = (bGPdata *)ob->data;
934   GP_SpaceConversion gsc = {NULL};
935
936   bGPDspoint *pt;
937   int i;
938   float diff_mat[4][4];
939   float inverse_diff_mat[4][4];
940
941   /* init space conversion stuff */
942   gp_point_conversion_init(C, &gsc);
943
944   ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat);
945   invert_m4_m4(inverse_diff_mat, diff_mat);
946
947   /* Adjust each point */
948   for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
949     float xy[2];
950
951     bGPDspoint pt2;
952     gp_point_to_parent_space(pt, diff_mat, &pt2);
953     gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]);
954
955     /* Planar - All on same plane parallel to the viewplane */
956     gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
957
958     /* Unapply parent corrections */
959     mul_m4_v3(inverse_diff_mat, &pt->x);
960   }
961 }
962
963 /**
964  * Reproject all points of the stroke to a plane locked to axis to avoid stroke offset
965  */
966 void ED_gp_project_stroke_to_plane(const Scene *scene,
967                                    const Object *ob,
968                                    const RegionView3D *rv3d,
969                                    bGPDstroke *gps,
970                                    const float origin[3],
971                                    const int axis)
972 {
973   const ToolSettings *ts = scene->toolsettings;
974   const View3DCursor *cursor = &scene->cursor;
975   float plane_normal[3];
976   float vn[3];
977
978   float ray[3];
979   float rpoint[3];
980
981   /* normal vector for a plane locked to axis */
982   zero_v3(plane_normal);
983   if (axis < 0) {
984     /* if the axis is not locked, need a vector to the view direction
985      * in order to get the right size of the stroke.
986      */
987     ED_view3d_global_to_vector(rv3d, origin, plane_normal);
988   }
989   else if (axis < 3) {
990     plane_normal[axis] = 1.0f;
991     /* if object, apply object rotation */
992     if (ob && (ob->type == OB_GPENCIL)) {
993       float mat[4][4];
994       copy_m4_m4(mat, ob->obmat);
995
996       /* move origin to cursor */
997       if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
998         copy_v3_v3(mat[3], cursor->location);
999       }
1000
1001       mul_mat3_m4_v3(mat, plane_normal);
1002     }
1003   }
1004   else {
1005     float scale[3] = {1.0f, 1.0f, 1.0f};
1006     plane_normal[2] = 1.0f;
1007     float mat[4][4];
1008     loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, scale);
1009
1010     /* move origin to object */
1011     if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
1012       copy_v3_v3(mat[3], ob->obmat[3]);
1013     }
1014
1015     mul_mat3_m4_v3(mat, plane_normal);
1016   }
1017
1018   /* Reproject the points in the plane */
1019   for (int i = 0; i < gps->totpoints; i++) {
1020     bGPDspoint *pt = &gps->points[i];
1021
1022     /* get a vector from the point with the current view direction of the viewport */
1023     ED_view3d_global_to_vector(rv3d, &pt->x, vn);
1024
1025     /* calculate line extreme point to create a ray that cross the plane */
1026     mul_v3_fl(vn, -50.0f);
1027     add_v3_v3v3(ray, &pt->x, vn);
1028
1029     /* if the line never intersect, the point is not changed */
1030     if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
1031       copy_v3_v3(&pt->x, rpoint);
1032     }
1033   }
1034 }
1035
1036 /**
1037  * Reproject given point to a plane locked to axis to avoid stroke offset
1038  * \param[in,out] pt: Point to affect
1039  */
1040 void ED_gp_project_point_to_plane(const Scene *scene,
1041                                   const Object *ob,
1042                                   const RegionView3D *rv3d,
1043                                   const float origin[3],
1044                                   const int axis,
1045                                   bGPDspoint *pt)
1046 {
1047   const ToolSettings *ts = scene->toolsettings;
1048   const View3DCursor *cursor = &scene->cursor;
1049   float plane_normal[3];
1050   float vn[3];
1051
1052   float ray[3];
1053   float rpoint[3];
1054
1055   /* normal vector for a plane locked to axis */
1056   zero_v3(plane_normal);
1057   if (axis < 0) {
1058     /* if the axis is not locked, need a vector to the view direction
1059      * in order to get the right size of the stroke.
1060      */
1061     ED_view3d_global_to_vector(rv3d, origin, plane_normal);
1062   }
1063   else if (axis < 3) {
1064     plane_normal[axis] = 1.0f;
1065     /* if object, apply object rotation */
1066     if (ob && (ob->type == OB_GPENCIL)) {
1067       float mat[4][4];
1068       copy_m4_m4(mat, ob->obmat);
1069
1070       /* move origin to cursor */
1071       if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) {
1072         copy_v3_v3(mat[3], cursor->location);
1073       }
1074
1075       mul_mat3_m4_v3(mat, plane_normal);
1076     }
1077   }
1078   else {
1079     float scale[3] = {1.0f, 1.0f, 1.0f};
1080     plane_normal[2] = 1.0f;
1081     float mat[4][4];
1082     loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, scale);
1083
1084     /* move origin to object */
1085     if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) {
1086       copy_v3_v3(mat[3], ob->obmat[3]);
1087     }
1088
1089     mul_mat3_m4_v3(mat, plane_normal);
1090   }
1091
1092   /* Reproject the points in the plane */
1093   /* get a vector from the point with the current view direction of the viewport */
1094   ED_view3d_global_to_vector(rv3d, &pt->x, vn);
1095
1096   /* calculate line extrem point to create a ray that cross the plane */
1097   mul_v3_fl(vn, -50.0f);
1098   add_v3_v3v3(ray, &pt->x, vn);
1099
1100   /* if the line never intersect, the point is not changed */
1101   if (isect_line_plane_v3(rpoint, &pt->x, ray, origin, plane_normal)) {
1102     copy_v3_v3(&pt->x, rpoint);
1103   }
1104 }
1105
1106 /* ******************************************************** */
1107 /* Stroke Operations */
1108
1109 /* XXX: Check if these functions duplicate stuff in blenkernel,
1110  * and/or whether we should just deduplicate. */
1111
1112 /**
1113  * Subdivide a stroke once, by adding a point half way between each pair of existing points
1114  * \param gps: Stroke data
1115  * \param subdivide: Number of times to subdivide
1116  */
1117 void gp_subdivide_stroke(bGPDstroke *gps, const int subdivide)
1118 {
1119   bGPDspoint *temp_points;
1120   int totnewpoints, oldtotpoints;
1121   int i2;
1122
1123   /* loop as many times as levels */
1124   for (int s = 0; s < subdivide; s++) {
1125     totnewpoints = gps->totpoints - 1;
1126     /* duplicate points in a temp area */
1127     temp_points = MEM_dupallocN(gps->points);
1128     oldtotpoints = gps->totpoints;
1129
1130     /* resize the points arrays */
1131     gps->totpoints += totnewpoints;
1132     gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
1133     if (gps->dvert != NULL) {
1134       gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
1135     }
1136     gps->flag |= GP_STROKE_RECALC_GEOMETRY;
1137
1138     /* move points from last to first to new place */
1139     i2 = gps->totpoints - 1;
1140     for (int i = oldtotpoints - 1; i > 0; i--) {
1141       bGPDspoint *pt = &temp_points[i];
1142       bGPDspoint *pt_final = &gps->points[i2];
1143
1144       copy_v3_v3(&pt_final->x, &pt->x);
1145       pt_final->pressure = pt->pressure;
1146       pt_final->strength = pt->strength;
1147       pt_final->time = pt->time;
1148       pt_final->flag = pt->flag;
1149       pt_final->uv_fac = pt->uv_fac;
1150       pt_final->uv_rot = pt->uv_rot;
1151
1152       if (gps->dvert != NULL) {
1153         MDeformVert *dvert = &gps->dvert[i];
1154         MDeformVert *dvert_final = &gps->dvert[i2];
1155
1156         dvert_final->totweight = dvert->totweight;
1157         dvert_final->dw = dvert->dw;
1158       }
1159
1160       i2 -= 2;
1161     }
1162     /* interpolate mid points */
1163     i2 = 1;
1164     for (int i = 0; i < oldtotpoints - 1; i++) {
1165       bGPDspoint *pt = &temp_points[i];
1166       bGPDspoint *next = &temp_points[i + 1];
1167       bGPDspoint *pt_final = &gps->points[i2];
1168
1169       /* add a half way point */
1170       interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
1171       pt_final->pressure = interpf(pt->pressure, next->pressure, 0.5f);
1172       pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
1173       CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
1174       pt_final->time = interpf(pt->time, next->time, 0.5f);
1175       pt_final->uv_fac = interpf(pt->uv_fac, next->uv_fac, 0.5f);
1176       pt_final->uv_rot = interpf(pt->uv_rot, next->uv_rot, 0.5f);
1177
1178       if (gps->dvert != NULL) {
1179         MDeformVert *dvert_final = &gps->dvert[i2];
1180         dvert_final->totweight = 0;
1181         dvert_final->dw = NULL;
1182       }
1183
1184       i2 += 2;
1185     }
1186
1187     MEM_SAFE_FREE(temp_points);
1188
1189     /* move points to smooth stroke */
1190     /* duplicate points in a temp area with the new subdivide data */
1191     temp_points = MEM_dupallocN(gps->points);
1192
1193     /* extreme points are not changed */
1194     for (int i = 0; i < gps->totpoints - 2; i++) {
1195       bGPDspoint *pt = &temp_points[i];
1196       bGPDspoint *next = &temp_points[i + 1];
1197       bGPDspoint *pt_final = &gps->points[i + 1];
1198
1199       /* move point */
1200       interp_v3_v3v3(&pt_final->x, &pt->x, &next->x, 0.5f);
1201     }
1202     /* free temp memory */
1203     MEM_SAFE_FREE(temp_points);
1204   }
1205 }
1206
1207 /**
1208  * Add randomness to stroke
1209  * \param gps: Stroke data
1210  * \param brush: Brush data
1211  */
1212 void gp_randomize_stroke(bGPDstroke *gps, Brush *brush, RNG *rng)
1213 {
1214   bGPDspoint *pt1, *pt2, *pt3;
1215   float v1[3];
1216   float v2[3];
1217   if (gps->totpoints < 3) {
1218     return;
1219   }
1220
1221   /* get two vectors using 3 points */
1222   pt1 = &gps->points[0];
1223   pt2 = &gps->points[1];
1224   pt3 = &gps->points[(int)(gps->totpoints * 0.75)];
1225
1226   sub_v3_v3v3(v1, &pt2->x, &pt1->x);
1227   sub_v3_v3v3(v2, &pt3->x, &pt2->x);
1228   normalize_v3(v1);
1229   normalize_v3(v2);
1230
1231   /* get normal vector to plane created by two vectors */
1232   float normal[3];
1233   cross_v3_v3v3(normal, v1, v2);
1234   normalize_v3(normal);
1235
1236   /* get orthogonal vector to plane to rotate random effect */
1237   float ortho[3];
1238   cross_v3_v3v3(ortho, v1, normal);
1239   normalize_v3(ortho);
1240
1241   /* Read all points and apply shift vector (first and last point not modified) */
1242   for (int i = 1; i < gps->totpoints - 1; i++) {
1243     bGPDspoint *pt = &gps->points[i];
1244     /* get vector with shift (apply a division because random is too sensitive */
1245     const float fac = BLI_rng_get_float(rng) * (brush->gpencil_settings->draw_random_sub / 10.0f);
1246     float svec[3];
1247     copy_v3_v3(svec, ortho);
1248     if (BLI_rng_get_float(rng) > 0.5f) {
1249       mul_v3_fl(svec, -fac);
1250     }
1251     else {
1252       mul_v3_fl(svec, fac);
1253     }
1254
1255     /* apply shift */
1256     add_v3_v3(&pt->x, svec);
1257   }
1258 }
1259
1260 /* ******************************************************** */
1261 /* Layer Parenting  - Compute Parent Transforms */
1262
1263 /* calculate difference matrix */
1264 void ED_gpencil_parent_location(const Depsgraph *depsgraph,
1265                                 Object *obact,
1266                                 bGPdata *UNUSED(gpd),
1267                                 bGPDlayer *gpl,
1268                                 float diff_mat[4][4])
1269 {
1270   Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact;
1271   Object *obparent = gpl->parent;
1272   Object *obparent_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obparent) :
1273                                               obparent;
1274
1275   /* if not layer parented, try with object parented */
1276   if (obparent_eval == NULL) {
1277     if (ob_eval != NULL) {
1278       if (ob_eval->type == OB_GPENCIL) {
1279         copy_m4_m4(diff_mat, ob_eval->obmat);
1280         return;
1281       }
1282     }
1283     /* not gpencil object */
1284     unit_m4(diff_mat);
1285     return;
1286   }
1287   else {
1288     if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
1289       mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
1290       add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
1291       return;
1292     }
1293     else if (gpl->partype == PARBONE) {
1294       bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr);
1295       if (pchan) {
1296         float tmp_mat[4][4];
1297         mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat);
1298         mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse);
1299         add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
1300       }
1301       else {
1302         /* if bone not found use object (armature) */
1303         mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
1304         add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
1305       }
1306       return;
1307     }
1308     else {
1309       unit_m4(diff_mat); /* not defined type */
1310     }
1311   }
1312 }
1313
1314 /* reset parent matrix for all layers */
1315 void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata *gpd)
1316 {
1317   bGPDspoint *pt;
1318   int i;
1319   float diff_mat[4][4];
1320   float cur_mat[4][4];
1321   float gpl_loc[3];
1322   zero_v3(gpl_loc);
1323
1324   for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1325     if (gpl->parent != NULL) {
1326       /* calculate new matrix */
1327       if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
1328         invert_m4_m4(cur_mat, gpl->parent->obmat);
1329         copy_v3_v3(gpl_loc, obact->obmat[3]);
1330       }
1331       else if (gpl->partype == PARBONE) {
1332         bPoseChannel *pchan = BKE_pose_channel_find_name(gpl->parent->pose, gpl->parsubstr);
1333         if (pchan) {
1334           float tmp_mat[4][4];
1335           mul_m4_m4m4(tmp_mat, gpl->parent->obmat, pchan->pose_mat);
1336           invert_m4_m4(cur_mat, tmp_mat);
1337           copy_v3_v3(gpl_loc, obact->obmat[3]);
1338         }
1339       }
1340
1341       /* only redo if any change */
1342       if (!equals_m4m4(gpl->inverse, cur_mat)) {
1343         /* first apply current transformation to all strokes */
1344         ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat);
1345         /* undo local object */
1346         sub_v3_v3(diff_mat[3], gpl_loc);
1347
1348         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1349           for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1350             for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1351               mul_m4_v3(diff_mat, &pt->x);
1352             }
1353           }
1354         }
1355         /* set new parent matrix */
1356         copy_m4_m4(gpl->inverse, cur_mat);
1357       }
1358     }
1359   }
1360 }
1361 /* ******************************************************** */
1362 /* GP Object Stuff */
1363
1364 /* Helper function to create new OB_GPENCIL Object */
1365 Object *ED_gpencil_add_object(bContext *C,
1366                               Scene *UNUSED(scene),
1367                               const float loc[3],
1368                               ushort local_view_bits)
1369 {
1370   float rot[3] = {0.0f};
1371
1372   Object *ob = ED_object_add_type(C, OB_GPENCIL, NULL, loc, rot, false, local_view_bits);
1373
1374   /* create default brushes and colors */
1375   ED_gpencil_add_defaults(C, ob);
1376
1377   return ob;
1378 }
1379
1380 /* Helper function to create default colors and drawing brushes */
1381 void ED_gpencil_add_defaults(bContext *C, Object *ob)
1382 {
1383   Main *bmain = CTX_data_main(C);
1384   ToolSettings *ts = CTX_data_tool_settings(C);
1385
1386   BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
1387   Paint *paint = &ts->gp_paint->paint;
1388   /* if not exist, create a new one */
1389   if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
1390     /* create new brushes */
1391     BKE_brush_gpencil_presets(C);
1392   }
1393
1394   /* ensure a color exists and is assigned to object */
1395   BKE_gpencil_object_material_ensure_from_active_input_toolsettings(bmain, ob, ts);
1396
1397   /* ensure multiframe falloff curve */
1398   if (ts->gp_sculpt.cur_falloff == NULL) {
1399     ts->gp_sculpt.cur_falloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
1400     CurveMapping *gp_falloff_curve = ts->gp_sculpt.cur_falloff;
1401     curvemapping_initialize(gp_falloff_curve);
1402     curvemap_reset(gp_falloff_curve->cm,
1403                    &gp_falloff_curve->clipr,
1404                    CURVE_PRESET_GAUSS,
1405                    CURVEMAP_SLOPE_POSITIVE);
1406   }
1407 }
1408
1409 /* ******************************************************** */
1410 /* Vertex Groups */
1411
1412 /* assign points to vertex group */
1413 void ED_gpencil_vgroup_assign(bContext *C, Object *ob, float weight)
1414 {
1415   bGPdata *gpd = (bGPdata *)ob->data;
1416   const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
1417   const int def_nr = ob->actdef - 1;
1418   if (!BLI_findlink(&ob->defbase, def_nr)) {
1419     return;
1420   }
1421
1422   CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
1423     bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
1424     bGPDstroke *gps = NULL;
1425
1426     for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
1427       if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
1428         if (gpf == NULL) {
1429           continue;
1430         }
1431
1432         for (gps = gpf->strokes.first; gps; gps = gps->next) {
1433
1434           /* skip strokes that are invalid for current view */
1435           if (ED_gpencil_stroke_can_use(C, gps) == false) {
1436             continue;
1437           }
1438
1439           if (gps->flag & GP_STROKE_SELECT) {
1440             /* verify the weight array is created */
1441             BKE_gpencil_dvert_ensure(gps);
1442
1443             for (int i = 0; i < gps->totpoints; i++) {
1444               bGPDspoint *pt = &gps->points[i];
1445               MDeformVert *dvert = &gps->dvert[i];
1446               if (pt->flag & GP_SPOINT_SELECT) {
1447                 MDeformWeight *dw = defvert_verify_index(dvert, def_nr);
1448                 if (dw) {
1449                   dw->weight = weight;
1450                 }
1451               }
1452             }
1453           }
1454         }
1455       }
1456
1457       /* if not multiedit, exit loop*/
1458       if (!is_multiedit) {
1459         break;
1460       }
1461     }
1462   }
1463   CTX_DATA_END;
1464 }
1465
1466 /* remove points from vertex group */
1467 void ED_gpencil_vgroup_remove(bContext *C, Object *ob)
1468 {
1469   bGPdata *gpd = (bGPdata *)ob->data;
1470   const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
1471   const int def_nr = ob->actdef - 1;
1472   if (!BLI_findlink(&ob->defbase, def_nr)) {
1473     return;
1474   }
1475
1476   CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
1477     bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
1478     bGPDstroke *gps = NULL;
1479
1480     for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
1481       if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
1482         if (gpf == NULL) {
1483           continue;
1484         }
1485
1486         for (gps = gpf->strokes.first; gps; gps = gps->next) {
1487
1488           /* skip strokes that are invalid for current view */
1489           if (ED_gpencil_stroke_can_use(C, gps) == false) {
1490             continue;
1491           }
1492
1493           for (int i = 0; i < gps->totpoints; i++) {
1494             bGPDspoint *pt = &gps->points[i];
1495             if (gps->dvert == NULL) {
1496               continue;
1497             }
1498             MDeformVert *dvert = &gps->dvert[i];
1499
1500             if ((pt->flag & GP_SPOINT_SELECT) && (dvert->totweight > 0)) {
1501               MDeformWeight *dw = defvert_find_index(dvert, def_nr);
1502               if (dw != NULL) {
1503                 defvert_remove_group(dvert, dw);
1504               }
1505             }
1506           }
1507         }
1508       }
1509
1510       /* if not multiedit, exit loop*/
1511       if (!is_multiedit) {
1512         break;
1513       }
1514     }
1515   }
1516   CTX_DATA_END;
1517 }
1518
1519 /* select points of vertex group */
1520 void ED_gpencil_vgroup_select(bContext *C, Object *ob)
1521 {
1522   bGPdata *gpd = (bGPdata *)ob->data;
1523   const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
1524   const int def_nr = ob->actdef - 1;
1525   if (!BLI_findlink(&ob->defbase, def_nr)) {
1526     return;
1527   }
1528
1529   CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
1530     bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
1531     bGPDstroke *gps = NULL;
1532
1533     for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
1534       if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
1535         if (gpf == NULL) {
1536           continue;
1537         }
1538
1539         for (gps = gpf->strokes.first; gps; gps = gps->next) {
1540
1541           /* skip strokes that are invalid for current view */
1542           if (ED_gpencil_stroke_can_use(C, gps) == false) {
1543             continue;
1544           }
1545
1546           for (int i = 0; i < gps->totpoints; i++) {
1547             bGPDspoint *pt = &gps->points[i];
1548             if (gps->dvert == NULL) {
1549               continue;
1550             }
1551             MDeformVert *dvert = &gps->dvert[i];
1552
1553             if (defvert_find_index(dvert, def_nr) != NULL) {
1554               pt->flag |= GP_SPOINT_SELECT;
1555               gps->flag |= GP_STROKE_SELECT;
1556             }
1557           }
1558         }
1559       }
1560
1561       /* if not multiedit, exit loop*/
1562       if (!is_multiedit) {
1563         break;
1564       }
1565     }
1566   }
1567   CTX_DATA_END;
1568 }
1569
1570 /* unselect points of vertex group */
1571 void ED_gpencil_vgroup_deselect(bContext *C, Object *ob)
1572 {
1573   bGPdata *gpd = (bGPdata *)ob->data;
1574   const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
1575   const int def_nr = ob->actdef - 1;
1576   if (!BLI_findlink(&ob->defbase, def_nr)) {
1577     return;
1578   }
1579
1580   CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
1581     bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
1582     bGPDstroke *gps = NULL;
1583
1584     for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
1585       if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
1586         if (gpf == NULL) {
1587           continue;
1588         }
1589
1590         for (gps = gpf->strokes.first; gps; gps = gps->next) {
1591
1592           /* skip strokes that are invalid for current view */
1593           if (ED_gpencil_stroke_can_use(C, gps) == false) {
1594             continue;
1595           }
1596
1597           for (int i = 0; i < gps->totpoints; i++) {
1598             bGPDspoint *pt = &gps->points[i];
1599             if (gps->dvert == NULL) {
1600               continue;
1601             }
1602             MDeformVert *dvert = &gps->dvert[i];
1603
1604             if (defvert_find_index(dvert, def_nr) != NULL) {
1605               pt->flag &= ~GP_SPOINT_SELECT;
1606             }
1607           }
1608         }
1609       }
1610
1611       /* if not multiedit, exit loop*/
1612       if (!is_multiedit) {
1613         break;
1614       }
1615     }
1616   }
1617   CTX_DATA_END;
1618 }
1619
1620 /* ******************************************************** */
1621 /* Cursor drawing */
1622
1623 /* check if cursor is in drawing region */
1624 static bool gp_check_cursor_region(bContext *C, int mval_i[2])
1625 {
1626   ARegion *ar = CTX_wm_region(C);
1627   ScrArea *sa = CTX_wm_area(C);
1628   Object *ob = CTX_data_active_object(C);
1629
1630   if ((ob == NULL) ||
1631       (!ELEM(ob->mode, OB_MODE_PAINT_GPENCIL, OB_MODE_SCULPT_GPENCIL, OB_MODE_WEIGHT_GPENCIL))) {
1632     return false;
1633   }
1634
1635   /* TODO: add more spacetypes */
1636   if (!ELEM(sa->spacetype, SPACE_VIEW3D)) {
1637     return false;
1638   }
1639   if ((ar) && (ar->regiontype != RGN_TYPE_WINDOW)) {
1640     return false;
1641   }
1642   else if (ar) {
1643     return BLI_rcti_isect_pt_v(&ar->winrct, mval_i);
1644   }
1645   else {
1646     return false;
1647   }
1648 }
1649
1650 /* draw eraser cursor */
1651 void ED_gpencil_brush_draw_eraser(Brush *brush, int x, int y)
1652 {
1653   short radius = (short)brush->size;
1654
1655   GPUVertFormat *format = immVertexFormat();
1656   const uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1657   immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1658
1659   GPU_line_smooth(true);
1660   GPU_blend(true);
1661   glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1662
1663   immUniformColor4ub(255, 100, 100, 20);
1664   imm_draw_circle_fill_2d(shdr_pos, x, y, radius, 40);
1665
1666   immUnbindProgram();
1667
1668   immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
1669
1670   float viewport_size[4];
1671   glGetFloatv(GL_VIEWPORT, viewport_size);
1672   immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
1673
1674   immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
1675   immUniform1i("colors_len", 0); /* "simple" mode */
1676   immUniform1f("dash_width", 12.0f);
1677   immUniform1f("dash_factor", 0.5f);
1678
1679   imm_draw_circle_wire_2d(shdr_pos,
1680                           x,
1681                           y,
1682                           radius,
1683                           /* XXX Dashed shader gives bad results with sets of small segments
1684                            * currently, temp hack around the issue. :( */
1685                           max_ii(8, radius / 2)); /* was fixed 40 */
1686
1687   immUnbindProgram();
1688
1689   GPU_blend(false);
1690   GPU_line_smooth(false);
1691 }
1692
1693 static bool gp_brush_cursor_poll(bContext *C)
1694 {
1695   if (WM_toolsystem_active_tool_is_brush(C)) {
1696     return true;
1697   }
1698   return false;
1699 }
1700
1701 /* Helper callback for drawing the cursor itself */
1702 static void gp_brush_cursor_draw(bContext *C, int x, int y, void *customdata)
1703 {
1704   Scene *scene = CTX_data_scene(C);
1705   Object *ob = CTX_data_active_object(C);
1706   ARegion *ar = CTX_wm_region(C);
1707
1708   GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
1709   bGPdata *gpd = ED_gpencil_data_get_active(C);
1710   GP_Sculpt_Data *gp_brush = NULL;
1711   Brush *brush = NULL;
1712   Material *ma = NULL;
1713   MaterialGPencilStyle *gp_style = NULL;
1714   float *last_mouse_position = customdata;
1715
1716   if ((gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE)) {
1717     gp_brush = &gset->brush[gset->weighttype];
1718   }
1719   else {
1720     gp_brush = &gset->brush[gset->brushtype];
1721   }
1722
1723   /* default radius and color */
1724   float color[3] = {1.0f, 1.0f, 1.0f};
1725   float darkcolor[3];
1726   float radius = 3.0f;
1727
1728   int mval_i[2] = {x, y};
1729   /* check if cursor is in drawing region and has valid datablock */
1730   if ((!gp_check_cursor_region(C, mval_i)) || (gpd == NULL)) {
1731     return;
1732   }
1733
1734   /* for paint use paint brush size and color */
1735   if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
1736     brush = scene->toolsettings->gp_paint->paint.brush;
1737     if ((brush == NULL) || (brush->gpencil_settings == NULL)) {
1738       return;
1739     }
1740
1741     /* while drawing hide */
1742     if ((gpd->runtime.sbuffer_used > 0) &&
1743         ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
1744         ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0)) {
1745       return;
1746     }
1747
1748     if ((brush->gpencil_settings->flag & GP_BRUSH_ENABLE_CURSOR) == 0) {
1749       return;
1750     }
1751
1752     /* eraser has special shape and use a different shader program */
1753     if (brush->gpencil_tool == GPAINT_TOOL_ERASE) {
1754       ED_gpencil_brush_draw_eraser(brush, x, y);
1755       return;
1756     }
1757
1758     /* get current drawing color */
1759     ma = BKE_gpencil_object_material_get_from_brush(ob, brush);
1760
1761     if (ma) {
1762       gp_style = ma->gp_style;
1763
1764       /* after some testing, display the size of the brush is not practical because
1765        * is too disruptive and the size of cursor does not change with zoom factor.
1766        * The decision was to use a fix size, instead of brush->thickness value.
1767        */
1768       if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) &&
1769           ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
1770           ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) &&
1771           (brush->gpencil_tool == GPAINT_TOOL_DRAW)) {
1772         radius = 2.0f;
1773         copy_v3_v3(color, gp_style->stroke_rgba);
1774       }
1775       else {
1776         radius = 5.0f;
1777         copy_v3_v3(color, brush->add_col);
1778       }
1779     }
1780   }
1781
1782   /* for sculpt use sculpt brush size */
1783   if (GPENCIL_SCULPT_OR_WEIGHT_MODE(gpd)) {
1784     if (gp_brush) {
1785       if ((gp_brush->flag & GP_SCULPT_FLAG_ENABLE_CURSOR) == 0) {
1786         return;
1787       }
1788
1789       radius = gp_brush->size;
1790       if (gp_brush->flag & (GP_SCULPT_FLAG_INVERT | GP_SCULPT_FLAG_TMP_INVERT)) {
1791         copy_v3_v3(color, gp_brush->curcolor_sub);
1792       }
1793       else {
1794         copy_v3_v3(color, gp_brush->curcolor_add);
1795       }
1796     }
1797   }
1798
1799   /* draw icon */
1800   GPUVertFormat *format = immVertexFormat();
1801   uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1802   immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
1803
1804   GPU_line_smooth(true);
1805   GPU_blend(true);
1806
1807   /* Inner Ring: Color from UI panel */
1808   immUniformColor4f(color[0], color[1], color[2], 0.8f);
1809   if ((gp_style) && (GPENCIL_PAINT_MODE(gpd)) &&
1810       ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE) == 0) &&
1811       ((brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) == 0) &&
1812       (brush->gpencil_tool == GPAINT_TOOL_DRAW)) {
1813     imm_draw_circle_fill_2d(pos, x, y, radius, 40);
1814   }
1815   else {
1816     imm_draw_circle_wire_2d(pos, x, y, radius, 40);
1817   }
1818
1819   /* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */
1820   mul_v3_v3fl(darkcolor, color, 0.40f);
1821   immUniformColor4f(darkcolor[0], darkcolor[1], darkcolor[2], 0.8f);
1822   imm_draw_circle_wire_2d(pos, x, y, radius + 1, 40);
1823
1824   GPU_blend(false);
1825   GPU_line_smooth(false);
1826
1827   /* Draw line for lazy mouse */
1828   if ((last_mouse_position) && (brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP)) {
1829     GPU_line_smooth(true);
1830     GPU_blend(true);
1831
1832     copy_v3_v3(color, brush->add_col);
1833     immUniformColor4f(color[0], color[1], color[2], 0.8f);
1834
1835     immBegin(GPU_PRIM_LINES, 2);
1836     immVertex2f(pos, x, y);
1837     immVertex2f(
1838         pos, last_mouse_position[0] + ar->winrct.xmin, last_mouse_position[1] + ar->winrct.ymin);
1839     immEnd();
1840
1841     GPU_blend(false);
1842     GPU_line_smooth(false);
1843   }
1844
1845   immUnbindProgram();
1846 }
1847
1848 /* Turn brush cursor in on/off */
1849 void ED_gpencil_toggle_brush_cursor(bContext *C, bool enable, void *customdata)
1850 {
1851   Scene *scene = CTX_data_scene(C);
1852   GP_Sculpt_Settings *gset = &scene->toolsettings->gp_sculpt;
1853   float *lastpost = customdata;
1854
1855   if (gset->paintcursor && !enable) {
1856     /* clear cursor */
1857     WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
1858     gset->paintcursor = NULL;
1859   }
1860   else if (enable) {
1861     /* in some situations cursor could be duplicated, so it is better disable first if exist */
1862     if (gset->paintcursor) {
1863       /* clear cursor */
1864       WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
1865       gset->paintcursor = NULL;
1866     }
1867     /* enable cursor */
1868     gset->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C),
1869                                                  SPACE_TYPE_ANY,
1870                                                  RGN_TYPE_ANY,
1871                                                  gp_brush_cursor_poll,
1872                                                  gp_brush_cursor_draw,
1873                                                  (lastpost) ? customdata : NULL);
1874   }
1875 }
1876
1877 /* verify if is using the right brush */
1878 static void gpencil_verify_brush_type(bContext *C, int newmode)
1879 {
1880   ToolSettings *ts = CTX_data_tool_settings(C);
1881   GP_Sculpt_Settings *gset = &ts->gp_sculpt;
1882
1883   switch (newmode) {
1884     case OB_MODE_SCULPT_GPENCIL:
1885       gset->flag &= ~GP_SCULPT_SETT_FLAG_WEIGHT_MODE;
1886       if ((gset->brushtype < 0) || (gset->brushtype >= GP_SCULPT_TYPE_WEIGHT)) {
1887         gset->brushtype = GP_SCULPT_TYPE_PUSH;
1888       }
1889       break;
1890     case OB_MODE_WEIGHT_GPENCIL:
1891       gset->flag |= GP_SCULPT_SETT_FLAG_WEIGHT_MODE;
1892       if ((gset->weighttype < GP_SCULPT_TYPE_WEIGHT) || (gset->weighttype >= GP_SCULPT_TYPE_MAX)) {
1893         gset->weighttype = GP_SCULPT_TYPE_WEIGHT;
1894       }
1895       break;
1896     default:
1897       break;
1898   }
1899 }
1900
1901 /* set object modes */
1902 void ED_gpencil_setup_modes(bContext *C, bGPdata *gpd, int newmode)
1903 {
1904   if (!gpd) {
1905     return;
1906   }
1907
1908   switch (newmode) {
1909     case OB_MODE_EDIT_GPENCIL:
1910       gpd->flag |= GP_DATA_STROKE_EDITMODE;
1911       gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
1912       gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
1913       gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
1914       ED_gpencil_toggle_brush_cursor(C, false, NULL);
1915       break;
1916     case OB_MODE_PAINT_GPENCIL:
1917       gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
1918       gpd->flag |= GP_DATA_STROKE_PAINTMODE;
1919       gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
1920       gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
1921       ED_gpencil_toggle_brush_cursor(C, true, NULL);
1922       break;
1923     case OB_MODE_SCULPT_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       gpencil_verify_brush_type(C, OB_MODE_SCULPT_GPENCIL);
1929       ED_gpencil_toggle_brush_cursor(C, true, NULL);
1930       break;
1931     case OB_MODE_WEIGHT_GPENCIL:
1932       gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
1933       gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
1934       gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
1935       gpd->flag |= GP_DATA_STROKE_WEIGHTMODE;
1936       gpencil_verify_brush_type(C, OB_MODE_WEIGHT_GPENCIL);
1937       ED_gpencil_toggle_brush_cursor(C, true, NULL);
1938       break;
1939     default:
1940       gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
1941       gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
1942       gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
1943       gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
1944       ED_gpencil_toggle_brush_cursor(C, false, NULL);
1945       break;
1946   }
1947 }
1948
1949 /* helper to convert 2d to 3d for simple drawing buffer */
1950 static void gpencil_stroke_convertcoords(ARegion *ar,
1951                                          const tGPspoint *point2D,
1952                                          float origin[3],
1953                                          float out[3])
1954 {
1955   float mval_f[2] = {(float)point2D->x, (float)point2D->y};
1956   float mval_prj[2];
1957   float rvec[3], dvec[3];
1958   float zfac;
1959
1960   copy_v3_v3(rvec, origin);
1961
1962   zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL);
1963
1964   if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
1965     sub_v2_v2v2(mval_f, mval_prj, mval_f);
1966     ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
1967     sub_v3_v3v3(out, rvec, dvec);
1968   }
1969   else {
1970     zero_v3(out);
1971   }
1972 }
1973
1974 /* convert 2d tGPspoint to 3d bGPDspoint */
1975 void ED_gpencil_tpoint_to_point(ARegion *ar, float origin[3], const tGPspoint *tpt, bGPDspoint *pt)
1976 {
1977   float p3d[3];
1978   /* conversion to 3d format */
1979   gpencil_stroke_convertcoords(ar, tpt, origin, p3d);
1980   copy_v3_v3(&pt->x, p3d);
1981
1982   pt->pressure = tpt->pressure;
1983   pt->strength = tpt->strength;
1984   pt->uv_fac = tpt->uv_fac;
1985   pt->uv_rot = tpt->uv_rot;
1986 }
1987
1988 /* texture coordinate utilities */
1989 void ED_gpencil_calc_stroke_uv(Object *ob, bGPDstroke *gps)
1990 {
1991   if (gps == NULL) {
1992     return;
1993   }
1994   MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
1995   float pixsize;
1996   if (gp_style) {
1997     pixsize = gp_style->texture_pixsize / 1000000.0f;
1998   }
1999   else {
2000     /* use this value by default */
2001     pixsize = 0.0001f;
2002   }
2003   pixsize = MAX2(pixsize, 0.0000001f);
2004
2005   bGPDspoint *pt = NULL;
2006   bGPDspoint *ptb = NULL;
2007   int i;
2008   float totlen = 0.0f;
2009
2010   /* first read all points and calc distance */
2011   for (i = 0; i < gps->totpoints; i++) {
2012     pt = &gps->points[i];
2013     /* first point */
2014     if (i == 0) {
2015       pt->uv_fac = 0.0f;
2016       continue;
2017     }
2018
2019     ptb = &gps->points[i - 1];
2020     totlen += len_v3v3(&pt->x, &ptb->x) / pixsize;
2021     pt->uv_fac = totlen;
2022   }
2023
2024   /* normalize the distance using a factor */
2025   float factor;
2026
2027   /* if image, use texture width */
2028   if ((gp_style) && (gp_style->stroke_style == GP_STYLE_STROKE_STYLE_TEXTURE) &&
2029       (gp_style->sima)) {
2030     factor = gp_style->sima->gen_x;
2031   }
2032   else if (totlen == 0) {
2033     return;
2034   }
2035   else {
2036     factor = totlen;
2037   }
2038
2039   for (i = 0; i < gps->totpoints; i++) {
2040     pt = &gps->points[i];
2041     pt->uv_fac /= factor;
2042   }
2043 }
2044
2045 /* recalc uv for any stroke using the material */
2046 void ED_gpencil_update_color_uv(Main *bmain, Material *mat)
2047 {
2048   Material *gps_ma = NULL;
2049   /* read all strokes  */
2050   for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
2051     if (ob->type == OB_GPENCIL) {
2052       bGPdata *gpd = ob->data;
2053       if (gpd == NULL) {
2054         continue;
2055       }
2056
2057       for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
2058         /* only editable and visible layers are considered */
2059         if (gpencil_layer_is_editable(gpl)) {
2060           for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
2061             for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
2062               /* check if it is editable */
2063               if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
2064                 continue;
2065               }
2066               gps_ma = give_current_material(ob, gps->mat_nr + 1);
2067               /* update */
2068               if ((gps_ma) && (gps_ma == mat)) {
2069                 ED_gpencil_calc_stroke_uv(ob, gps);
2070               }
2071             }
2072           }
2073         }
2074       }
2075       DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
2076     }
2077   }
2078 }
2079
2080 static bool gpencil_check_collision(bGPDstroke *gps,
2081                                     bGPDstroke **gps_array,
2082                                     GHash *all_2d,
2083                                     int totstrokes,
2084                                     float p2d_a1[2],
2085                                     float p2d_a2[2],
2086                                     float r_hit[2])
2087 {
2088   bool hit = false;
2089   /* check segment with all segments of all strokes */
2090   for (int s = 0; s < totstrokes; s++) {
2091     bGPDstroke *gps_iter = gps_array[s];
2092     if (gps_iter->totpoints < 2) {
2093       continue;
2094     }
2095     /* get stroke 2d version */
2096     float(*points2d)[2] = BLI_ghash_lookup(all_2d, gps_iter);
2097
2098     for (int i2 = 0; i2 < gps_iter->totpoints - 1; i2++) {
2099       float p2d_b1[2], p2d_b2[2];
2100       copy_v2_v2(p2d_b1, points2d[i2]);
2101       copy_v2_v2(p2d_b2, points2d[i2 + 1]);
2102
2103       /* don't self check */
2104       if (gps == gps_iter) {
2105         if (equals_v2v2(p2d_a1, p2d_b1) || equals_v2v2(p2d_a1, p2d_b2)) {
2106           continue;
2107         }
2108         if (equals_v2v2(p2d_a2, p2d_b1) || equals_v2v2(p2d_a2, p2d_b2)) {
2109           continue;
2110         }
2111       }
2112       /* check collision */
2113       int check = isect_seg_seg_v2_point(p2d_a1, p2d_a2, p2d_b1, p2d_b2, r_hit);
2114       if (check > 0) {
2115         hit = true;
2116         break;
2117       }
2118     }
2119
2120     if (hit) {
2121       break;
2122     }
2123   }
2124
2125   if (!hit) {
2126     zero_v2(r_hit);
2127   }
2128
2129   return hit;
2130 }
2131
2132 static void gp_copy_points(bGPDstroke *gps, bGPDspoint *pt, bGPDspoint *pt_final, int i, int i2)
2133 {
2134   /* don't copy same point */
2135   if (i == i2) {
2136     return;
2137   }
2138
2139   copy_v3_v3(&pt_final->x, &pt->x);
2140   pt_final->pressure = pt->pressure;
2141   pt_final->strength = pt->strength;
2142   pt_final->time = pt->time;
2143   pt_final->flag = pt->flag;
2144   pt_final->uv_fac = pt->uv_fac;
2145   pt_final->uv_rot = pt->uv_rot;
2146
2147   if (gps->dvert != NULL) {
2148     MDeformVert *dvert = &gps->dvert[i];
2149     MDeformVert *dvert_final = &gps->dvert[i2];
2150     MEM_SAFE_FREE(dvert_final->dw);
2151
2152     dvert_final->totweight = dvert->totweight;
2153     if (dvert->dw == NULL) {
2154       dvert_final->dw = NULL;
2155       dvert_final->totweight = 0;
2156     }
2157     else {
2158       dvert_final->dw = MEM_dupallocN(dvert->dw);
2159     }
2160   }
2161 }
2162
2163 static void gp_insert_point(
2164     bGPDstroke *gps, bGPDspoint *a_pt, bGPDspoint *b_pt, float co_a[3], float co_b[3])
2165 {
2166   bGPDspoint *temp_points;
2167   int totnewpoints, oldtotpoints;
2168
2169   totnewpoints = gps->totpoints;
2170   if (a_pt) {
2171     totnewpoints++;
2172   }
2173   if (b_pt) {
2174     totnewpoints++;
2175   }
2176
2177   /* duplicate points in a temp area */
2178   temp_points = MEM_dupallocN(gps->points);
2179   oldtotpoints = gps->totpoints;
2180
2181   /* look index of base points because memory is changed when resize points array */
2182   int a_idx = -1;
2183   int b_idx = -1;
2184   for (int i = 0; i < oldtotpoints; i++) {
2185     bGPDspoint *pt = &gps->points[i];
2186     if (pt == a_pt) {
2187       a_idx = i;
2188     }
2189     if (pt == b_pt) {
2190       b_idx = i;
2191     }
2192   }
2193
2194   /* resize the points arrays */
2195   gps->totpoints = totnewpoints;
2196   gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
2197   if (gps->dvert != NULL) {
2198     gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
2199   }
2200   gps->flag |= GP_STROKE_RECALC_GEOMETRY;
2201
2202   /* copy all points */
2203   int i2 = 0;
2204   for (int i = 0; i < oldtotpoints; i++) {
2205     bGPDspoint *pt = &temp_points[i];
2206     bGPDspoint *pt_final = &gps->points[i2];
2207     gp_copy_points(gps, pt, pt_final, i, i2);
2208
2209     /* create new point duplicating point and copy location */
2210     if ((i == a_idx) || (i == b_idx)) {
2211       i2++;
2212       pt_final = &gps->points[i2];
2213       gp_copy_points(gps, pt, pt_final, i, i2);
2214       copy_v3_v3(&pt_final->x, (i == a_idx) ? co_a : co_b);
2215
2216       /* unselect */
2217       pt_final->flag &= ~GP_SPOINT_SELECT;
2218       /* tag to avoid more checking with this point */
2219       pt_final->flag |= GP_SPOINT_TAG;
2220     }
2221
2222     i2++;
2223   }
2224
2225   MEM_SAFE_FREE(temp_points);
2226 }
2227
2228 static float gp_calc_factor(float p2d_a1[2], float p2d_a2[2], float r_hit2d[2])
2229 {
2230   float dist1 = len_squared_v2v2(p2d_a1, p2d_a2);
2231   float dist2 = len_squared_v2v2(p2d_a1, r_hit2d);
2232   float f = dist1 > 0.0f ? dist2 / dist1 : 0.0f;
2233
2234   /* apply a correction factor */
2235   float v1[2];
2236   interp_v2_v2v2(v1, p2d_a1, p2d_a2, f);
2237   float dist3 = len_squared_v2v2(p2d_a1, v1);
2238   float f1 = dist1 > 0.0f ? dist3 / dist1 : 0.0f;
2239   f = f + (f - f1);
2240
2241   return f;
2242 }
2243
2244 /* extend selection to stroke intersections */
2245 int ED_gpencil_select_stroke_segment(bGPDlayer *gpl,
2246                                      bGPDstroke *gps,
2247                                      bGPDspoint *pt,
2248                                      bool select,
2249                                      bool insert,
2250                                      const float scale,
2251                                      float r_hita[3],
2252                                      float r_hitb[3])
2253 {
2254   const float min_factor = 0.0015f;
2255   bGPDspoint *pta1 = NULL;
2256   bGPDspoint *pta2 = NULL;
2257   float f = 0.0f;
2258   int i2 = 0;
2259
2260   bGPDframe *gpf = gpl->actframe;
2261   if (gpf == NULL) {
2262     return 0;
2263   }
2264
2265   int memsize = BLI_listbase_count(&gpf->strokes);
2266   bGPDstroke **gps_array = MEM_callocN(sizeof(bGPDstroke *) * memsize, __func__);
2267
2268   /* save points */
2269   bGPDspoint *oldpoints = MEM_dupallocN(gps->points);
2270
2271   /* Save list of strokes to check */
2272   int totstrokes = 0;
2273   for (bGPDstroke *gps_iter = gpf->strokes.first; gps_iter; gps_iter = gps_iter->next) {
2274     if (gps_iter->totpoints < 2) {
2275       continue;
2276     }
2277     gps_array[totstrokes] = gps_iter;
2278     totstrokes++;
2279   }
2280
2281   if (totstrokes == 0) {
2282     return 0;
2283   }
2284
2285   /* look for index of the current point */
2286   int cur_idx = -1;
2287   for (int i = 0; i < gps->totpoints; i++) {
2288     pta1 = &gps->points[i];
2289     if (pta1 == pt) {
2290       cur_idx = i;
2291       break;
2292     }
2293   }
2294   if (cur_idx < 0) {
2295     return 0;
2296   }
2297
2298   /* convert all gps points to 2d and save in a hash to avoid recalculation  */
2299   int direction = 0;
2300   float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints,
2301                                     "GP Stroke temp 2d points");
2302   BKE_gpencil_stroke_2d_flat_ref(
2303       gps->points, gps->totpoints, gps->points, gps->totpoints, points2d, scale, &direction);
2304
2305   GHash *all_2d = BLI_ghash_ptr_new(__func__);
2306
2307   for (int s = 0; s < totstrokes; s++) {
2308     bGPDstroke *gps_iter = gps_array[s];
2309     float(*points2d_iter)[2] = MEM_mallocN(sizeof(*points2d_iter) * gps_iter->totpoints, __func__);
2310
2311     /* the extremes of the stroke are scaled to improve collision detection
2312      * for near lines */
2313     BKE_gpencil_stroke_2d_flat_ref(gps->points,
2314                                    gps->totpoints,
2315                                    gps_iter->points,
2316                                    gps_iter->totpoints,
2317                                    points2d_iter,
2318                                    scale,
2319                                    &direction);
2320     BLI_ghash_insert(all_2d, gps_iter, points2d_iter);
2321   }
2322
2323   bool hit_a = false;
2324   bool hit_b = false;
2325   float p2d_a1[2] = {0.0f, 0.0f};
2326   float p2d_a2[2] = {0.0f, 0.0f};
2327   float r_hit2d[2];
2328   bGPDspoint *hit_pointa = NULL;
2329   bGPDspoint *hit_pointb = NULL;
2330
2331   /* analyze points before current */
2332   if (cur_idx > 0) {
2333     for (int i = cur_idx; i >= 0; i--) {
2334       pta1 = &gps->points[i];
2335       copy_v2_v2(p2d_a1, points2d[i]);
2336
2337       i2 = i - 1;
2338       CLAMP_MIN(i2, 0);
2339       pta2 = &gps->points[i2];
2340       copy_v2_v2(p2d_a2, points2d[i2]);
2341
2342       hit_a = gpencil_check_collision(gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d);
2343
2344       if (select) {
2345         pta1->flag |= GP_SPOINT_SELECT;
2346       }
2347       else {
2348         pta1->flag &= ~GP_SPOINT_SELECT;
2349       }
2350
2351       if (hit_a) {
2352         f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d);
2353         interp_v3_v3v3(r_hita, &pta1->x, &pta2->x, f);
2354         if (f > min_factor) {
2355           hit_pointa = pta2; /* first point is second (inverted loop) */
2356         }
2357         else {
2358           pta1->flag &= ~GP_SPOINT_SELECT;
2359         }
2360         break;
2361       }
2362     }
2363   }
2364
2365   /* analyze points after current */
2366   for (int i = cur_idx; i < gps->totpoints; i++) {
2367     pta1 = &gps->points[i];
2368     copy_v2_v2(p2d_a1, points2d[i]);
2369
2370     i2 = i + 1;
2371     CLAMP_MAX(i2, gps->totpoints - 1);
2372     pta2 = &gps->points[i2];
2373     copy_v2_v2(p2d_a2, points2d[i2]);
2374
2375     hit_b = gpencil_check_collision(gps, gps_array, all_2d, totstrokes, p2d_a1, p2d_a2, r_hit2d);
2376
2377     if (select) {
2378       pta1->flag |= GP_SPOINT_SELECT;
2379     }
2380     else {
2381       pta1->flag &= ~GP_SPOINT_SELECT;
2382     }
2383
2384     if (hit_b) {
2385       f = gp_calc_factor(p2d_a1, p2d_a2, r_hit2d);
2386       interp_v3_v3v3(r_hitb, &pta1->x, &pta2->x, f);
2387       if (f > min_factor) {
2388         hit_pointb = pta1;
2389       }
2390       else {
2391         pta1->flag &= ~GP_SPOINT_SELECT;
2392       }
2393       break;
2394     }
2395   }
2396
2397   /* insert new point in the collision points */
2398   if (insert) {
2399     gp_insert_point(gps, hit_pointa, hit_pointb, r_hita, r_hitb);
2400   }
2401
2402   /* free memory */
2403   if (all_2d) {
2404     GHashIterator gh_iter;
2405     GHASH_ITER (gh_iter, all_2d) {
2406       float(*p2d)[2] = BLI_ghashIterator_getValue(&gh_iter);
2407       MEM_SAFE_FREE(p2d);
2408     }
2409     BLI_ghash_free(all_2d, NULL, NULL);
2410   }
2411
2412   /* if no hit, reset selection flag */
2413   if ((!hit_a) && (!hit_b)) {
2414     for (int i = 0; i < gps->totpoints; i++) {
2415       pta1 = &gps->points[i];
2416       pta2 = &oldpoints[i];
2417       pta1->flag = pta2->flag;
2418     }
2419   }
2420
2421   MEM_SAFE_FREE(points2d);
2422   MEM_SAFE_FREE(gps_array);
2423   MEM_SAFE_FREE(oldpoints);
2424
2425   /* return type of hit */
2426   if ((hit_a) && (hit_b)) {
2427     return 3;
2428   }
2429   else if (hit_a) {
2430     return 1;
2431   }
2432   else if (hit_b) {
2433     return 2;
2434   }
2435   else {
2436     return 0;
2437   }
2438 }
2439
2440 void ED_gpencil_select_toggle_all(bContext *C, int action)
2441 {
2442   /* for "toggle", test for existing selected strokes */
2443   if (action == SEL_TOGGLE) {
2444     action = SEL_SELECT;
2445
2446     CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
2447       if (gps->flag & GP_STROKE_SELECT) {
2448         action = SEL_DESELECT;
2449         break;  // XXX: this only gets out of the inner loop...
2450       }
2451     }
2452     CTX_DATA_END;
2453   }
2454
2455   /* if deselecting, we need to deselect strokes across all frames
2456    * - Currently, an exception is only given for deselection
2457    *   Selecting and toggling should only affect what's visible,
2458    *   while deselecting helps clean up unintended/forgotten
2459    *   stuff on other frames
2460    */
2461   if (action == SEL_DESELECT) {
2462     /* deselect strokes across editable layers
2463      * NOTE: we limit ourselves to editable layers, since once a layer is "locked/hidden
2464      *       nothing should be able to touch it
2465      */
2466     CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
2467       bGPDframe *gpf;
2468
2469       /* deselect all strokes on all frames */
2470       for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
2471         bGPDstroke *gps;
2472
2473         for (gps = gpf->strokes.first; gps; gps = gps->next) {
2474           bGPDspoint *pt;
2475           int i;
2476
2477           /* only edit strokes that are valid in this view... */
2478           if (ED_gpencil_stroke_can_use(C, gps)) {
2479             for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
2480               pt->flag &= ~GP_SPOINT_SELECT;
2481             }
2482
2483             gps->flag &= ~GP_STROKE_SELECT;
2484           }
2485         }
2486       }
2487     }
2488     CTX_DATA_END;
2489   }
2490   else {
2491     /* select or deselect all strokes */
2492     CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
2493       bGPDspoint *pt;
2494       int i;
2495       bool selected = false;
2496
2497       /* Change selection status of all points, then make the stroke match */
2498       for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
2499         switch (action) {
2500           case SEL_SELECT:
2501             pt->flag |= GP_SPOINT_SELECT;
2502             break;
2503           // case SEL_DESELECT:
2504           //  pt->flag &= ~GP_SPOINT_SELECT;
2505           //  break;
2506           case SEL_INVERT:
2507             pt->flag ^= GP_SPOINT_SELECT;
2508             break;
2509         }
2510
2511         if (pt->flag & GP_SPOINT_SELECT) {
2512           selected = true;
2513         }
2514       }
2515
2516       /* Change status of stroke */
2517       if (selected) {
2518         gps->flag |= GP_STROKE_SELECT;
2519       }
2520       else {
2521         gps->flag &= ~GP_STROKE_SELECT;
2522       }
2523     }
2524     CTX_DATA_END;
2525   }
2526 }
2527
2528 /* Ensure the SBuffer (while drawing stroke) size is enough to save all points of the stroke */
2529 tGPspoint *ED_gpencil_sbuffer_ensure(tGPspoint *buffer_array,
2530                                      short *buffer_size,
2531                                      short *buffer_used,
2532                                      const bool clear)
2533 {
2534   tGPspoint *p = NULL;
2535
2536   /* By default a buffer is created with one block with a predefined number of free points,
2537    * if the size is not enough, the cache is reallocated adding a new block of free points.
2538    * This is done in order to keep cache small and improve speed. */
2539   if (*buffer_used + 1 > *buffer_size) {
2540     if ((*buffer_size == 0) || (buffer_array == NULL)) {
2541       p = MEM_callocN(sizeof(struct tGPspoint) * GP_STROKE_BUFFER_CHUNK, "GPencil Sbuffer");
2542       *buffer_size = GP_STROKE_BUFFER_CHUNK;
2543     }
2544     else {
2545       *buffer_size += GP_STROKE_BUFFER_CHUNK;
2546       p = MEM_recallocN(buffer_array, sizeof(struct tGPspoint) * *buffer_size);
2547     }
2548     buffer_array = p;
2549   }
2550
2551   /* clear old data */
2552   if (clear) {
2553     *buffer_used = 0;
2554     if (buffer_array != NULL) {
2555       memset(buffer_array, 0, sizeof(tGPspoint) * *buffer_size);
2556     }
2557   }
2558
2559   return buffer_array;
2560 }