Cleanup: Rename 'make local' functions to new scheme.
[blender-staging.git] / source / blender / blenkernel / intern / gpencil.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2008, Blender Foundation
17  * This is a new part of Blender
18  */
19
20 /** \file
21  * \ingroup bke
22  */
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <stddef.h>
28 #include <math.h>
29
30 #include "CLG_log.h"
31
32 #include "MEM_guardedalloc.h"
33
34 #include "BLI_blenlib.h"
35 #include "BLI_utildefines.h"
36 #include "BLI_math_vector.h"
37 #include "BLI_polyfill_2d.h"
38 #include "BLI_string_utils.h"
39
40 #include "BLT_translation.h"
41
42 #include "DNA_anim_types.h"
43 #include "DNA_meshdata_types.h"
44 #include "DNA_material_types.h"
45 #include "DNA_gpencil_types.h"
46 #include "DNA_userdef_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_object_types.h"
49
50 #include "BKE_action.h"
51 #include "BKE_animsys.h"
52 #include "BKE_curve.h"
53 #include "BKE_collection.h"
54 #include "BKE_colortools.h"
55 #include "BKE_deform.h"
56 #include "BKE_gpencil.h"
57 #include "BKE_icons.h"
58 #include "BKE_lib_id.h"
59 #include "BKE_main.h"
60 #include "BKE_material.h"
61 #include "BKE_object.h"
62
63 #include "BLI_math_color.h"
64
65 #include "DEG_depsgraph.h"
66
67 static CLG_LogRef LOG = {"bke.gpencil"};
68
69 /* ************************************************** */
70 /* Draw Engine */
71
72 void (*BKE_gpencil_batch_cache_dirty_tag_cb)(bGPdata *gpd) = NULL;
73 void (*BKE_gpencil_batch_cache_free_cb)(bGPdata *gpd) = NULL;
74
75 void BKE_gpencil_batch_cache_dirty_tag(bGPdata *gpd)
76 {
77   if (gpd) {
78     DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
79     BKE_gpencil_batch_cache_dirty_tag_cb(gpd);
80   }
81 }
82
83 void BKE_gpencil_batch_cache_free(bGPdata *gpd)
84 {
85   if (gpd) {
86     BKE_gpencil_batch_cache_free_cb(gpd);
87   }
88 }
89
90 /* ************************************************** */
91 /* Memory Management */
92
93 /* clean vertex groups weights */
94 void BKE_gpencil_free_point_weights(MDeformVert *dvert)
95 {
96   if (dvert == NULL) {
97     return;
98   }
99   MEM_SAFE_FREE(dvert->dw);
100 }
101
102 void BKE_gpencil_free_stroke_weights(bGPDstroke *gps)
103 {
104   if (gps == NULL) {
105     return;
106   }
107
108   if (gps->dvert == NULL) {
109     return;
110   }
111
112   for (int i = 0; i < gps->totpoints; i++) {
113     MDeformVert *dvert = &gps->dvert[i];
114     BKE_gpencil_free_point_weights(dvert);
115   }
116 }
117
118 /* free stroke, doesn't unlink from any listbase */
119 void BKE_gpencil_free_stroke(bGPDstroke *gps)
120 {
121   if (gps == NULL) {
122     return;
123   }
124   /* free stroke memory arrays, then stroke itself */
125   if (gps->points) {
126     MEM_freeN(gps->points);
127   }
128   if (gps->dvert) {
129     BKE_gpencil_free_stroke_weights(gps);
130     MEM_freeN(gps->dvert);
131   }
132   if (gps->triangles) {
133     MEM_freeN(gps->triangles);
134   }
135
136   MEM_freeN(gps);
137 }
138
139 /* Free strokes belonging to a gp-frame */
140 bool BKE_gpencil_free_strokes(bGPDframe *gpf)
141 {
142   bGPDstroke *gps_next;
143   bool changed = (BLI_listbase_is_empty(&gpf->strokes) == false);
144
145   /* free strokes */
146   for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps_next) {
147     gps_next = gps->next;
148     BKE_gpencil_free_stroke(gps);
149   }
150   BLI_listbase_clear(&gpf->strokes);
151
152   return changed;
153 }
154
155 /* Free strokes and colors belonging to a gp-frame */
156 bool BKE_gpencil_free_frame_runtime_data(bGPDframe *gpf_eval)
157 {
158   bGPDstroke *gps_next;
159   if (!gpf_eval) {
160     return false;
161   }
162
163   /* free strokes */
164   for (bGPDstroke *gps = gpf_eval->strokes.first; gps; gps = gps_next) {
165     gps_next = gps->next;
166     BKE_gpencil_free_stroke(gps);
167   }
168   BLI_listbase_clear(&gpf_eval->strokes);
169
170   return true;
171 }
172
173 /* Free all of a gp-layer's frames */
174 void BKE_gpencil_free_frames(bGPDlayer *gpl)
175 {
176   bGPDframe *gpf_next;
177
178   /* error checking */
179   if (gpl == NULL) {
180     return;
181   }
182
183   /* free frames */
184   for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf_next) {
185     gpf_next = gpf->next;
186
187     /* free strokes and their associated memory */
188     BKE_gpencil_free_strokes(gpf);
189     BLI_freelinkN(&gpl->frames, gpf);
190   }
191   gpl->actframe = NULL;
192 }
193
194 /* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */
195 void BKE_gpencil_free_layers(ListBase *list)
196 {
197   bGPDlayer *gpl_next;
198
199   /* error checking */
200   if (list == NULL) {
201     return;
202   }
203
204   /* delete layers */
205   for (bGPDlayer *gpl = list->first; gpl; gpl = gpl_next) {
206     gpl_next = gpl->next;
207
208     /* free layers and their data */
209     BKE_gpencil_free_frames(gpl);
210     BLI_freelinkN(list, gpl);
211   }
212 }
213
214 /** Free (or release) any data used by this grease pencil (does not free the gpencil itself). */
215 void BKE_gpencil_free(bGPdata *gpd, bool free_all)
216 {
217   /* clear animation data */
218   BKE_animdata_free(&gpd->id, false);
219
220   /* free layers */
221   BKE_gpencil_free_layers(&gpd->layers);
222
223   /* materials */
224   MEM_SAFE_FREE(gpd->mat);
225
226   /* free all data */
227   if (free_all) {
228     /* clear cache */
229     BKE_gpencil_batch_cache_free(gpd);
230   }
231 }
232
233 /* ************************************************** */
234 /* Container Creation */
235
236 /* add a new gp-frame to the given layer */
237 bGPDframe *BKE_gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
238 {
239   bGPDframe *gpf = NULL, *gf = NULL;
240   short state = 0;
241
242   /* error checking */
243   if (gpl == NULL) {
244     return NULL;
245   }
246
247   /* allocate memory for this frame */
248   gpf = MEM_callocN(sizeof(bGPDframe), "bGPDframe");
249   gpf->framenum = cframe;
250
251   /* find appropriate place to add frame */
252   if (gpl->frames.first) {
253     for (gf = gpl->frames.first; gf; gf = gf->next) {
254       /* check if frame matches one that is supposed to be added */
255       if (gf->framenum == cframe) {
256         state = -1;
257         break;
258       }
259
260       /* if current frame has already exceeded the frame to add, add before */
261       if (gf->framenum > cframe) {
262         BLI_insertlinkbefore(&gpl->frames, gf, gpf);
263         state = 1;
264         break;
265       }
266     }
267   }
268
269   /* check whether frame was added successfully */
270   if (state == -1) {
271     CLOG_ERROR(
272         &LOG, "Frame (%d) existed already for this layer_active. Using existing frame", cframe);
273
274     /* free the newly created one, and use the old one instead */
275     MEM_freeN(gpf);
276
277     /* return existing frame instead... */
278     BLI_assert(gf != NULL);
279     gpf = gf;
280   }
281   else if (state == 0) {
282     /* add to end then! */
283     BLI_addtail(&gpl->frames, gpf);
284   }
285
286   /* return frame */
287   return gpf;
288 }
289
290 /* add a copy of the active gp-frame to the given layer */
291 bGPDframe *BKE_gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
292 {
293   bGPDframe *new_frame;
294   bool found = false;
295
296   /* Error checking/handling */
297   if (gpl == NULL) {
298     /* no layer */
299     return NULL;
300   }
301   else if (gpl->actframe == NULL) {
302     /* no active frame, so just create a new one from scratch */
303     return BKE_gpencil_frame_addnew(gpl, cframe);
304   }
305
306   /* Create a copy of the frame */
307   new_frame = BKE_gpencil_frame_duplicate(gpl->actframe);
308
309   /* Find frame to insert it before */
310   for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
311     if (gpf->framenum > cframe) {
312       /* Add it here */
313       BLI_insertlinkbefore(&gpl->frames, gpf, new_frame);
314
315       found = true;
316       break;
317     }
318     else if (gpf->framenum == cframe) {
319       /* This only happens when we're editing with framelock on...
320        * - Delete the new frame and don't do anything else here...
321        */
322       BKE_gpencil_free_strokes(new_frame);
323       MEM_freeN(new_frame);
324       new_frame = NULL;
325
326       found = true;
327       break;
328     }
329   }
330
331   if (found == false) {
332     /* Add new frame to the end */
333     BLI_addtail(&gpl->frames, new_frame);
334   }
335
336   /* Ensure that frame is set up correctly, and return it */
337   if (new_frame) {
338     new_frame->framenum = cframe;
339     gpl->actframe = new_frame;
340   }
341
342   return new_frame;
343 }
344
345 /* add a new gp-layer and make it the active layer */
346 bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setactive)
347 {
348   bGPDlayer *gpl = NULL;
349   bGPDlayer *gpl_active = NULL;
350
351   /* check that list is ok */
352   if (gpd == NULL) {
353     return NULL;
354   }
355
356   /* allocate memory for frame and add to end of list */
357   gpl = MEM_callocN(sizeof(bGPDlayer), "bGPDlayer");
358
359   gpl_active = BKE_gpencil_layer_getactive(gpd);
360
361   /* add to datablock */
362   if (gpl_active == NULL) {
363     BLI_addtail(&gpd->layers, gpl);
364   }
365   else {
366     /* if active layer, add after that layer */
367     BLI_insertlinkafter(&gpd->layers, gpl_active, gpl);
368   }
369
370   /* annotation vs GP Object behavior is slightly different */
371   if (gpd->flag & GP_DATA_ANNOTATIONS) {
372     /* set default color of new strokes for this layer */
373     copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
374     gpl->opacity = 1.0f;
375
376     /* set default thickness of new strokes for this layer */
377     gpl->thickness = 3;
378
379     /* Onion colors */
380     ARRAY_SET_ITEMS(gpl->gcolor_prev, 0.302f, 0.851f, 0.302f);
381     ARRAY_SET_ITEMS(gpl->gcolor_next, 0.250f, 0.1f, 1.0f);
382   }
383   else {
384     /* thickness parameter represents "thickness change", not absolute thickness */
385     gpl->thickness = 0;
386     gpl->opacity = 1.0f;
387     /* default channel color */
388     ARRAY_SET_ITEMS(gpl->color, 0.2f, 0.2f, 0.2f);
389   }
390
391   /* auto-name */
392   BLI_strncpy(gpl->info, name, sizeof(gpl->info));
393   BLI_uniquename(&gpd->layers,
394                  gpl,
395                  (gpd->flag & GP_DATA_ANNOTATIONS) ? DATA_("Note") : DATA_("GP_Layer"),
396                  '.',
397                  offsetof(bGPDlayer, info),
398                  sizeof(gpl->info));
399
400   /* make this one the active one */
401   if (setactive) {
402     BKE_gpencil_layer_setactive(gpd, gpl);
403   }
404
405   /* return layer */
406   return gpl;
407 }
408
409 /* add a new gp-datablock */
410 bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
411 {
412   bGPdata *gpd;
413
414   /* allocate memory for a new block */
415   gpd = BKE_libblock_alloc(bmain, ID_GD, name, 0);
416
417   /* initial settings */
418   gpd->flag = (GP_DATA_DISPINFO | GP_DATA_EXPAND);
419
420   /* general flags */
421   gpd->flag |= GP_DATA_VIEWALIGN;
422   gpd->flag |= GP_DATA_STROKE_FORCE_RECALC;
423   /* always enable object onion skin switch */
424   gpd->flag |= GP_DATA_SHOW_ONIONSKINS;
425   /* GP object specific settings */
426   ARRAY_SET_ITEMS(gpd->line_color, 0.6f, 0.6f, 0.6f, 0.5f);
427
428   gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
429
430   /* grid settings */
431   ARRAY_SET_ITEMS(gpd->grid.color, 0.5f, 0.5f, 0.5f); /* Color */
432   ARRAY_SET_ITEMS(gpd->grid.scale, 1.0f, 1.0f);       /* Scale */
433   gpd->grid.lines = GP_DEFAULT_GRID_LINES;            /* Number of lines */
434
435   /* onion-skinning settings (datablock level) */
436   gpd->onion_flag |= (GP_ONION_GHOST_PREVCOL | GP_ONION_GHOST_NEXTCOL);
437   gpd->onion_flag |= GP_ONION_FADE;
438   gpd->onion_mode = GP_ONION_MODE_RELATIVE;
439   gpd->onion_factor = 0.5f;
440   ARRAY_SET_ITEMS(gpd->gcolor_prev, 0.145098f, 0.419608f, 0.137255f); /* green */
441   ARRAY_SET_ITEMS(gpd->gcolor_next, 0.125490f, 0.082353f, 0.529412f); /* blue */
442   gpd->gstep = 1;
443   gpd->gstep_next = 1;
444
445   return gpd;
446 }
447
448 /* ************************************************** */
449 /* Primitive Creation */
450 /* Utilities for easier bulk-creation of geometry */
451
452 /**
453  * Populate stroke with point data from data buffers
454  *
455  * \param array: Flat array of point data values. Each entry has GP_PRIM_DATABUF_SIZE values
456  * \param mat: 4x4 transform matrix to transform points into the right coordinate space
457  */
458 void BKE_gpencil_stroke_add_points(bGPDstroke *gps,
459                                    const float *array,
460                                    const int totpoints,
461                                    const float mat[4][4])
462 {
463   for (int i = 0; i < totpoints; i++) {
464     bGPDspoint *pt = &gps->points[i];
465     const int x = GP_PRIM_DATABUF_SIZE * i;
466
467     pt->x = array[x];
468     pt->y = array[x + 1];
469     pt->z = array[x + 2];
470     mul_m4_v3(mat, &pt->x);
471
472     pt->pressure = array[x + 3];
473     pt->strength = array[x + 4];
474   }
475 }
476
477 /* Create a new stroke, with pre-allocated data buffers */
478 bGPDstroke *BKE_gpencil_add_stroke(bGPDframe *gpf, int mat_idx, int totpoints, short thickness)
479 {
480   /* allocate memory for a new stroke */
481   bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
482
483   gps->thickness = thickness;
484   gps->gradient_f = 1.0f;
485   gps->gradient_s[0] = 1.0f;
486   gps->gradient_s[1] = 1.0f;
487
488   gps->inittime = 0;
489
490   /* enable recalculation flag by default */
491   gps->flag = GP_STROKE_RECALC_GEOMETRY | GP_STROKE_3DSPACE;
492
493   gps->totpoints = totpoints;
494   gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
495
496   /* initialize triangle memory to dummy data */
497   gps->triangles = NULL;
498   gps->flag |= GP_STROKE_RECALC_GEOMETRY;
499   gps->tot_triangles = 0;
500
501   gps->mat_nr = mat_idx;
502
503   /* add to frame */
504   BLI_addtail(&gpf->strokes, gps);
505
506   return gps;
507 }
508
509 /* Add a stroke and copy the temporary drawing color value from one of the existing stroke */
510 bGPDstroke *BKE_gpencil_add_stroke_existing_style(
511     bGPDframe *gpf, bGPDstroke *existing, int mat_idx, int totpoints, short thickness)
512 {
513   bGPDstroke *gps = BKE_gpencil_add_stroke(gpf, mat_idx, totpoints, thickness);
514   /* Copy run-time color data so that strokes added in the modifier has the style.
515    * There are depsgraph reference pointers inside,
516    * change the copy function if interfere with future drawing implementation. */
517   memcpy(&gps->runtime, &existing->runtime, sizeof(bGPDstroke_Runtime));
518   return gps;
519 }
520
521 /* ************************************************** */
522 /* Data Duplication */
523
524 /* make a copy of a given gpencil weights */
525 void BKE_gpencil_stroke_weights_duplicate(bGPDstroke *gps_src, bGPDstroke *gps_dst)
526 {
527   if (gps_src == NULL) {
528     return;
529   }
530   BLI_assert(gps_src->totpoints == gps_dst->totpoints);
531
532   BKE_defvert_array_copy(gps_dst->dvert, gps_src->dvert, gps_src->totpoints);
533 }
534
535 /* make a copy of a given gpencil stroke */
536 bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src)
537 {
538   bGPDstroke *gps_dst = NULL;
539
540   gps_dst = MEM_dupallocN(gps_src);
541   gps_dst->prev = gps_dst->next = NULL;
542
543   gps_dst->points = MEM_dupallocN(gps_src->points);
544
545   if (gps_src->dvert != NULL) {
546     gps_dst->dvert = MEM_dupallocN(gps_src->dvert);
547     BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst);
548   }
549   else {
550     gps_dst->dvert = NULL;
551   }
552
553   /* Don't clear triangles, so that modifier evaluation can just use
554    * this without extra work first. Most places that need to force
555    * this data to get recalculated will destroy the data anyway though.
556    */
557   gps_dst->triangles = MEM_dupallocN(gps_dst->triangles);
558   /* gps_dst->flag |= GP_STROKE_RECALC_GEOMETRY; */
559
560   /* return new stroke */
561   return gps_dst;
562 }
563
564 /* make a copy of a given gpencil frame */
565 bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src)
566 {
567   bGPDstroke *gps_dst = NULL;
568   bGPDframe *gpf_dst;
569
570   /* error checking */
571   if (gpf_src == NULL) {
572     return NULL;
573   }
574
575   /* make a copy of the source frame */
576   gpf_dst = MEM_dupallocN(gpf_src);
577   gpf_dst->prev = gpf_dst->next = NULL;
578
579   /* copy strokes */
580   BLI_listbase_clear(&gpf_dst->strokes);
581   for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
582     /* make copy of source stroke */
583     gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
584     BLI_addtail(&gpf_dst->strokes, gps_dst);
585   }
586
587   /* return new frame */
588   return gpf_dst;
589 }
590
591 /* make a copy of strokes between gpencil frames */
592 void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, struct bGPDframe *gpf_dst)
593 {
594   bGPDstroke *gps_dst = NULL;
595   /* error checking */
596   if ((gpf_src == NULL) || (gpf_dst == NULL)) {
597     return;
598   }
599
600   /* copy strokes */
601   BLI_listbase_clear(&gpf_dst->strokes);
602   for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
603     /* make copy of source stroke */
604     gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
605     BLI_addtail(&gpf_dst->strokes, gps_dst);
606   }
607 }
608
609 /* make a copy of a given gpencil layer */
610 bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src)
611 {
612   const bGPDframe *gpf_src;
613   bGPDframe *gpf_dst;
614   bGPDlayer *gpl_dst;
615
616   /* error checking */
617   if (gpl_src == NULL) {
618     return NULL;
619   }
620
621   /* make a copy of source layer */
622   gpl_dst = MEM_dupallocN(gpl_src);
623   gpl_dst->prev = gpl_dst->next = NULL;
624
625   /* copy frames */
626   BLI_listbase_clear(&gpl_dst->frames);
627   for (gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) {
628     /* make a copy of source frame */
629     gpf_dst = BKE_gpencil_frame_duplicate(gpf_src);
630     BLI_addtail(&gpl_dst->frames, gpf_dst);
631
632     /* if source frame was the current layer's 'active' frame, reassign that too */
633     if (gpf_src == gpl_dst->actframe) {
634       gpl_dst->actframe = gpf_dst;
635     }
636   }
637
638   /* return new layer */
639   return gpl_dst;
640 }
641
642 /**
643  * Only copy internal data of GreasePencil ID from source
644  * to already allocated/initialized destination.
645  * You probably never want to use that directly,
646  * use #BKE_id_copy or #BKE_id_copy_ex for typical needs.
647  *
648  * WARNING! This function will not handle ID user count!
649  *
650  * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more).
651  */
652 void BKE_gpencil_copy_data(bGPdata *gpd_dst, const bGPdata *gpd_src, const int UNUSED(flag))
653 {
654   /* duplicate material array */
655   if (gpd_src->mat) {
656     gpd_dst->mat = MEM_dupallocN(gpd_src->mat);
657   }
658
659   /* copy layers */
660   BLI_listbase_clear(&gpd_dst->layers);
661   for (const bGPDlayer *gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) {
662     /* make a copy of source layer and its data */
663
664     /* TODO here too could add unused flags... */
665     bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src);
666
667     BLI_addtail(&gpd_dst->layers, gpl_dst);
668   }
669 }
670
671 /* Standard API to make a copy of GP datablock, separate from copying its data */
672 bGPdata *BKE_gpencil_copy(Main *bmain, const bGPdata *gpd)
673 {
674   bGPdata *gpd_copy;
675   BKE_id_copy(bmain, &gpd->id, (ID **)&gpd_copy);
676   return gpd_copy;
677 }
678
679 /* make a copy of a given gpencil datablock */
680 /* XXX: Should this be deprecated? */
681 bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy)
682 {
683   bGPdata *gpd_dst;
684
685   /* Yuck and super-uber-hyper yuck!!!
686    * Should be replaceable with a no-main copy (LIB_ID_COPY_NO_MAIN etc.), but not sure about it,
687    * so for now keep old code for that one. */
688
689   /* error checking */
690   if (gpd_src == NULL) {
691     return NULL;
692   }
693
694   if (internal_copy) {
695     /* make a straight copy for undo buffers used during stroke drawing */
696     gpd_dst = MEM_dupallocN(gpd_src);
697   }
698   else {
699     BLI_assert(bmain != NULL);
700     BKE_id_copy(bmain, &gpd_src->id, (ID **)&gpd_dst);
701   }
702
703   /* Copy internal data (layers, etc.) */
704   BKE_gpencil_copy_data(gpd_dst, gpd_src, 0);
705
706   /* return new */
707   return gpd_dst;
708 }
709
710 void BKE_gpencil_make_local(Main *bmain, bGPdata *gpd, const bool lib_local)
711 {
712   BKE_lib_id_make_local_generic(bmain, &gpd->id, true, lib_local);
713 }
714
715 /* ************************************************** */
716 /* GP Stroke API */
717
718 /* ensure selection status of stroke is in sync with its points */
719 void BKE_gpencil_stroke_sync_selection(bGPDstroke *gps)
720 {
721   bGPDspoint *pt;
722   int i;
723
724   /* error checking */
725   if (gps == NULL) {
726     return;
727   }
728
729   /* we'll stop when we find the first selected point,
730    * so initially, we must deselect
731    */
732   gps->flag &= ~GP_STROKE_SELECT;
733
734   for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
735     if (pt->flag & GP_SPOINT_SELECT) {
736       gps->flag |= GP_STROKE_SELECT;
737       break;
738     }
739   }
740 }
741
742 /* ************************************************** */
743 /* GP Frame API */
744
745 /* delete the last stroke of the given frame */
746 void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
747 {
748   bGPDstroke *gps = (gpf) ? gpf->strokes.last : NULL;
749   int cfra = (gpf) ? gpf->framenum : 0; /* assume that the current frame was not locked */
750
751   /* error checking */
752   if (ELEM(NULL, gpf, gps)) {
753     return;
754   }
755
756   /* free the stroke and its data */
757   if (gps->points) {
758     MEM_freeN(gps->points);
759   }
760   if (gps->dvert) {
761     BKE_gpencil_free_stroke_weights(gps);
762     MEM_freeN(gps->dvert);
763   }
764   MEM_freeN(gps->triangles);
765   BLI_freelinkN(&gpf->strokes, gps);
766
767   /* if frame has no strokes after this, delete it */
768   if (BLI_listbase_is_empty(&gpf->strokes)) {
769     BKE_gpencil_layer_delframe(gpl, gpf);
770     BKE_gpencil_layer_getframe(gpl, cfra, GP_GETFRAME_USE_PREV);
771   }
772 }
773
774 /* ************************************************** */
775 /* GP Layer API */
776
777 /* Check if the given layer is able to be edited or not */
778 bool gpencil_layer_is_editable(const bGPDlayer *gpl)
779 {
780   /* Sanity check */
781   if (gpl == NULL) {
782     return false;
783   }
784
785   /* Layer must be: Visible + Editable */
786   if ((gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) == 0) {
787     /* Opacity must be sufficiently high that it is still "visible"
788      * Otherwise, it's not really "visible" to the user, so no point editing...
789      */
790     if (gpl->opacity > GPENCIL_ALPHA_OPACITY_THRESH) {
791       return true;
792     }
793   }
794
795   /* Something failed */
796   return false;
797 }
798
799 /* Look up the gp-frame on the requested frame number, but don't add a new one */
800 bGPDframe *BKE_gpencil_layer_find_frame(bGPDlayer *gpl, int cframe)
801 {
802   bGPDframe *gpf;
803
804   /* Search in reverse order, since this is often used for playback/adding,
805    * where it's less likely that we're interested in the earlier frames
806    */
807   for (gpf = gpl->frames.last; gpf; gpf = gpf->prev) {
808     if (gpf->framenum == cframe) {
809       return gpf;
810     }
811   }
812
813   return NULL;
814 }
815
816 /* get the appropriate gp-frame from a given layer
817  * - this sets the layer's actframe var (if allowed to)
818  * - extension beyond range (if first gp-frame is after all frame in interest and cannot add)
819  */
820 bGPDframe *BKE_gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
821 {
822   bGPDframe *gpf = NULL;
823   bool found = false;
824
825   /* error checking */
826   if (gpl == NULL) {
827     return NULL;
828   }
829
830   /* check if there is already an active frame */
831   if (gpl->actframe) {
832     gpf = gpl->actframe;
833
834     /* do not allow any changes to layer's active frame if layer is locked from changes
835      * or if the layer has been set to stay on the current frame
836      */
837     if (gpl->flag & GP_LAYER_FRAMELOCK) {
838       return gpf;
839     }
840     /* do not allow any changes to actframe if frame has painting tag attached to it */
841     if (gpf->flag & GP_FRAME_PAINT) {
842       return gpf;
843     }
844
845     /* try to find matching frame */
846     if (gpf->framenum < cframe) {
847       for (; gpf; gpf = gpf->next) {
848         if (gpf->framenum == cframe) {
849           found = true;
850           break;
851         }
852         else if ((gpf->next) && (gpf->next->framenum > cframe)) {
853           found = true;
854           break;
855         }
856       }
857
858       /* set the appropriate frame */
859       if (addnew) {
860         if ((found) && (gpf->framenum == cframe)) {
861           gpl->actframe = gpf;
862         }
863         else if (addnew == GP_GETFRAME_ADD_COPY) {
864           gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe);
865         }
866         else {
867           gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
868         }
869       }
870       else if (found) {
871         gpl->actframe = gpf;
872       }
873       else {
874         gpl->actframe = gpl->frames.last;
875       }
876     }
877     else {
878       for (; gpf; gpf = gpf->prev) {
879         if (gpf->framenum <= cframe) {
880           found = true;
881           break;
882         }
883       }
884
885       /* set the appropriate frame */
886       if (addnew) {
887         if ((found) && (gpf->framenum == cframe)) {
888           gpl->actframe = gpf;
889         }
890         else if (addnew == GP_GETFRAME_ADD_COPY) {
891           gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe);
892         }
893         else {
894           gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
895         }
896       }
897       else if (found) {
898         gpl->actframe = gpf;
899       }
900       else {
901         gpl->actframe = gpl->frames.first;
902       }
903     }
904   }
905   else if (gpl->frames.first) {
906     /* check which of the ends to start checking from */
907     const int first = ((bGPDframe *)(gpl->frames.first))->framenum;
908     const int last = ((bGPDframe *)(gpl->frames.last))->framenum;
909
910     if (abs(cframe - first) > abs(cframe - last)) {
911       /* find gp-frame which is less than or equal to cframe */
912       for (gpf = gpl->frames.last; gpf; gpf = gpf->prev) {
913         if (gpf->framenum <= cframe) {
914           found = true;
915           break;
916         }
917       }
918     }
919     else {
920       /* find gp-frame which is less than or equal to cframe */
921       for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
922         if (gpf->framenum <= cframe) {
923           found = true;
924           break;
925         }
926       }
927     }
928
929     /* set the appropriate frame */
930     if (addnew) {
931       if ((found) && (gpf->framenum == cframe)) {
932         gpl->actframe = gpf;
933       }
934       else {
935         gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
936       }
937     }
938     else if (found) {
939       gpl->actframe = gpf;
940     }
941     else {
942       /* If delete first frame, need to find one. */
943       if (gpl->frames.first != NULL) {
944         gpl->actframe = gpl->frames.first;
945       }
946       else {
947         /* unresolved errogenous situation! */
948         CLOG_STR_ERROR(&LOG, "cannot find appropriate gp-frame");
949         /* gpl->actframe should still be NULL */
950       }
951     }
952   }
953   else {
954     /* currently no frames (add if allowed to) */
955     if (addnew) {
956       gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
957     }
958     else {
959       /* don't do anything... this may be when no frames yet! */
960       /* gpl->actframe should still be NULL */
961     }
962   }
963
964   /* return */
965   return gpl->actframe;
966 }
967
968 /* delete the given frame from a layer */
969 bool BKE_gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
970 {
971   bool changed = false;
972
973   /* error checking */
974   if (ELEM(NULL, gpl, gpf)) {
975     return false;
976   }
977
978   /* if this frame was active, make the previous frame active instead
979    * since it's tricky to set active frame otherwise
980    */
981   if (gpl->actframe == gpf) {
982     gpl->actframe = gpf->prev;
983   }
984
985   /* free the frame and its data */
986   changed = BKE_gpencil_free_strokes(gpf);
987   BLI_freelinkN(&gpl->frames, gpf);
988
989   return changed;
990 }
991
992 /* get the active gp-layer for editing */
993 bGPDlayer *BKE_gpencil_layer_getactive(bGPdata *gpd)
994 {
995   bGPDlayer *gpl;
996
997   /* error checking */
998   if (ELEM(NULL, gpd, gpd->layers.first)) {
999     return NULL;
1000   }
1001
1002   /* loop over layers until found (assume only one active) */
1003   for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1004     if (gpl->flag & GP_LAYER_ACTIVE) {
1005       return gpl;
1006     }
1007   }
1008
1009   /* no active layer found */
1010   return NULL;
1011 }
1012
1013 /* set the active gp-layer */
1014 void BKE_gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active)
1015 {
1016   bGPDlayer *gpl;
1017
1018   /* error checking */
1019   if (ELEM(NULL, gpd, gpd->layers.first, active)) {
1020     return;
1021   }
1022
1023   /* loop over layers deactivating all */
1024   for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1025     gpl->flag &= ~GP_LAYER_ACTIVE;
1026     if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
1027       gpl->flag |= GP_LAYER_LOCKED;
1028     }
1029   }
1030
1031   /* set as active one */
1032   active->flag |= GP_LAYER_ACTIVE;
1033   if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
1034     active->flag &= ~GP_LAYER_LOCKED;
1035   }
1036 }
1037
1038 /* Set locked layers for autolock mode. */
1039 void BKE_gpencil_layer_autolock_set(bGPdata *gpd, const bool unlock)
1040 {
1041   BLI_assert(gpd != NULL);
1042
1043   bGPDlayer *gpl;
1044
1045   if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
1046     bGPDlayer *layer_active = BKE_gpencil_layer_getactive(gpd);
1047
1048     /* Lock all other layers */
1049     for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1050       /* unlock active layer */
1051       if (gpl == layer_active) {
1052         gpl->flag &= ~GP_LAYER_LOCKED;
1053       }
1054       else {
1055         gpl->flag |= GP_LAYER_LOCKED;
1056       }
1057     }
1058   }
1059   else {
1060     /* If disable is better unlock all layers by default or it looks there is
1061      * a problem in the UI because the user expects all layers will be unlocked
1062      */
1063     if (unlock) {
1064       for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1065         gpl->flag &= ~GP_LAYER_LOCKED;
1066       }
1067     }
1068   }
1069 }
1070
1071 /* delete the active gp-layer */
1072 void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl)
1073 {
1074   /* error checking */
1075   if (ELEM(NULL, gpd, gpl)) {
1076     return;
1077   }
1078
1079   /* free layer */
1080   BKE_gpencil_free_frames(gpl);
1081
1082   /* free icon providing preview of icon color */
1083   BKE_icon_delete(gpl->runtime.icon_id);
1084
1085   BLI_freelinkN(&gpd->layers, gpl);
1086 }
1087
1088 Material *BKE_gpencil_brush_material_get(Brush *brush)
1089 {
1090   Material *ma = NULL;
1091
1092   if ((brush != NULL) && (brush->gpencil_settings != NULL) &&
1093       (brush->gpencil_settings->material != NULL)) {
1094     ma = brush->gpencil_settings->material;
1095   }
1096
1097   return ma;
1098 }
1099
1100 void BKE_gpencil_brush_material_set(Brush *brush, Material *ma)
1101 {
1102   BLI_assert(brush);
1103   BLI_assert(brush->gpencil_settings);
1104   if (brush->gpencil_settings->material != ma) {
1105     if (brush->gpencil_settings->material) {
1106       id_us_min(&brush->gpencil_settings->material->id);
1107     }
1108     if (ma) {
1109       id_us_plus(&ma->id);
1110     }
1111     brush->gpencil_settings->material = ma;
1112   }
1113 }
1114
1115 /* Adds the pinned material to the object if necessary. */
1116 Material *BKE_gpencil_object_material_ensure_from_brush(Main *bmain, Object *ob, Brush *brush)
1117 {
1118   if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) {
1119     Material *ma = BKE_gpencil_brush_material_get(brush);
1120
1121     /* check if the material is already on object material slots and add it if missing */
1122     if (ma && BKE_gpencil_object_material_get_index(ob, ma) < 0) {
1123       BKE_object_material_slot_add(bmain, ob);
1124       BKE_object_material_assign(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
1125     }
1126
1127     return ma;
1128   }
1129   else {
1130     /* using active material instead */
1131     return BKE_object_material_get(ob, ob->actcol);
1132   }
1133 }
1134
1135 /* Assigns the material to object (if not already present) and returns its index (mat_nr). */
1136 int BKE_gpencil_object_material_ensure(Main *bmain, Object *ob, Material *material)
1137 {
1138   if (!material) {
1139     return -1;
1140   }
1141   int index = BKE_gpencil_object_material_get_index(ob, material);
1142   if (index < 0) {
1143     BKE_object_material_slot_add(bmain, ob);
1144     BKE_object_material_assign(bmain, ob, material, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
1145     return ob->totcol - 1;
1146   }
1147   return index;
1148 }
1149
1150 /**
1151  * Creates a new gpencil material and assigns it to object.
1152  *
1153  * \param *r_index: value is set to zero based index of the new material if r_index is not NULL
1154  */
1155 Material *BKE_gpencil_object_material_new(Main *bmain, Object *ob, const char *name, int *r_index)
1156 {
1157   Material *ma = BKE_gpencil_material_add(bmain, name);
1158   id_us_min(&ma->id); /* no users yet */
1159
1160   BKE_object_material_slot_add(bmain, ob);
1161   BKE_object_material_assign(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
1162
1163   if (r_index) {
1164     *r_index = ob->actcol - 1;
1165   }
1166   return ma;
1167 }
1168
1169 /* Returns the material for a brush with respect to its pinned state. */
1170 Material *BKE_gpencil_object_material_get_from_brush(Object *ob, Brush *brush)
1171 {
1172   if ((brush) && (brush->gpencil_settings) &&
1173       (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED)) {
1174     Material *ma = BKE_gpencil_brush_material_get(brush);
1175     return ma;
1176   }
1177   else {
1178     return BKE_object_material_get(ob, ob->actcol);
1179   }
1180 }
1181
1182 /* Returns the material index for a brush with respect to its pinned state. */
1183 int BKE_gpencil_object_material_get_index_from_brush(Object *ob, Brush *brush)
1184 {
1185   if ((brush) && (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED)) {
1186     return BKE_gpencil_object_material_get_index(ob, brush->gpencil_settings->material);
1187   }
1188   else {
1189     return ob->actcol - 1;
1190   }
1191 }
1192
1193 /* Guaranteed to return a material assigned to object. Returns never NULL. */
1194 Material *BKE_gpencil_object_material_ensure_from_active_input_toolsettings(Main *bmain,
1195                                                                             Object *ob,
1196                                                                             ToolSettings *ts)
1197 {
1198   if (ts && ts->gp_paint && ts->gp_paint->paint.brush) {
1199     return BKE_gpencil_object_material_ensure_from_active_input_brush(
1200         bmain, ob, ts->gp_paint->paint.brush);
1201   }
1202   else {
1203     return BKE_gpencil_object_material_ensure_from_active_input_brush(bmain, ob, NULL);
1204   }
1205 }
1206
1207 /* Guaranteed to return a material assigned to object. Returns never NULL. */
1208 Material *BKE_gpencil_object_material_ensure_from_active_input_brush(Main *bmain,
1209                                                                      Object *ob,
1210                                                                      Brush *brush)
1211 {
1212   if (brush) {
1213     Material *ma = BKE_gpencil_object_material_ensure_from_brush(bmain, ob, brush);
1214     if (ma) {
1215       return ma;
1216     }
1217     else if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) {
1218       /* it is easier to just unpin a NULL material, instead of setting a new one */
1219       brush->gpencil_settings->flag &= ~GP_BRUSH_MATERIAL_PINNED;
1220     }
1221   }
1222   return BKE_gpencil_object_material_ensure_from_active_input_material(ob);
1223 }
1224
1225 /**
1226  * Guaranteed to return a material assigned to object. Returns never NULL.
1227  * Only use this for materials unrelated to user input.
1228  */
1229 Material *BKE_gpencil_object_material_ensure_from_active_input_material(Object *ob)
1230 {
1231   Material *ma = BKE_object_material_get(ob, ob->actcol);
1232   if (ma) {
1233     return ma;
1234   }
1235
1236   return BKE_material_default_gpencil();
1237 }
1238
1239 /* Get active color, and add all default settings if we don't find anything */
1240 Material *BKE_gpencil_object_material_ensure_active(Object *ob)
1241 {
1242   Material *ma = NULL;
1243
1244   /* sanity checks */
1245   if (ob == NULL) {
1246     return NULL;
1247   }
1248
1249   ma = BKE_gpencil_object_material_ensure_from_active_input_material(ob);
1250   if (ma->gp_style == NULL) {
1251     BKE_gpencil_material_attr_init(ma);
1252   }
1253
1254   return ma;
1255 }
1256
1257 /* ************************************************** */
1258 /* GP Object - Boundbox Support */
1259
1260 /**
1261  * Get min/max coordinate bounds for single stroke
1262  * \return Returns whether we found any selected points
1263  */
1264 bool BKE_gpencil_stroke_minmax(const bGPDstroke *gps,
1265                                const bool use_select,
1266                                float r_min[3],
1267                                float r_max[3])
1268 {
1269   const bGPDspoint *pt;
1270   int i;
1271   bool changed = false;
1272
1273   if (ELEM(NULL, gps, r_min, r_max)) {
1274     return false;
1275   }
1276
1277   for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1278     if ((use_select == false) || (pt->flag & GP_SPOINT_SELECT)) {
1279       minmax_v3v3_v3(r_min, r_max, &pt->x);
1280       changed = true;
1281     }
1282   }
1283   return changed;
1284 }
1285
1286 /* get min/max bounds of all strokes in GP datablock */
1287 bool BKE_gpencil_data_minmax(const bGPdata *gpd, float r_min[3], float r_max[3])
1288 {
1289   bool changed = false;
1290
1291   INIT_MINMAX(r_min, r_max);
1292
1293   if (gpd == NULL) {
1294     return changed;
1295   }
1296
1297   for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1298     bGPDframe *gpf = gpl->actframe;
1299
1300     if (gpf != NULL) {
1301       for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1302         changed = BKE_gpencil_stroke_minmax(gps, false, r_min, r_max);
1303       }
1304     }
1305   }
1306
1307   return changed;
1308 }
1309
1310 bool BKE_gpencil_stroke_select_check(const bGPDstroke *gps)
1311 {
1312   const bGPDspoint *pt;
1313   int i;
1314   for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1315     if (pt->flag & GP_SPOINT_SELECT) {
1316       return true;
1317     }
1318   }
1319   return false;
1320 }
1321
1322 /* compute center of bounding box */
1323 void BKE_gpencil_centroid_3d(bGPdata *gpd, float r_centroid[3])
1324 {
1325   float min[3], max[3], tot[3];
1326
1327   BKE_gpencil_data_minmax(gpd, min, max);
1328
1329   add_v3_v3v3(tot, min, max);
1330   mul_v3_v3fl(r_centroid, tot, 0.5f);
1331 }
1332
1333 /* create bounding box values */
1334 static void boundbox_gpencil(Object *ob)
1335 {
1336   BoundBox *bb;
1337   bGPdata *gpd;
1338   float min[3], max[3];
1339
1340   if (ob->runtime.bb == NULL) {
1341     ob->runtime.bb = MEM_callocN(sizeof(BoundBox), "GPencil boundbox");
1342   }
1343
1344   bb = ob->runtime.bb;
1345   gpd = ob->data;
1346
1347   if (!BKE_gpencil_data_minmax(gpd, min, max)) {
1348     min[0] = min[1] = min[2] = -1.0f;
1349     max[0] = max[1] = max[2] = 1.0f;
1350   }
1351
1352   BKE_boundbox_init_from_minmax(bb, min, max);
1353
1354   bb->flag &= ~BOUNDBOX_DIRTY;
1355 }
1356
1357 /* get bounding box */
1358 BoundBox *BKE_gpencil_boundbox_get(Object *ob)
1359 {
1360   if (ELEM(NULL, ob, ob->data)) {
1361     return NULL;
1362   }
1363
1364   bGPdata *gpd = (bGPdata *)ob->data;
1365   if ((ob->runtime.bb) && ((gpd->flag & GP_DATA_CACHE_IS_DIRTY) == 0)) {
1366     return ob->runtime.bb;
1367   }
1368
1369   boundbox_gpencil(ob);
1370
1371   return ob->runtime.bb;
1372 }
1373
1374 /* ************************************************** */
1375 /* Apply Transforms */
1376
1377 void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4])
1378 {
1379   if (gpd == NULL) {
1380     return;
1381   }
1382
1383   const float scalef = mat4_to_scale(mat);
1384   for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1385     /* FIXME: For now, we just skip parented layers.
1386      * Otherwise, we have to update each frame to find
1387      * the current parent position/effects.
1388      */
1389     if (gpl->parent) {
1390       continue;
1391     }
1392
1393     for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1394       for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1395         bGPDspoint *pt;
1396         int i;
1397
1398         for (pt = gps->points, i = 0; i < gps->totpoints; pt++, i++) {
1399           mul_m4_v3(mat, &pt->x);
1400           pt->pressure *= scalef;
1401         }
1402
1403         /* TODO: Do we need to do this? distortion may mean we need to re-triangulate */
1404         gps->flag |= GP_STROKE_RECALC_GEOMETRY;
1405         gps->tot_triangles = 0;
1406       }
1407     }
1408   }
1409 }
1410
1411 /* ************************************************** */
1412 /* GP Object - Vertex Groups */
1413
1414 /* remove a vertex group */
1415 void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup)
1416 {
1417   bGPdata *gpd = ob->data;
1418   MDeformVert *dvert = NULL;
1419   const int def_nr = BLI_findindex(&ob->defbase, defgroup);
1420   const int totgrp = BLI_listbase_count(&ob->defbase);
1421
1422   /* Remove points data */
1423   if (gpd) {
1424     for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1425       for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1426         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1427           if (gps->dvert != NULL) {
1428             for (int i = 0; i < gps->totpoints; i++) {
1429               dvert = &gps->dvert[i];
1430               MDeformWeight *dw = defvert_find_index(dvert, def_nr);
1431               if (dw != NULL) {
1432                 defvert_remove_group(dvert, dw);
1433               }
1434               else {
1435                 /* Reorganize weights for other groups after deleted one. */
1436                 for (int g = 0; g < totgrp; g++) {
1437                   dw = defvert_find_index(dvert, g);
1438                   if ((dw != NULL) && (dw->def_nr > def_nr)) {
1439                     dw->def_nr--;
1440                   }
1441                 }
1442               }
1443             }
1444           }
1445         }
1446       }
1447     }
1448   }
1449
1450   /* Remove the group */
1451   BLI_freelinkN(&ob->defbase, defgroup);
1452   DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1453 }
1454
1455 void BKE_gpencil_dvert_ensure(bGPDstroke *gps)
1456 {
1457   if (gps->dvert == NULL) {
1458     gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
1459   }
1460 }
1461
1462 /* ************************************************** */
1463
1464 static void stroke_defvert_create_nr_list(MDeformVert *dv_list,
1465                                           int count,
1466                                           ListBase *result,
1467                                           int *totweight)
1468 {
1469   LinkData *ld;
1470   MDeformVert *dv;
1471   MDeformWeight *dw;
1472   int i, j;
1473   int tw = 0;
1474   for (i = 0; i < count; i++) {
1475     dv = &dv_list[i];
1476
1477     /* find def_nr in list, if not exist, then create one */
1478     for (j = 0; j < dv->totweight; j++) {
1479       bool found = false;
1480       dw = &dv->dw[j];
1481       for (ld = result->first; ld; ld = ld->next) {
1482         if (ld->data == POINTER_FROM_INT(dw->def_nr)) {
1483           found = true;
1484           break;
1485         }
1486       }
1487       if (!found) {
1488         ld = MEM_callocN(sizeof(LinkData), "def_nr_item");
1489         ld->data = POINTER_FROM_INT(dw->def_nr);
1490         BLI_addtail(result, ld);
1491         tw++;
1492       }
1493     }
1494   }
1495
1496   *totweight = tw;
1497 }
1498
1499 static MDeformVert *stroke_defvert_new_count(int count, int totweight, ListBase *def_nr_list)
1500 {
1501   int i, j;
1502   LinkData *ld;
1503   MDeformVert *dst = MEM_mallocN(count * sizeof(MDeformVert), "new_deformVert");
1504
1505   for (i = 0; i < count; i++) {
1506     dst[i].dw = MEM_mallocN(sizeof(MDeformWeight) * totweight, "new_deformWeight");
1507     dst[i].totweight = totweight;
1508     j = 0;
1509     /* re-assign deform groups */
1510     for (ld = def_nr_list->first; ld; ld = ld->next) {
1511       dst[i].dw[j].def_nr = POINTER_AS_INT(ld->data);
1512       j++;
1513     }
1514   }
1515
1516   return dst;
1517 }
1518
1519 static void stroke_interpolate_deform_weights(
1520     bGPDstroke *gps, int index_from, int index_to, float ratio, MDeformVert *vert)
1521 {
1522   const MDeformVert *vl = &gps->dvert[index_from];
1523   const MDeformVert *vr = &gps->dvert[index_to];
1524   int i;
1525
1526   for (i = 0; i < vert->totweight; i++) {
1527     float wl = defvert_find_weight(vl, vert->dw[i].def_nr);
1528     float wr = defvert_find_weight(vr, vert->dw[i].def_nr);
1529     vert->dw[i].weight = interpf(wr, wl, ratio);
1530   }
1531 }
1532
1533 static int stroke_march_next_point(const bGPDstroke *gps,
1534                                    const int index_next_pt,
1535                                    const float *current,
1536                                    const float dist,
1537                                    float *result,
1538                                    float *pressure,
1539                                    float *strength,
1540                                    float *ratio_result,
1541                                    int *index_from,
1542                                    int *index_to)
1543 {
1544   float remaining_till_next = 0.0f;
1545   float remaining_march = dist;
1546   float step_start[3];
1547   float point[3];
1548   int next_point_index = index_next_pt;
1549   bGPDspoint *pt = NULL;
1550
1551   if (!(next_point_index < gps->totpoints)) {
1552     return -1;
1553   }
1554
1555   copy_v3_v3(step_start, current);
1556   pt = &gps->points[next_point_index];
1557   copy_v3_v3(point, &pt->x);
1558   remaining_till_next = len_v3v3(point, step_start);
1559
1560   while (remaining_till_next < remaining_march) {
1561     remaining_march -= remaining_till_next;
1562     pt = &gps->points[next_point_index];
1563     copy_v3_v3(point, &pt->x);
1564     copy_v3_v3(step_start, point);
1565     next_point_index++;
1566     if (!(next_point_index < gps->totpoints)) {
1567       next_point_index = gps->totpoints - 1;
1568       break;
1569     }
1570     pt = &gps->points[next_point_index];
1571     copy_v3_v3(point, &pt->x);
1572     remaining_till_next = len_v3v3(point, step_start);
1573   }
1574   if (remaining_till_next < remaining_march) {
1575     pt = &gps->points[next_point_index];
1576     copy_v3_v3(result, &pt->x);
1577     *pressure = gps->points[next_point_index].pressure;
1578     *strength = gps->points[next_point_index].strength;
1579
1580     *index_from = next_point_index - 1;
1581     *index_to = next_point_index;
1582     *ratio_result = 1.0f;
1583
1584     return 0;
1585   }
1586   else {
1587     float ratio = remaining_march / remaining_till_next;
1588     interp_v3_v3v3(result, step_start, point, ratio);
1589     *pressure = interpf(
1590         gps->points[next_point_index].pressure, gps->points[next_point_index - 1].pressure, ratio);
1591     *strength = interpf(
1592         gps->points[next_point_index].strength, gps->points[next_point_index - 1].strength, ratio);
1593
1594     *index_from = next_point_index - 1;
1595     *index_to = next_point_index;
1596     *ratio_result = ratio;
1597
1598     return next_point_index;
1599   }
1600 }
1601
1602 static int stroke_march_next_point_no_interp(const bGPDstroke *gps,
1603                                              const int index_next_pt,
1604                                              const float *current,
1605                                              const float dist,
1606                                              float *result)
1607 {
1608   float remaining_till_next = 0.0f;
1609   float remaining_march = dist;
1610   float step_start[3];
1611   float point[3];
1612   int next_point_index = index_next_pt;
1613   bGPDspoint *pt = NULL;
1614
1615   if (!(next_point_index < gps->totpoints)) {
1616     return -1;
1617   }
1618
1619   copy_v3_v3(step_start, current);
1620   pt = &gps->points[next_point_index];
1621   copy_v3_v3(point, &pt->x);
1622   remaining_till_next = len_v3v3(point, step_start);
1623
1624   while (remaining_till_next < remaining_march) {
1625     remaining_march -= remaining_till_next;
1626     pt = &gps->points[next_point_index];
1627     copy_v3_v3(point, &pt->x);
1628     copy_v3_v3(step_start, point);
1629     next_point_index++;
1630     if (!(next_point_index < gps->totpoints)) {
1631       next_point_index = gps->totpoints - 1;
1632       break;
1633     }
1634     pt = &gps->points[next_point_index];
1635     copy_v3_v3(point, &pt->x);
1636     remaining_till_next = len_v3v3(point, step_start);
1637   }
1638   if (remaining_till_next < remaining_march) {
1639     pt = &gps->points[next_point_index];
1640     copy_v3_v3(result, &pt->x);
1641     return 0;
1642   }
1643   else {
1644     float ratio = remaining_march / remaining_till_next;
1645     interp_v3_v3v3(result, step_start, point, ratio);
1646     return next_point_index;
1647   }
1648 }
1649
1650 static int stroke_march_count(const bGPDstroke *gps, const float dist)
1651 {
1652   int point_count = 0;
1653   float point[3];
1654   int next_point_index = 1;
1655   bGPDspoint *pt = NULL;
1656
1657   pt = &gps->points[0];
1658   copy_v3_v3(point, &pt->x);
1659   point_count++;
1660
1661   while ((next_point_index = stroke_march_next_point_no_interp(
1662               gps, next_point_index, point, dist, point)) > -1) {
1663     point_count++;
1664     if (next_point_index == 0) {
1665       break; /* last point finished */
1666     }
1667   }
1668   return point_count;
1669 }
1670
1671 /**
1672  * Resample a stroke
1673  * \param gps: Stroke to sample
1674  * \param dist: Distance of one segment
1675  */
1676 bool BKE_gpencil_sample_stroke(bGPDstroke *gps, const float dist, const bool select)
1677 {
1678   bGPDspoint *pt = gps->points;
1679   bGPDspoint *pt1 = NULL;
1680   bGPDspoint *pt2 = NULL;
1681   int i;
1682   LinkData *ld;
1683   ListBase def_nr_list = {0};
1684
1685   if (gps->totpoints < 2 || dist < FLT_EPSILON) {
1686     return false;
1687   }
1688   /* TODO: Implement feature point preservation. */
1689   int count = stroke_march_count(gps, dist);
1690
1691   bGPDspoint *new_pt = MEM_callocN(sizeof(bGPDspoint) * count, "gp_stroke_points_sampled");
1692   MDeformVert *new_dv = NULL;
1693
1694   int result_totweight;
1695
1696   if (gps->dvert != NULL) {
1697     stroke_defvert_create_nr_list(gps->dvert, gps->totpoints, &def_nr_list, &result_totweight);
1698     new_dv = stroke_defvert_new_count(count, result_totweight, &def_nr_list);
1699   }
1700
1701   int next_point_index = 1;
1702   i = 0;
1703   float pressure, strength, ratio_result;
1704   int index_from, index_to;
1705   float last_coord[3];
1706
1707   /*  1st point is always at the start */
1708   pt1 = &gps->points[0];
1709   copy_v3_v3(last_coord, &pt1->x);
1710   pt2 = &new_pt[i];
1711   copy_v3_v3(&pt2->x, last_coord);
1712   new_pt[i].pressure = pt[0].pressure;
1713   new_pt[i].strength = pt[0].strength;
1714   if (select) {
1715     new_pt[i].flag |= GP_SPOINT_SELECT;
1716   }
1717   i++;
1718
1719   if (new_dv) {
1720     stroke_interpolate_deform_weights(gps, 0, 0, 0, &new_dv[0]);
1721   }
1722
1723   /*  the rest */
1724   while ((next_point_index = stroke_march_next_point(gps,
1725                                                      next_point_index,
1726                                                      last_coord,
1727                                                      dist,
1728                                                      last_coord,
1729                                                      &pressure,
1730                                                      &strength,
1731                                                      &ratio_result,
1732                                                      &index_from,
1733                                                      &index_to)) > -1) {
1734     pt2 = &new_pt[i];
1735     copy_v3_v3(&pt2->x, last_coord);
1736     new_pt[i].pressure = pressure;
1737     new_pt[i].strength = strength;
1738     if (select) {
1739       new_pt[i].flag |= GP_SPOINT_SELECT;
1740     }
1741
1742     if (new_dv) {
1743       stroke_interpolate_deform_weights(gps, index_from, index_to, ratio_result, &new_dv[i]);
1744     }
1745
1746     i++;
1747     if (next_point_index == 0) {
1748       break; /* last point finished */
1749     }
1750   }
1751
1752   gps->points = new_pt;
1753   /* Free original vertex list. */
1754   MEM_freeN(pt);
1755
1756   if (new_dv) {
1757     /* Free original weight data. */
1758     BKE_gpencil_free_stroke_weights(gps);
1759     MEM_freeN(gps->dvert);
1760     while ((ld = BLI_pophead(&def_nr_list))) {
1761       MEM_freeN(ld);
1762     }
1763
1764     gps->dvert = new_dv;
1765   }
1766
1767   gps->totpoints = i;
1768
1769   gps->flag |= GP_STROKE_RECALC_GEOMETRY;
1770   gps->tot_triangles = 0;
1771
1772   return true;
1773 }
1774
1775 /**
1776  * Backbone stretch similar to Freestyle.
1777  * \param gps: Stroke to sample
1778  * \param dist: Distance of one segment
1779  * \param tip_length: Ignore tip jittering, set zero to use default value.
1780  */
1781 bool BKE_gpencil_stretch_stroke(bGPDstroke *gps, const float dist, const float tip_length)
1782 {
1783   bGPDspoint *pt = gps->points, *last_pt, *second_last, *next_pt;
1784   int i;
1785   float threshold = (tip_length == 0 ? 0.001f : tip_length);
1786
1787   if (gps->totpoints < 2 || dist < FLT_EPSILON) {
1788     return false;
1789   }
1790
1791   last_pt = &pt[gps->totpoints - 1];
1792   second_last = &pt[gps->totpoints - 2];
1793   next_pt = &pt[1];
1794
1795   float len1 = 0.0f;
1796   float len2 = 0.0f;
1797
1798   i = 1;
1799   while (len1 < threshold && gps->totpoints > i) {
1800     next_pt = &pt[i];
1801     len1 = len_v3v3(&next_pt->x, &pt->x);
1802     i++;
1803   }
1804
1805   i = 2;
1806   while (len2 < threshold && gps->totpoints >= i) {
1807     second_last = &pt[gps->totpoints - i];
1808     len2 = len_v3v3(&last_pt->x, &second_last->x);
1809     i++;
1810   }
1811
1812   float extend1 = (len1 + dist) / len1;
1813   float extend2 = (len2 + dist) / len2;
1814
1815   float result1[3], result2[3];
1816
1817   interp_v3_v3v3(result1, &next_pt->x, &pt->x, extend1);
1818   interp_v3_v3v3(result2, &second_last->x, &last_pt->x, extend2);
1819
1820   copy_v3_v3(&pt->x, result1);
1821   copy_v3_v3(&last_pt->x, result2);
1822
1823   return true;
1824 }
1825
1826 /**
1827  * Trim stroke to needed segments
1828  * \param gps: Target stroke
1829  * \param index_from: the index of the first point to be used in the trimmed result
1830  * \param index_to: the index of the last point to be used in the trimmed result
1831  */
1832 bool BKE_gpencil_trim_stroke_points(bGPDstroke *gps, const int index_from, const int index_to)
1833 {
1834   bGPDspoint *pt = gps->points, *new_pt;
1835   MDeformVert *dv, *new_dv;
1836
1837   const int new_count = index_to - index_from + 1;
1838
1839   if (new_count >= gps->totpoints) {
1840     return false;
1841   }
1842
1843   if (new_count == 1) {
1844     BKE_gpencil_free_stroke_weights(gps);
1845     MEM_freeN(gps->points);
1846     gps->points = NULL;
1847     gps->dvert = NULL;
1848     gps->totpoints = 0;
1849     return false;
1850   }
1851
1852   new_pt = MEM_callocN(sizeof(bGPDspoint) * new_count, "gp_stroke_points_trimmed");
1853
1854   for (int i = 0; i < new_count; i++) {
1855     memcpy(&new_pt[i], &pt[i + index_from], sizeof(bGPDspoint));
1856   }
1857
1858   if (gps->dvert) {
1859     new_dv = MEM_callocN(sizeof(MDeformVert) * new_count, "gp_stroke_dverts_trimmed");
1860     for (int i = 0; i < new_count; i++) {
1861       dv = &gps->dvert[i + index_from];
1862       new_dv[i].flag = dv->flag;
1863       new_dv[i].totweight = dv->totweight;
1864       new_dv[i].dw = MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
1865                                  "gp_stroke_dverts_dw_trimmed");
1866       for (int j = 0; j < dv->totweight; j++) {
1867         new_dv[i].dw[j].weight = dv->dw[j].weight;
1868         new_dv[i].dw[j].def_nr = dv->dw[j].def_nr;
1869       }
1870     }
1871     MEM_freeN(gps->dvert);
1872     gps->dvert = new_dv;
1873   }
1874
1875   MEM_freeN(gps->points);
1876   gps->points = new_pt;
1877   gps->totpoints = new_count;
1878
1879   return true;
1880 }
1881
1882 bool BKE_gpencil_split_stroke(bGPDframe *gpf,
1883                               bGPDstroke *gps,
1884                               const int before_index,
1885                               bGPDstroke **remaining_gps)
1886 {
1887   bGPDstroke *new_gps;
1888   bGPDspoint *pt = gps->points, *new_pt;
1889   MDeformVert *dv, *new_dv;
1890
1891   if (before_index >= gps->totpoints || before_index == 0) {
1892     return false;
1893   }
1894
1895   const int new_count = gps->totpoints - before_index;
1896   const int old_count = before_index;
1897
1898   /* Handle remaining segments first. */
1899
1900   new_gps = BKE_gpencil_add_stroke_existing_style(
1901       gpf, gps, gps->mat_nr, new_count, gps->thickness);
1902
1903   new_pt = new_gps->points; /* Allocated from above. */
1904
1905   for (int i = 0; i < new_count; i++) {
1906     memcpy(&new_pt[i], &pt[i + before_index], sizeof(bGPDspoint));
1907   }
1908
1909   if (gps->dvert) {
1910     new_dv = MEM_callocN(sizeof(MDeformVert) * new_count, "gp_stroke_dverts_remaining");
1911     for (int i = 0; i < new_count; i++) {
1912       dv = &gps->dvert[i + before_index];
1913       new_dv[i].flag = dv->flag;
1914       new_dv[i].totweight = dv->totweight;
1915       new_dv[i].dw = MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
1916                                  "gp_stroke_dverts_dw_remaining");
1917       for (int j = 0; j < dv->totweight; j++) {
1918         new_dv[i].dw[j].weight = dv->dw[j].weight;
1919         new_dv[i].dw[j].def_nr = dv->dw[j].def_nr;
1920       }
1921     }
1922     new_gps->dvert = new_dv;
1923   }
1924
1925   (*remaining_gps) = new_gps;
1926
1927   /* Trim the original stroke into a shorter one.
1928    * Keep the end point. */
1929
1930   BKE_gpencil_trim_stroke_points(gps, 0, old_count);
1931
1932   return true;
1933 }
1934
1935 /**
1936  * Shrink the stroke by length.
1937  * \param gps: Stroke to shrink
1938  * \param dist: delta length
1939  */
1940 bool BKE_gpencil_shrink_stroke(bGPDstroke *gps, const float dist)
1941 {
1942   bGPDspoint *pt = gps->points, *second_last;
1943   int i;
1944
1945   if (gps->totpoints < 2 || dist < FLT_EPSILON) {
1946     return false;
1947   }
1948
1949   second_last = &pt[gps->totpoints - 2];
1950
1951   float len1, this_len1, cut_len1;
1952   float len2, this_len2, cut_len2;
1953   int index_start, index_end;
1954
1955   len1 = len2 = this_len1 = this_len2 = cut_len1 = cut_len2 = 0.0f;
1956
1957   i = 1;
1958   while (len1 < dist && gps->totpoints > i - 1) {
1959     this_len1 = len_v3v3(&pt[i].x, &pt[i + 1].x);
1960     len1 += this_len1;
1961     cut_len1 = len1 - dist;
1962     i++;
1963   }
1964   index_start = i - 2;
1965
1966   i = 2;
1967   while (len2 < dist && gps->totpoints >= i) {
1968     second_last = &pt[gps->totpoints - i];
1969     this_len2 = len_v3v3(&second_last[1].x, &second_last->x);
1970     len2 += this_len2;
1971     cut_len2 = len2 - dist;
1972     i++;
1973   }
1974   index_end = gps->totpoints - i + 2;
1975
1976   if (len1 < dist || len2 < dist || index_end <= index_start) {
1977     index_start = index_end = 0; /* empty stroke */
1978   }
1979
1980   if ((index_end == index_start + 1) && (cut_len1 + cut_len2 > 1.0f)) {
1981     index_start = index_end = 0; /* no length left to cut */
1982   }
1983
1984   BKE_gpencil_trim_stroke_points(gps, index_start, index_end);
1985
1986   if (gps->totpoints == 0) {
1987     return false;
1988   }
1989
1990   pt = gps->points;
1991
1992   float cut1 = cut_len1 / this_len1;
1993   float cut2 = cut_len2 / this_len2;
1994
1995   float result1[3], result2[3];
1996
1997   interp_v3_v3v3(result1, &pt[1].x, &pt[0].x, cut1);
1998   interp_v3_v3v3(result2, &pt[gps->totpoints - 2].x, &pt[gps->totpoints - 1].x, cut2);
1999
2000   copy_v3_v3(&pt[0].x, result1);
2001   copy_v3_v3(&pt[gps->totpoints - 1].x, result2);
2002
2003   return true;
2004 }
2005
2006 /**
2007  * Apply smooth to stroke point
2008  * \param gps: Stroke to smooth
2009  * \param i: Point index
2010  * \param inf: Amount of smoothing to apply
2011  */
2012 bool BKE_gpencil_smooth_stroke(bGPDstroke *gps, int i, float inf)
2013 {
2014   bGPDspoint *pt = &gps->points[i];
2015   float sco[3] = {0.0f};
2016
2017   /* Do nothing if not enough points to smooth out */
2018   if (gps->totpoints <= 2) {
2019     return false;
2020   }
2021
2022   /* Only affect endpoints by a fraction of the normal strength,
2023    * to prevent the stroke from shrinking too much
2024    */
2025   if ((i == 0) || (i == gps->totpoints - 1)) {
2026     inf *= 0.1f;
2027   }
2028
2029   /* Compute smoothed coordinate by taking the ones nearby */
2030   /* XXX: This is potentially slow,
2031    *      and suffers from accumulation error as earlier points are handled before later ones. */
2032   {
2033     /* XXX: this is hardcoded to look at 2 points on either side of the current one
2034      * (i.e. 5 items total). */
2035     const int steps = 2;
2036     const float average_fac = 1.0f / (float)(steps * 2 + 1);
2037     int step;
2038
2039     /* add the point itself */
2040     madd_v3_v3fl(sco, &pt->x, average_fac);
2041
2042     /* n-steps before/after current point */
2043     /* XXX: review how the endpoints are treated by this algorithm. */
2044     /* XXX: falloff measures should also introduce some weighting variations,
2045      *      so that further-out points get less weight. */
2046     for (step = 1; step <= steps; step++) {
2047       bGPDspoint *pt1, *pt2;
2048       int before = i - step;
2049       int after = i + step;
2050
2051       CLAMP_MIN(before, 0);
2052       CLAMP_MAX(after, gps->totpoints - 1);
2053
2054       pt1 = &gps->points[before];
2055       pt2 = &gps->points[after];
2056
2057       /* add both these points to the average-sum (s += p[i]/n) */
2058       madd_v3_v3fl(sco, &pt1->x, average_fac);
2059       madd_v3_v3fl(sco, &pt2->x, average_fac);
2060     }
2061   }
2062
2063   /* Based on influence factor, blend between original and optimal smoothed coordinate */
2064   interp_v3_v3v3(&pt->x, &pt->x, sco, inf);
2065
2066   return true;
2067 }
2068
2069 /**
2070  * Apply smooth for strength to stroke point */
2071 bool BKE_gpencil_smooth_stroke_strength(bGPDstroke *gps, int point_index, float influence)
2072 {
2073   bGPDspoint *ptb = &gps->points[point_index];
2074
2075   /* Do nothing if not enough points */
2076   if ((gps->totpoints <= 2) || (point_index < 1)) {
2077     return false;
2078   }
2079   /* Only affect endpoints by a fraction of the normal influence */
2080   float inf = influence;
2081   if ((point_index == 0) || (point_index == gps->totpoints - 1)) {
2082     inf *= 0.01f;
2083   }
2084   /* Limit max influence to reduce pop effect. */
2085   CLAMP_MAX(inf, 0.98f);
2086
2087   float total = 0.0f;
2088   float max_strength = 0.0f;
2089   const int steps = 4;
2090   const float average_fac = 1.0f / (float)(steps * 2 + 1);
2091   int step;
2092
2093   /* add the point itself */
2094   total += ptb->strength * average_fac;
2095   max_strength = ptb->strength;
2096
2097   /* n-steps before/after current point */
2098   for (step = 1; step <= steps; step++) {
2099     bGPDspoint *pt1, *pt2;
2100     int before = point_index - step;
2101     int after = point_index + step;
2102
2103     CLAMP_MIN(before, 0);
2104     CLAMP_MAX(after, gps->totpoints - 1);
2105
2106     pt1 = &gps->points[before];
2107     pt2 = &gps->points[after];
2108
2109     /* add both these points to the average-sum (s += p[i]/n) */
2110     total += pt1->strength * average_fac;
2111     total += pt2->strength * average_fac;
2112     /* Save max value. */
2113     if (max_strength < pt1->strength) {
2114       max_strength = pt1->strength;
2115     }
2116     if (max_strength < pt2->strength) {
2117       max_strength = pt2->strength;
2118     }
2119   }
2120
2121   /* Based on influence factor, blend between original and optimal smoothed value. */
2122   ptb->strength = interpf(ptb->strength, total, inf);
2123   /* Clamp to maximum stroke strength to avoid weird results. */
2124   CLAMP_MAX(ptb->strength, max_strength);
2125
2126   return true;
2127 }
2128
2129 /**
2130  * Apply smooth for thickness to stroke point (use pressure) */
2131 bool BKE_gpencil_smooth_stroke_thickness(bGPDstroke *gps, int point_index, float influence)
2132 {
2133   bGPDspoint *ptb = &gps->points[point_index];
2134
2135   /* Do nothing if not enough points */
2136   if ((gps->totpoints <= 2) || (point_index < 1)) {
2137     return false;
2138   }
2139   /* Only affect endpoints by a fraction of the normal influence */
2140   float inf = influence;
2141   if ((point_index == 0) || (point_index == gps->totpoints - 1)) {
2142     inf *= 0.01f;
2143   }
2144   /* Limit max influence to reduce pop effect. */
2145   CLAMP_MAX(inf, 0.98f);
2146
2147   float total = 0.0f;
2148   float max_pressure = 0.0f;
2149   const int steps = 4;
2150   const float average_fac = 1.0f / (float)(steps * 2 + 1);
2151   int step;
2152
2153   /* add the point itself */
2154   total += ptb->pressure * average_fac;
2155   max_pressure = ptb->pressure;
2156
2157   /* n-steps before/after current point */
2158   for (step = 1; step <= steps; step++) {
2159     bGPDspoint *pt1, *pt2;
2160     int before = point_index - step;
2161     int after = point_index + step;
2162
2163     CLAMP_MIN(before, 0);
2164     CLAMP_MAX(after, gps->totpoints - 1);
2165
2166     pt1 = &gps->points[before];
2167     pt2 = &gps->points[after];
2168
2169     /* add both these points to the average-sum (s += p[i]/n) */
2170     total += pt1->pressure * average_fac;
2171     total += pt2->pressure * average_fac;
2172     /* Save max value. */
2173     if (max_pressure < pt1->pressure) {
2174       max_pressure = pt1->pressure;
2175     }
2176     if (max_pressure < pt2->pressure) {
2177       max_pressure = pt2->pressure;
2178     }
2179   }
2180
2181   /* Based on influence factor, blend between original and optimal smoothed value. */
2182   ptb->pressure = interpf(ptb->pressure, total, inf);
2183   /* Clamp to maximum stroke thickness to avoid weird results. */
2184   CLAMP_MAX(ptb->pressure, max_pressure);
2185   return true;
2186 }
2187
2188 /**
2189  * Apply smooth for UV rotation to stroke point (use pressure).
2190  */
2191 bool BKE_gpencil_smooth_stroke_uv(bGPDstroke *gps, int point_index, float influence)
2192 {
2193   bGPDspoint *ptb = &gps->points[point_index];
2194
2195   /* Do nothing if not enough points */
2196   if (gps->totpoints <= 2) {
2197     return false;
2198   }
2199
2200   /* Compute theoretical optimal value */
2201   bGPDspoint *pta, *ptc;
2202   int before = point_index - 1;
2203   int after = point_index + 1;
2204
2205   CLAMP_MIN(before, 0);
2206   CLAMP_MAX(after, gps->totpoints - 1);
2207
2208   pta = &gps->points[before];
2209   ptc = &gps->points[after];
2210
2211   /* the optimal value is the corresponding to the interpolation of the pressure
2212    * at the distance of point b
2213    */
2214   float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
2215   /* sometimes the factor can be wrong due stroke geometry, so use middle point */
2216   if ((fac < 0.0f) || (fac > 1.0f)) {
2217     fac = 0.5f;
2218   }
2219   float optimal = interpf(ptc->uv_rot, pta->uv_rot, fac);
2220
2221   /* Based on influence factor, blend between original and optimal */
2222   ptb->uv_rot = interpf(optimal, ptb->uv_rot, influence);
2223   CLAMP(ptb->uv_rot, -M_PI_2, M_PI_2);
2224
2225   return true;
2226 }
2227
2228 /**
2229  * Get range of selected frames in layer.
2230  * Always the active frame is considered as selected, so if no more selected the range
2231  * will be equal to the current active frame.
2232  * \param gpl: Layer
2233  * \param r_initframe: Number of first selected frame
2234  * \param r_endframe: Number of last selected frame
2235  */
2236 void BKE_gpencil_get_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_endframe)
2237 {
2238   *r_initframe = gpl->actframe->framenum;
2239   *r_endframe = gpl->actframe->framenum;
2240
2241   for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
2242     if (gpf->flag & GP_FRAME_SELECT) {
2243       if (gpf->framenum < *r_initframe) {
2244         *r_initframe = gpf->framenum;
2245       }
2246       if (gpf->framenum > *r_endframe) {
2247         *r_endframe = gpf->framenum;
2248       }
2249     }
2250   }
2251 }
2252
2253 /**
2254  * Get Falloff factor base on frame range
2255  * \param gpf: Frame
2256  * \param actnum: Number of active frame in layer
2257  * \param f_init: Number of first selected frame
2258  * \param f_end: Number of last selected frame
2259  * \param cur_falloff: Curve with falloff factors
2260  */
2261 float BKE_gpencil_multiframe_falloff_calc(
2262     bGPDframe *gpf, int actnum, int f_init, int f_end, CurveMapping *cur_falloff)
2263 {
2264   float fnum = 0.5f; /* default mid curve */
2265   float value;
2266
2267   /* check curve is available */
2268   if (cur_falloff == NULL) {
2269     return 1.0f;
2270   }
2271
2272   /* frames to the right of the active frame */
2273   if (gpf->framenum < actnum) {
2274     fnum = (float)(gpf->framenum - f_init) / (actnum - f_init);
2275     fnum *= 0.5f;
2276     value = BKE_curvemapping_evaluateF(cur_falloff, 0, fnum);
2277   }
2278   /* frames to the left of the active frame */
2279   else if (gpf->framenum > actnum) {
2280     fnum = (float)(gpf->framenum - actnum) / (f_end - actnum);
2281     fnum *= 0.5f;
2282     value = BKE_curvemapping_evaluateF(cur_falloff, 0, fnum + 0.5f);
2283   }
2284   else {
2285     value = 1.0f;
2286   }
2287
2288   return value;
2289 }
2290
2291 /* reassign strokes using a material */
2292 void BKE_gpencil_material_index_reassign(bGPdata *gpd, int totcol, int index)
2293 {
2294   for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
2295     for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
2296       for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
2297         /* reassign strokes */
2298         if ((gps->mat_nr > index) || (gps->mat_nr > totcol - 1)) {
2299           gps->mat_nr--;
2300           CLAMP_MIN(gps->mat_nr, 0);
2301         }
2302       }
2303     }
2304   }
2305 }
2306
2307 /* remove strokes using a material */
2308 bool BKE_gpencil_material_index_used(bGPdata *gpd, int index)
2309 {
2310   for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
2311     for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
2312       for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
2313         if (gps->mat_nr == index) {
2314           return true;
2315         }
2316       }
2317     }
2318   }
2319
2320   return false;
2321 }
2322
2323 void BKE_gpencil_material_remap(struct bGPdata *gpd,
2324                                 const unsigned int *remap,
2325                                 unsigned int remap_len)
2326 {
2327   const short remap_len_short = (short)remap_len;
2328
2329 #define MAT_NR_REMAP(n) \
2330   if (n < remap_len_short) { \
2331     BLI_assert(n >= 0 && remap[n] < remap_len_short); \
2332     n = remap[n]; \
2333   } \
2334   ((void)0)
2335
2336   for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
2337     for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
2338       for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
2339         /* reassign strokes */
2340         MAT_NR_REMAP(gps->mat_nr);
2341       }
2342     }
2343   }
2344
2345 #undef MAT_NR_REMAP
2346 }
2347
2348 /* statistics functions */
2349 void BKE_gpencil_stats_update(bGPdata *gpd)
2350 {
2351   gpd->totlayer = 0;
2352   gpd->totframe = 0;
2353   gpd->totstroke = 0;
2354   gpd->totpoint = 0;
2355
2356   for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
2357     gpd->totlayer++;
2358     for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
2359       gpd->totframe++;
2360       for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
2361         gpd->totstroke++;
2362         gpd->totpoint += gps->totpoints;
2363       }
2364     }
2365   }
2366 }
2367
2368 /* get material index (0-based like mat_nr not actcol) */
2369 int BKE_gpencil_object_material_get_index(Object *ob, Material *ma)
2370 {
2371   short *totcol = BKE_object_material_num(ob);
2372   Material *read_ma = NULL;
2373   for (short i = 0; i < *totcol; i++) {
2374     read_ma = BKE_object_material_get(ob, i + 1);
2375     if (ma == read_ma) {
2376       return i;
2377     }
2378   }
2379
2380   return -1;
2381 }
2382
2383 /* Get points of stroke always flat to view not affected by camera view or view position */
2384 void BKE_gpencil_stroke_2d_flat(const bGPDspoint *points,
2385                                 int totpoints,
2386                                 float (*points2d)[2],
2387                                 int *r_direction)
2388 {
2389   BLI_assert(totpoints >= 2);
2390
2391   const bGPDspoint *pt0 = &points[0];
2392   const bGPDspoint *pt1 = &points[1];
2393   const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
2394
2395   float locx[3];
2396   float locy[3];
2397   float loc3[3];
2398   float normal[3];
2399
2400   /* local X axis (p0 -> p1) */
2401   sub_v3_v3v3(locx, &pt1->x, &pt0->x);
2402
2403   /* point vector at 3/4 */
2404   float v3[3];
2405   if (totpoints == 2) {
2406     mul_v3_v3fl(v3, &pt3->x, 0.001f);
2407   }
2408   else {
2409     copy_v3_v3(v3, &pt3->x);
2410   }
2411
2412   sub_v3_v3v3(loc3, v3, &pt0->x);
2413
2414   /* vector orthogonal to polygon plane */
2415   cross_v3_v3v3(normal, locx, loc3);
2416
2417   /* local Y axis (cross to normal/x axis) */
2418   cross_v3_v3v3(locy, normal, locx);
2419
2420   /* Normalize vectors */
2421   normalize_v3(locx);
2422   normalize_v3(locy);
2423
2424   /* Get all points in local space */
2425   for (int i = 0; i < totpoints; i++) {
2426     const bGPDspoint *pt = &points[i];
2427     float loc[3];
2428
2429     /* Get local space using first point as origin */
2430     sub_v3_v3v3(loc, &pt->x, &pt0->x);
2431
2432     points2d[i][0] = dot_v3v3(loc, locx);
2433     points2d[i][1] = dot_v3v3(loc, locy);
2434   }
2435
2436   /* Concave (-1), Convex (1), or Autodetect (0)? */
2437   *r_direction = (int)locy[2];
2438 }
2439
2440 /* Get points of stroke always flat to view not affected by camera view or view position
2441  * using another stroke as reference
2442  */
2443 void BKE_gpencil_stroke_2d_flat_ref(const bGPDspoint *ref_points,
2444                                     int ref_totpoints,
2445                                     const bGPDspoint *points,
2446                                     int totpoints,
2447                                     float (*points2d)[2],
2448                                     const float scale,
2449                                     int *r_direction)
2450 {
2451   BLI_assert(totpoints >= 2);
2452
2453   const bGPDspoint *pt0 = &ref_points[0];
2454   const bGPDspoint *pt1 = &ref_points[1];
2455   const bGPDspoint *pt3 = &ref_points[(int)(ref_totpoints * 0.75)];
2456
2457   float locx[3];
2458   float locy[3];
2459   float loc3[3];
2460   float normal[3];
2461
2462   /* local X axis (p0 -> p1) */
2463   sub_v3_v3v3(locx, &pt1->x, &pt0->x);
2464
2465   /* point vector at 3/4 */
2466   float v3[3];
2467   if (totpoints == 2) {
2468     mul_v3_v3fl(v3, &pt3->x, 0.001f);
2469   }
2470   else {
2471     copy_v3_v3(v3, &pt3->x);
2472   }
2473
2474   sub_v3_v3v3(loc3, v3, &pt0->x);
2475
2476   /* vector orthogonal to polygon plane */
2477   cross_v3_v3v3(normal, locx, loc3);
2478
2479   /* local Y axis (cross to normal/x axis) */
2480   cross_v3_v3v3(locy, normal, locx);
2481
2482   /* Normalize vectors */
2483   normalize_v3(locx);
2484   normalize_v3(locy);
2485
2486   /* Get all points in local space */
2487   for (int i = 0; i < totpoints; i++) {
2488     const bGPDspoint *pt = &points[i];
2489     float loc[3];
2490     float v1[3];
2491     float vn[3] = {0.0f, 0.0f, 0.0f};
2492
2493     /* apply scale to extremes of the stroke to get better collision detection
2494      * the scale is divided to get more control in the UI parameter
2495      */
2496     /* first point */
2497     if (i == 0) {
2498       const bGPDspoint *pt_next = &points[i + 1];
2499       sub_v3_v3v3(vn, &pt->x, &pt_next->x);
2500       normalize_v3(vn);
2501       mul_v3_fl(vn, scale / 10.0f);
2502       add_v3_v3v3(v1, &pt->x, vn);
2503     }
2504     /* last point */
2505     else if (i == totpoints - 1) {
2506       const bGPDspoint *pt_prev = &points[i - 1];
2507       sub_v3_v3v3(vn, &pt->x, &pt_prev->x);
2508       normalize_v3(vn);
2509       mul_v3_fl(vn, scale / 10.0f);
2510       add_v3_v3v3(v1, &pt->x, vn);
2511     }
2512     else {
2513       copy_v3_v3(v1, &pt->x);
2514     }
2515
2516     /* Get local space using first point as origin (ref stroke) */
2517     sub_v3_v3v3(loc, v1, &pt0->x);
2518
2519     points2d[i][0] = dot_v3v3(loc, locx);
2520     points2d[i][1] = dot_v3v3(loc, locy);
2521   }
2522
2523   /* Concave (-1), Convex (1), or Autodetect (0)? */
2524   *r_direction = (int)locy[2];
2525 }
2526
2527 /* calc bounding box in 2d using flat projection data */
2528 static void gpencil_calc_2d_bounding_box(const float (*points2d)[2],
2529                                          int totpoints,
2530                                          float minv[2],
2531                                          float maxv[2])
2532 {
2533   minv[0] = points2d[0][0];
2534   minv[1] = points2d[0][1];
2535   maxv[0] = points2d[0][0];
2536   maxv[1] = points2d[0][1];
2537
2538   for (int i = 1; i < totpoints; i++) {
2539     /* min */
2540     if (points2d[i][0] < minv[0]) {
2541       minv[0] = points2d[i][0];
2542     }
2543     if (points2d[i][1] < minv[1]) {
2544       minv[1] = points2d[i][1];
2545     }
2546     /* max */
2547     if (points2d[i][0] > maxv[0]) {
2548       maxv[0] = points2d[i][0];
2549     }
2550     if (points2d[i][1] > maxv[1]) {
2551       maxv[1] = points2d[i][1];
2552     }
2553   }
2554   /* use a perfect square */
2555   if (maxv[0] > maxv[1]) {
2556     maxv[1] = maxv[0];
2557   }
2558   else {
2559     maxv[0] = maxv[1];
2560   }
2561 }
2562
2563 /* calc texture coordinates using flat projected points */
2564 static void gpencil_calc_stroke_fill_uv(const float (*points2d)[2],
2565                                         int totpoints,
2566                                         const float minv[2],
2567                                         float maxv[2],
2568                                         float (*r_uv)[2])
2569 {
2570   float d[2];
2571   d[0] = maxv[0] - minv[0];
2572   d[1] = maxv[1] - minv[1];
2573   for (int i = 0; i < totpoints; i++) {
2574     r_uv[i][0] = (points2d[i][0] - minv[0]) / d[0];
2575     r_uv[i][1] = (points2d[i][1] - minv[1]) / d[1];
2576   }
2577 }
2578
2579 /* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was
2580  * modified) */
2581 void BKE_gpencil_triangulate_stroke_fill(bGPdata *gpd, bGPDstroke *gps)
2582 {
2583   BLI_assert(gps->totpoints >= 3);
2584
2585   /* allocate memory for temporary areas */
2586   gps->tot_triangles = gps->totpoints - 2;
2587   uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles,
2588                                         "GP Stroke temp triangulation");
2589   float(*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints,
2590                                     "GP Stroke temp 2d points");
2591   float(*uv)[2] = MEM_mallocN(sizeof(*uv) * gps->totpoints, "GP Stroke temp 2d uv data");
2592
2593   int direction = 0;
2594
2595   /* convert to 2d and triangulate */
2596   BKE_gpencil_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction);
2597   BLI_polyfill_calc(points2d, (uint)gps->totpoints, direction, tmp_triangles);
2598
2599   /* calc texture coordinates automatically */
2600   float minv[2];
2601   float maxv[2];
2602   /* first needs bounding box data */
2603   if (gpd->flag & GP_DATA_UV_ADAPTIVE) {
2604     gpencil_calc_2d_bounding_box(points2d, gps->totpoints, minv, maxv);
2605   }
2606   else {
2607     ARRAY_SET_ITEMS(minv, -1.0f, -1.0f);
2608     ARRAY_SET_ITEMS(maxv, 1.0f, 1.0f);
2609   }
2610
2611   /* calc uv data */
2612   gpencil_calc_stroke_fill_uv(points2d, gps->totpoints, minv, maxv, uv);
2613
2614   /* Number of triangles */
2615   gps->tot_triangles = gps->totpoints - 2;
2616   /* save triangulation data in stroke cache */
2617   if (gps->tot_triangles > 0) {
2618     if (gps->triangles == NULL) {
2619       gps->triangles = MEM_callocN(sizeof(*gps->triangles) * gps->tot_triangles,
2620                                    "GP Stroke triangulation");
2621     }
2622     else {
2623       gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles);
2624     }
2625
2626     for (int i = 0; i < gps->tot_triangles; i++) {
2627       bGPDtriangle *stroke_triangle = &gps->triangles[i];
2628       memcpy(gps->triangles[i].verts, tmp_triangles[i], sizeof(uint[3]));
2629       /* copy texture coordinates */
2630       copy_v2_v2(stroke_triangle->uv[0], uv[tmp_triangles[i][0]]);
2631       copy_v2_v2(stroke_triangle->uv[1], uv[tmp_triangles[i][1]]);
2632       copy_v2_v2(stroke_triangle->uv[2], uv[tmp_triangles[i][2]]);
2633     }
2634   }
2635   else {
2636     /* No triangles needed - Free anything allocated previously */
2637     if (gps->triangles) {
2638       MEM_freeN(gps->triangles);
2639     }
2640
2641     gps->triangles = NULL;
2642   }
2643
2644   /* disable recalculation flag */
2645   if (gps->flag & GP_STROKE_RECALC_GEOMETRY) {
2646     gps->flag &= ~GP_STROKE_RECALC_GEOMETRY;
2647   }
2648
2649   /* clear memory */
2650   MEM_SAFE_FREE(tmp_triangles);
2651   MEM_SAFE_FREE(points2d);
2652   MEM_SAFE_FREE(uv);
2653 }
2654
2655 float BKE_gpencil_stroke_length(const bGPDstroke *gps, bool use_3d)
2656 {
2657   if (!gps->points || gps->totpoints < 2) {
2658     return 0.0f;
2659   }
2660   float *last_pt = &gps->points[0].x;
2661   int i;
2662   bGPDspoint *pt;
2663   float total_length = 0.0f;
2664   for (i = 1; i < gps->totpoints; i++) {
2665     pt = &gps->points[i];
2666     if (use_3d) {
2667       total_length += len_v3v3(&pt->x, last_pt);
2668     }
2669     else {
2670       total_length += len_v2v2(&pt->x, last_pt);
2671     }
2672     last_pt = &pt->x;
2673   }
2674   return total_length;
2675 }
2676
2677 /**
2678  * Trim stroke to the first intersection or loop
2679  * \param gps: Stroke data
2680  */
2681 bool BKE_gpencil_trim_stroke(bGPDstroke *gps)
2682 {
2683   if (gps->totpoints < 4) {
2684     return false;
2685   }
2686   bool intersect = false;
2687   int start, end;
2688   float point[3];
2689   /* loop segments from start until we have an intersection */
2690   for (int i = 0; i < gps->totpoints - 2; i++) {
2691     start = i;
2692     bGPDspoint *a = &gps->points[start];
2693     bGPDspoint *b = &gps->points[start + 1];
2694     for (int j = start + 2; j < gps->totpoints - 1; j++) {
2695       end = j + 1;
2696       bGPDspoint *c = &gps->points[j];
2697       bGPDspoint *d = &gps->points[end];
2698       float pointb[3];
2699       /* get intersection */
2700       if (isect_line_line_v3(&a->x, &b->x, &c->x, &d->x, point, pointb)) {
2701         if (len_v3(point) > 0.0f) {
2702           float closest[3];
2703           /* check intersection is on both lines */
2704           float lambda = closest_to_line_v3(closest, point, &a->x, &b->x);
2705           if ((lambda <= 0.0f) || (lambda >= 1.0f)) {
2706             continue;
2707           }
2708           lambda = closest_to_line_v3(closest, point, &c->x, &d->x);
2709           if ((lambda <= 0.0f) || (lambda >= 1.0f)) {
2710             continue;
2711           }
2712           else {
2713             intersect = true;
2714             break;
2715           }
2716         }
2717       }
2718     }
2719     if (intersect) {
2720       break;
2721     }
2722   }
2723
2724   /* trim unwanted points */
2725   if (intersect) {
2726
2727     /* save points */
2728     bGPDspoint *old_points = MEM_dupallocN(gps->points);
2729     MDeformVert *old_dvert = NULL;
2730     MDeformVert *dvert_src = NULL;
2731
2732     if (gps->dvert != NULL) {
2733       old_dvert = MEM_dupallocN(gps->dvert);
2734     }
2735
2736     /* resize gps */
2737     int newtot = end - start + 1;
2738
2739     gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * newtot);
2740     if (gps->dvert != NULL) {
2741       gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot);
2742     }
2743
2744     for (int i = 0; i < newtot; i++) {
2745       int idx = start + i;
2746       bGPDspoint *pt_src = &old_points[idx];
2747       bGPDspoint *pt_new = &gps->points[i];
2748       memcpy(pt_new, pt_src, sizeof(bGPDspoint));
2749       if (gps->dvert != NULL) {
2750         dvert_src = &old_dvert[idx];
2751         MDeformVert *dvert = &gps->dvert[i];
2752         memcpy(dvert, dvert_src, sizeof(MDeformVert));
2753         if (dvert_src->dw) {
2754           memcpy(dvert->dw, dvert_src->dw, sizeof(MDeformWeight));
2755         }
2756       }
2757       if (idx == start || idx == end) {
2758         copy_v3_v3(&pt_new->x, point);
2759       }
2760     }
2761
2762     gps->flag |= GP_STROKE_RECALC_GEOMETRY;
2763     gps->tot_triangles = 0;
2764     gps->totpoints = newtot;
2765
2766     MEM_SAFE_FREE(old_points);
2767     MEM_SAFE_FREE(old_dvert);
2768   }
2769   return intersect;
2770 }
2771
2772 /**
2773  * Close stroke
2774  * \param gps: Stroke to close
2775  */
2776 bool BKE_gpencil_close_stroke(bGPDstroke *gps)
2777 {
2778   bGPDspoint *pt1 = NULL;
2779   bGPDspoint *pt2 = NULL;
2780
2781   /* Only can close a stroke with 3 points or more. */
2782   if (gps->totpoints < 3) {
2783     return false;
2784   }
2785
2786   /* Calc average distance between points to get same level of sampling. */
2787   float dist_tot = 0.0f;
2788   for (int i = 0; i < gps->totpoints - 1; i++) {
2789     pt1 = &gps->points[i];
2790     pt2 = &gps->points[i + 1];
2791     dist_tot += len_v3v3(&pt1->x, &pt2->x);
2792   }
2793   /* Calc the average distance. */
2794   float dist_avg = dist_tot / (gps->totpoints - 1);
2795
2796   /* Calc distance between last and first point. */
2797   pt1 = &gps->points[gps->totpoints - 1];
2798   pt2 = &gps->points[0];
2799   float dist_close = len_v3v3(&pt1->x, &pt2->x);
2800
2801   /* if the distance to close is very small, don't need add points and just enable cyclic. */
2802   if (dist_close <= dist_avg) {
2803     gps->flag |= GP_STROKE_CYCLIC;
2804     return true;
2805   }
2806
2807   /* Calc number of points required using the average distance. */
2808   int tot_newpoints = MAX2(dist_close / dist_avg, 1);
2809
2810   /* Resize stroke array. */
2811   int old_tot = gps->totpoints;
2812   gps->totpoints += tot_newpoints;
2813   gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
2814   if (gps->dvert != NULL) {
2815     gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
2816   }
2817
2818   /* Generate new points */
2819   pt1 = &gps->points[old_tot - 1];
2820   pt2 = &gps->points[0];
2821   bGPDspoint *pt = &gps->points[old_tot];
2822   for (int i = 1; i < tot_newpoints + 1; i++, pt++) {
2823     float step = (tot_newpoints > 1) ? ((float)i / (float)tot_newpoints) : 0.99f;
2824     /* Clamp last point to be near, but not on top of first point. */
2825     if ((tot_newpoints > 1) && (i == tot_newpoints)) {
2826       step *= 0.99f;
2827     }
2828
2829     /* Average point. */
2830     interp_v3_v3v3(&pt->x, &pt1->x, &pt2->x, step);
2831     pt->pressure = interpf(pt2->pressure, pt1->pressure, step);
2832     pt->strength = interpf(pt2->strength, pt1->strength, step);
2833     pt->flag = 0;
2834
2835     /* Set weights. */
2836     if (gps->dvert != NULL) {
2837       MDeformVert *dvert1 = &gps->dvert[old_tot - 1];
2838       MDeformWeight *dw1 = defvert_verify_index(dvert1, 0);
2839       float weight_1 = dw1 ? dw1->weight : 0.0f;
2840
2841       MDeformVert *dvert2 = &gps->dvert[0];
2842       MDeformWeight *dw2 = defvert_verify_index(dvert2, 0);
2843       float weight_2 = dw2 ? dw2->weight : 0.0f;
2844
2845       MDeformVert *dvert_final = &gps->dvert[old_tot + i - 1];
2846       dvert_final->totweight = 0;
2847       MDeformWeight *dw = defvert_verify_index(dvert_final, 0);
2848       if (dvert_final->dw) {
2849         dw->weight = interpf(weight_2, weight_1, step);
2850       }
2851     }
2852   }
2853
2854   /* Enable cyclic flag. */
2855   gps->flag |= GP_STROKE_CYCLIC;
2856
2857   return true;
2858 }
2859 /* Dissolve points in stroke */
2860 void BKE_gpencil_dissolve_points(bGPDframe *gpf, bGPDstroke *gps, const short tag)
2861 {
2862   bGPDspoint *pt;
2863   MDeformVert *dvert = NULL;
2864   int i;
2865
2866   int tot = gps->totpoints; /* number of points in new buffer */
2867   /* first pass: count points to remove */
2868   /* Count how many points are selected (i.e. how many to remove) */
2869   for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
2870     if (pt->flag & tag) {
2871       /* selected point - one of the points to remove */
2872       tot--;
2873     }
2874   }
2875
2876   /* if no points are left, we simply delete the entire stroke */
2877   if (tot <= 0) {
2878     /* remove the entire stroke */
2879     if (gps->points) {
2880       MEM_freeN(gps->points);
2881     }
2882     if (gps->dvert) {
2883       BKE_gpencil_free_stroke_weights(gps);
2884       MEM_freeN(gps->dvert);
2885     }
2886     if (gps->triangles) {
2887       MEM_freeN(gps->triangles);
2888     }
2889     BLI_freelinkN(&gpf->strokes, gps);
2890   }
2891   else {
2892     /* just copy all points to keep into a smaller buffer */
2893     bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot, "new gp stroke points copy");
2894     bGPDspoint *npt = new_points;
2895
2896     MDeformVert *new_dvert = NULL;
2897     MDeformVert *ndvert = NULL;
2898
2899     if (gps->dvert != NULL) {
2900       new_dvert = MEM_callocN(sizeof(MDeformVert) * tot, "new gp stroke weights copy");
2901       ndvert = new_dvert;
2902     }
2903
2904     (gps->dvert != NULL) ? dvert = gps->dvert : NULL;
2905     for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
2906       if ((pt->flag & tag) == 0) {
2907         *npt = *pt;
2908         npt++;
2909
2910         if (gps->dvert != NULL) {
2911           *ndvert = *dvert;
2912           ndvert->dw = MEM_dupallocN(dvert->dw);
2913           ndvert++;
2914         }
2915       }
2916       if (gps->dvert != NULL) {
2917         dvert++;
2918       }
2919     }
2920
2921     /* free the old buffer */
2922     if (gps->points) {
2923       MEM_freeN(gps->points);
2924     }
2925     if (gps->dvert) {
2926       BKE_gpencil_free_stroke_weights(gps);
2927       MEM_freeN(gps->dvert);
2928     }
2929
2930     /* save the new buffer */
2931     gps->points = new_points;
2932     gps->dvert = new_dvert;
2933     gps->totpoints = tot;
2934
2935     /* triangles cache needs to be recalculated */
2936     gps->flag |= GP_STROKE_RECALC_GEOMETRY;
2937     gps->tot_triangles = 0;
2938   }
2939 }
2940
2941 /* Merge by distance ------------------------------------- */
2942 /* Reduce a series of points when the distance is below a threshold.
2943  * Special case for first and last points (both are keeped) for other points,
2944  * the merge point always is at first point.
2945  * \param gpf: Grease Pencil frame
2946  * \param gps: Grease Pencil stroke
2947  * \param threshold: Distance between points
2948  * \param use_unselected: Set to true to analyze all stroke and not only selected points
2949  */
2950 void BKE_gpencil_merge_distance_stroke(bGPDframe *gpf,
2951                                        bGPDstroke *gps,
2952                                        const float threshold,
2953                                        const bool use_unselected)
2954 {
2955   bGPDspoint *pt = NULL;
2956   bGPDspoint *pt_next = NULL;
2957   float tagged = false;
2958   /* Use square distance to speed up loop */
2959   const float th_square = threshold * threshold;
2960   /* Need to have something to merge. */
2961   if (gps->totpoints < 2) {
2962     return;
2963   }
2964   int i = 0;
2965   int step = 1;
2966   while ((i < gps->totpoints - 1) && (i + step < gps->totpoints)) {
2967     pt = &gps->points[i];
2968     if (pt->flag & GP_SPOINT_TAG) {
2969       i++;
2970       step = 1;
2971       continue;
2972     }
2973     pt_next = &gps->points[i + step];
2974     /* Do not recalc tagged points. */
2975     if (pt_next->flag & GP_SPOINT_TAG) {
2976       step++;
2977       continue;
2978     }
2979     /* Check if contiguous points are selected. */
2980     if (!use_unselected) {
2981       if (((pt->flag & GP_SPOINT_SELECT) == 0) || ((pt_next->flag & GP_SPOINT_SELECT) == 0)) {
2982         i++;
2983         step = 1;
2984         continue;
2985       }
2986     }
2987     float len_square = len_squared_v3v3(&pt->x, &pt_next->x);
2988     if (len_square <= th_square) {
2989       tagged = true;
2990       if (i != gps->totpoints - 1) {
2991         /* Tag second point for delete. */
2992         pt_next->flag |= GP_SPOINT_TAG;
2993       }
2994       else {
2995         pt->flag |= GP_SPOINT_TAG;
2996       }
2997       /* Jump to next pair of points, keeping first point segment equals.*/
2998       step++;
2999     }
3000     else {
3001       /* Analyze next point. */
3002       i++;
3003       step = 1;
3004     }
3005   }
3006
3007   /* Always untag extremes. */
3008   pt = &gps->points[0];
3009   pt->flag &= ~GP_SPOINT_TAG;
3010   pt = &gps->points[gps->totpoints - 1];
3011   pt->flag &= ~GP_SPOINT_TAG;
3012
3013   /* Dissolve tagged points */
3014   if (tagged) {
3015     BKE_gpencil_dissolve_points(gpf, gps, GP_SPOINT_TAG);
3016   }
3017 }
3018
3019 /* Helper: Check materials with same color. */
3020 static int gpencil_check_same_material_color(Object *ob_gp, float color[4], Material **r_mat)
3021 {
3022   Material *ma = NULL;
3023   float color_cu[4];
3024   linearrgb_to_srgb_v3_v3(color_cu, color);
3025   float hsv1[4];
3026   rgb_to_hsv_v(color_cu, hsv1);
3027   hsv1[3] = color[3];
3028
3029   for (int i = 1; i <= ob_gp->totcol; i++) {
3030     ma = BKE_object_material_get(ob_gp, i);
3031     MaterialGPencilStyle *gp_style = ma->gp_style;
3032     /* Check color with small tolerance (better in HSV). */
3033     float hsv2[4];
3034     rgb_to_hsv_v(gp_style->fill_rgba, hsv2);
3035     hsv2[3] = gp_style->fill_rgba[3];
3036     if ((gp_style->fill_style == GP_STYLE_FILL_STYLE_SOLID) && (compare_v4v4(hsv1, hsv2, 0.01f))) {
3037       *r_mat = ma;
3038       return i - 1;
3039     }
3040   }
3041
3042   *r_mat = NULL;
3043   return -1;
3044 }
3045
3046 /* Helper: Add gpencil material using curve material as base. */
3047 static Material *gpencil_add_from_curve_material(Main *bmain,
3048                                                  Object *ob_gp,
3049                                                  const float cu_color[4],
3050                                                  const bool gpencil_lines,
3051                                                  const bool fill,
3052                                                  int *r_idx)
3053 {
3054   Material *mat_gp = BKE_gpencil_object_material_new(
3055       bmain, ob_gp, (fill) ? "Material" : "Unassigned", r_idx);
3056   MaterialGPencilStyle *gp_style = mat_gp->gp_style;
3057
3058   /* Stroke color. */
3059   if (gpencil_lines) {
3060     ARRAY_SET_ITEMS(gp_style->stroke_rgba, 0.0f, 0.0f, 0.0f, 1.0f);
3061     gp_style->flag |= GP_STYLE_STROKE_SHOW;
3062   }
3063   else {
3064     linearrgb_to_srgb_v4(gp_style->stroke_rgba, cu_color);
3065     gp_style->flag &= ~GP_STYLE_STROKE_SHOW;
3066   }
3067
3068   /* Fill color. */
3069   linearrgb_to_srgb_v4(gp_style->fill_rgba, cu_color);
3070   /* Fill is false if the original curve hasn't material assigned, so enable it. */
3071   if (fill) {
3072     gp_style->flag |= GP_STYLE_FILL_SHOW;
3073   }
3074
3075   /* Check at least one is enabled. */
3076   if (((gp_style->flag & GP_STYLE_STROKE_SHOW) == 0) &&
3077       ((gp_style->flag & GP_STYLE_FILL_SHOW) == 0)) {
3078     gp_style->flag |= GP_STYLE_STROKE_SHOW;
3079   }
3080
3081   return mat_gp;
3082 }
3083
3084 /* Helper: Create new stroke section. */
3085 static void gpencil_add_new_points(bGPDstroke *gps,
3086                                    float *coord_array,
3087                                    float pressure,
3088                                    int init,
3089                                    int totpoints,
3090                                    const float init_co[3],
3091                                    bool last)
3092 {
3093   for (int i = 0; i < totpoints; i++) {
3094     bGPDspoint *pt = &gps->points[i + init];
3095     copy_v3_v3(&pt->x, &coord_array[3 * i]);
3096     /* Be sure the last point is not on top of the first point of the curve or
3097      * the close of the stroke will produce glitches. */
3098     if ((last) && (i > 0) && (i == totpoints - 1)) {
3099       float dist = len_v3v3(init_co, &pt->x);
3100       if (dist < 0.1f) {
3101         /* Interpolate between previous point and current to back slightly. */
3102         bGPDspoint *pt_prev = &gps->points[i + init - 1];
3103         interp_v3_v3v3(&pt->x, &pt_prev->x, &pt->x, 0.95f);
3104       }
3105     }
3106
3107     pt->pressure = pressure;
3108     pt->strength = 1.0f;
3109   }
3110 }
3111
3112 /* Helper: Get the first collection that includes the object. */
3113 static Collection *gpencil_get_parent_collection(Scene *scene, Object *ob)
3114 {
3115   Collection *mycol = NULL;
3116   FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
3117     for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
3118       if ((mycol == NULL) && (cob->ob == ob)) {
3119         mycol = collection;
3120       }
3121     }
3122   }
3123   FOREACH_SCENE_COLLECTION_END;
3124
3125   return mycol;
3126 }
3127
3128 /* Helper: Convert one spline to grease pencil stroke. */
3129 static void gpencil_convert_spline(Main *bmain,
3130                                    Object *ob_gp,
3131                                    Object *ob_cu,
3132                                    const bool gpencil_lines,
3133                                    const bool only_stroke,
3134                                    bGPDframe *gpf,
3135                                    Nurb *nu)
3136 {
3137   Curve *cu = (Curve *)ob_cu->data;
3138   bool cyclic = true;
3139
3140   /* Create Stroke. */
3141   bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke");
3142   gps->thickness = 1.0f;
3143   gps->gradient_f = 1.0f;
3144   ARRAY_SET_ITEMS(gps->gradient_s, 1.0f, 1.0f);
3145   ARRAY_SET_ITEMS(gps->caps, GP_STROKE_CAP_ROUND, GP_STROKE_CAP_ROUND);
3146   gps->inittime = 0.0f;
3147
3148   /* Enable recalculation flag by default. */
3149   gps->flag |= GP_STROKE_RECALC_GEOMETRY;
3150   gps->flag &= ~GP_STROKE_SELECT;
3151   gps->flag |= GP_STROKE_3DSPACE;
3152
3153   gps->mat_nr = 0;
3154   /* Count total points
3155    * The total of points must consider that last point of each segment is equal to the first
3156    * point of next segment.
3157    */
3158   int totpoints = 0;
3159   int segments = 0;
3160   int resolu = nu->resolu + 1;
3161   segments = nu->pntsu;
3162   if (((nu->flagu & CU_NURB_CYCLIC) == 0) || (nu->pntsu == 2)) {
3163     segments--;
3164     cyclic = false;
3165   }
3166   totpoints = (resolu * segments) - (segments - 1);
3167
3168   /* Initialize triangle memory to dummy data. */
3169   gps->tot_triangles = 0;
3170   gps->triangles = NULL;
3171
3172   /* Materials
3173    * Notice: The color of the material is the color of viewport and not the final shader color.
3174    */
3175   Material *mat_gp = NULL;
3176   bool fill = true;
3177   /* Check if grease pencil has a material with same color.*/
3178   float color[4];
3179   if ((cu->mat) && (*cu->mat)) {
3180     Material *mat_cu = *cu->mat;
3181     copy_v4_v4(color, &mat_cu->r);
3182   }
3183   else {
3184     /* Gray (unassigned from SVG add-on) */
3185     zero_v4(color);
3186     add_v3_fl(color, 0.6f);
3187     color[3] = 1.0f;
3188     fill = false;
3189   }
3190
3191   /* Special case: If the color was created by the SVG add-on and the name contains '_stroke' and
3192    * there is only one color, the stroke must not be closed, fill to false and use for
3193    * stroke the fill color.
3194    */
3195   bool do_stroke = false;
3196   if (ob_cu->totcol == 1) {
3197     Material *ma_stroke = BKE_object_material_get(ob_cu, 1);
3198     if ((ma_stroke) && (strstr(ma_stroke->id.name, "_stroke") != NULL)) {
3199       do_stroke = true;
3200     }
3201   }
3202
3203   int r_idx = gpencil_check_same_material_color(ob_gp, color, &mat_gp);
3204   if ((ob_cu->totcol > 0) && (r_idx < 0)) {
3205     Material *mat_curve = BKE_object_material_get(ob_cu, 1);
3206     mat_gp = gpencil_add_from_curve_material(bmain, ob_gp, color, gpencil_lines, fill, &r_idx);
3207
3208     if ((mat_curve) && (mat_curve->gp_style != NULL)) {
3209       MaterialGPencilStyle *gp_style_cur = mat_curve->gp_style;
3210       MaterialGPencilStyle *gp_style_gp = mat_gp->gp_style;
3211
3212       copy_v4_v4(gp_style_gp->mix_rgba, gp_style_cur->mix_rgba);
3213       gp_style_gp->fill_style = gp_style_cur->fill_style;
3214       gp_style_gp->mix_factor = gp_style_cur->mix_factor;
3215       gp_style_gp->gradient_angle = gp_style_cur->gradient_angle;
3216     }
3217
3218     /* If object has more than 1 material, use second material for stroke color. */
3219     if ((!only_stroke) && (ob_cu->totcol > 1) && (BKE_object_material_get(ob_cu, 2))) {
3220       mat_curve = BKE_object_material_get(ob_cu, 2);
3221       if (mat_curve) {
3222         linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r);
3223         mat_gp->gp_style->stroke_rgba[3] = mat_curve->a;
3224       }
3225     }
3226     else if ((only_stroke) || (do_stroke)) {
3227       /* Also use the first color if the fill is none for stroke color. */
3228       if (ob_cu->totcol > 0) {
3229         mat_curve = BKE_object_material_get(ob_cu, 1);
3230         if (mat_curve) {
3231           linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r);
3232           mat_gp->gp_style->stroke_rgba[3] = mat_curve->a;
3233           /* Set fill and stroke depending of curve type (3D or 2D). */
3234           if ((cu->flag & CU_3D) || ((cu->flag & (CU_FRONT | CU_BACK)) == 0)) {
3235             mat_gp->gp_style->flag |= GP_STYLE_STROKE_SHOW;
3236             mat_gp->gp_style->flag &= ~GP_STYLE_FILL_SHOW;
3237           }
3238           else {
3239             mat_gp->gp_style->flag &= ~GP_STYLE_STROKE_SHOW;
3240             mat_gp->gp_style->flag |= GP_STYLE_FILL_SHOW;
3241           }
3242         }
3243       }
3244     }
3245   }
3246   CLAMP_MIN(r_idx, 0);
3247
3248   /* Assign material index to stroke. */
3249   gps->mat_nr = r_idx;
3250
3251   /* Add stroke to frame.*/
3252   BLI_addtail(&gpf->strokes, gps);
3253
3254   float *coord_array = NULL;
3255   float init_co[3];
3256
3257   switch (nu->type) {
3258     case CU_POLY: {
3259       /* Allocate memory for storage points. */
3260       gps->totpoints = nu->pntsu;
3261       gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
3262       /* Increase thickness for this type. */
3263       gps->thickness = 10.0f;
3264
3265       /* Get all curve points */
3266       for (int s = 0; s < gps->totpoints; s++) {
3267         BPoint *bp = &nu->bp[s];
3268         bGPDspoint *pt = &gps->points[s];
3269         copy_v3_v3(&pt->x, bp->vec);
3270         pt->pressure = bp->radius;
3271         pt->strength = 1.0f;
3272       }
3273       break;
3274     }
3275     case CU_BEZIER: {
3276       /* Allocate memory for storage points. */
3277       gps->totpoints = totpoints;
3278       gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
3279
3280       int init = 0;
3281       resolu = nu->resolu + 1;
3282       segments = nu->pntsu;
3283       if (((nu->flagu & CU_NURB_CYCLIC) == 0) || (nu->pntsu == 2)) {
3284         segments--;
3285       }
3286       /* Get all interpolated curve points of Beziert */
3287       for (int s = 0; s < segments; s++) {
3288         int inext = (s + 1) % nu->pntsu;
3289         BezTriple *prevbezt = &nu->bezt[s];
3290         BezTriple *bezt = &nu->bezt[inext];
3291         bool last = (bool)(s == segments - 1);
3292
3293         coord_array = MEM_callocN((size_t)3 * resolu * sizeof(float), __func__);
3294
3295         for (int j = 0; j < 3; j++) {
3296           BKE_curve_forward_diff_bezier(prevbezt->vec[1][j],
3297                                         prevbezt->vec[2][j],
3298                                         bezt->vec[0][j],
3299                                         bezt->vec[1][j],
3300                                         coord_array + j,
3301                                         resolu - 1,
3302                                         3 * sizeof(float));
3303         }
3304         /* Save first point coordinates. */
3305         if (s == 0) {
3306           copy_v3_v3(init_co, &coord_array[0]);
3307         }
3308         /* Add points to the stroke */
3309         gpencil_add_new_points(gps, coord_array, bezt->radius, init, resolu, init_co, last);
3310         /* Free memory. */
3311         MEM_SAFE_FREE(coord_array);
3312
3313         /* As the last point of segment is the first point of next segment, back one array
3314          * element to avoid duplicated points on the same location.
3315          */
3316         init += resolu - 1;
3317       }
3318       break;
3319     }
3320     case CU_NURBS: {
3321       if (nu->pntsv == 1) {
3322
3323         int nurb_points;
3324         if (nu->flagu & CU_NURB_CYCLIC) {
3325           resolu++;
3326           nurb_points = nu->pntsu * resolu;
3327         }
3328         else {
3329           nurb_points = (nu->pntsu - 1) * resolu;
3330         }
3331         /* Get all curve points. */
3332         coord_array = MEM_callocN(sizeof(float[3]) * nurb_points, __func__);
3333         BKE_nurb_makeCurve(nu, coord_array, NULL, NULL, NULL, resolu, sizeof(float[3]));
3334
3335         /* Allocate memory for storage points. */
3336         gps->totpoints = nurb_points - 1;
3337         gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
3338
3339         /* Add points. */
3340         gpencil_add_new_points(gps, coord_array, 1.0f, 0, gps->totpoints, init_co, false);
3341
3342         MEM_SAFE_FREE(coord_array);
3343       }
3344       break;
3345     }
3346     default: {
3347       break;
3348     }
3349   }
3350   /* Cyclic curve, close stroke. */
3351   if ((cyclic) && (!do_stroke)) {
3352     BKE_gpencil_close_stroke(gps);
3353   }
3354 }
3355
3356 /* Convert a curve object to grease pencil stroke.
3357  *
3358  * \param bmain: Main thread pointer
3359  * \param scene: Original scene.
3360  * \param ob_gp: Grease pencil object to add strokes.
3361  * \param ob_cu: Curve to convert.
3362  * \param gpencil_lines: Use lines for strokes.
3363  * \param use_collections: Create layers using collection names.
3364  * \param only_stroke: The material must be only stroke without fill.
3365  */
3366 void BKE_gpencil_convert_curve(Main *bmain,
3367                                Scene *scene,
3368                                Object *ob_gp,
3369                                Object *ob_cu,
3370                                const bool gpencil_lines,
3371                                const bool use_collections,
3372                                const bool only_stroke)
3373 {
3374   if (ELEM(NULL, ob_gp, ob_cu) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) {
3375     return;
3376   }
3377
3378   Curve *cu = (Curve *)ob_cu->data;
3379   bGPdata *gpd = (bGPdata *)ob_gp->data;
3380   bGPDlayer *gpl = NULL;
3381
3382   /* If the curve is empty, cancel. */
3383   if (cu->nurb.first == NULL) {
3384     return;
3385   }
3386
3387   /* Check if there is an active layer. */
3388   if (use_collections) {
3389     Collection *collection = gpencil_get_parent_collection(scene, ob_cu);
3390     if (collection != NULL) {
3391       gpl = BLI_findstring(&gpd->layers, collection->id.name + 2, offsetof(bGPDlayer, info));
3392       if (gpl == NULL) {
3393         gpl = BKE_gpencil_layer_addnew(gpd, collection->id.name + 2, true);
3394       }
3395     }
3396   }
3397
3398   if (gpl == NULL) {
3399     gpl = BKE_gpencil_layer_getactive(gpd);
3400     if (gpl == NULL) {
3401       gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
3402     }
3403   }
3404
3405   /* Check if there is an active frame and add if needed. */
3406   bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_COPY);
3407
3408   /* Read all splines of the curve and create a stroke for each. */
3409   for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
3410     gpencil_convert_spline(bmain, ob_gp, ob_cu, gpencil_lines, only_stroke, gpf, nu);
3411   }
3412
3413   /* Tag for recalculation */
3414   DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
3415 }