Cleanup: remove redundant doxygen \file argument
[blender.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 \ingroup bke
21  */
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_string_utils.h"
38
39 #include "BLT_translation.h"
40
41 #include "DNA_anim_types.h"
42 #include "DNA_meshdata_types.h"
43 #include "DNA_material_types.h"
44 #include "DNA_gpencil_types.h"
45 #include "DNA_userdef_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_object_types.h"
48
49 #include "BKE_action.h"
50 #include "BKE_animsys.h"
51 #include "BKE_deform.h"
52 #include "BKE_gpencil.h"
53 #include "BKE_colortools.h"
54 #include "BKE_icons.h"
55 #include "BKE_library.h"
56 #include "BKE_main.h"
57 #include "BKE_object.h"
58 #include "BKE_material.h"
59
60 #include "DEG_depsgraph.h"
61
62 static CLG_LogRef LOG = {"bke.gpencil"};
63
64 /* ************************************************** */
65 /* Draw Engine */
66
67 void(*BKE_gpencil_batch_cache_dirty_tag_cb)(bGPdata *gpd) = NULL;
68 void(*BKE_gpencil_batch_cache_free_cb)(bGPdata *gpd) = NULL;
69
70 void BKE_gpencil_batch_cache_dirty_tag(bGPdata *gpd)
71 {
72         if (gpd) {
73                 DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
74                 BKE_gpencil_batch_cache_dirty_tag_cb(gpd);
75         }
76 }
77
78 void BKE_gpencil_batch_cache_free(bGPdata *gpd)
79 {
80         if (gpd) {
81                 BKE_gpencil_batch_cache_free_cb(gpd);
82         }
83 }
84
85 /* ************************************************** */
86 /* Memory Management */
87
88 /* clean vertex groups weights */
89 void BKE_gpencil_free_point_weights(MDeformVert *dvert)
90 {
91         if (dvert == NULL) {
92                 return;
93         }
94         MEM_SAFE_FREE(dvert->dw);
95 }
96
97 void BKE_gpencil_free_stroke_weights(bGPDstroke *gps)
98 {
99         if (gps == NULL) {
100                 return;
101         }
102
103         if (gps->dvert == NULL) {
104                 return;
105         }
106
107         for (int i = 0; i < gps->totpoints; i++) {
108                 MDeformVert *dvert = &gps->dvert[i];
109                 BKE_gpencil_free_point_weights(dvert);
110         }
111 }
112
113 /* free stroke, doesn't unlink from any listbase */
114 void BKE_gpencil_free_stroke(bGPDstroke *gps)
115 {
116         if (gps == NULL) {
117                 return;
118         }
119         /* free stroke memory arrays, then stroke itself */
120         if (gps->points) {
121                 MEM_freeN(gps->points);
122         }
123         if (gps->dvert) {
124                 BKE_gpencil_free_stroke_weights(gps);
125                 MEM_freeN(gps->dvert);
126         }
127         if (gps->triangles)
128                 MEM_freeN(gps->triangles);
129
130         MEM_freeN(gps);
131 }
132
133 /* Free strokes belonging to a gp-frame */
134 bool BKE_gpencil_free_strokes(bGPDframe *gpf)
135 {
136         bGPDstroke *gps_next;
137         bool changed = (BLI_listbase_is_empty(&gpf->strokes) == false);
138
139         /* free strokes */
140         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps_next) {
141                 gps_next = gps->next;
142                 BKE_gpencil_free_stroke(gps);
143         }
144         BLI_listbase_clear(&gpf->strokes);
145
146         return changed;
147 }
148
149 /* Free strokes and colors belonging to a gp-frame */
150 bool BKE_gpencil_free_frame_runtime_data(bGPDframe *derived_gpf)
151 {
152         bGPDstroke *gps_next;
153         if (!derived_gpf) {
154                 return false;
155         }
156
157         /* free strokes */
158         for (bGPDstroke *gps = derived_gpf->strokes.first; gps; gps = gps_next) {
159                 gps_next = gps->next;
160                 BKE_gpencil_free_stroke(gps);
161         }
162         BLI_listbase_clear(&derived_gpf->strokes);
163
164         return true;
165 }
166
167 /* Free all of a gp-layer's frames */
168 void BKE_gpencil_free_frames(bGPDlayer *gpl)
169 {
170         bGPDframe *gpf_next;
171
172         /* error checking */
173         if (gpl == NULL) return;
174
175         /* free frames */
176         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf_next) {
177                 gpf_next = gpf->next;
178
179                 /* free strokes and their associated memory */
180                 BKE_gpencil_free_strokes(gpf);
181                 BLI_freelinkN(&gpl->frames, gpf);
182         }
183         gpl->actframe = NULL;
184 }
185
186
187
188 /* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */
189 void BKE_gpencil_free_layers(ListBase *list)
190 {
191         bGPDlayer *gpl_next;
192
193         /* error checking */
194         if (list == NULL) return;
195
196         /* delete layers */
197         for (bGPDlayer *gpl = list->first; gpl; gpl = gpl_next) {
198                 gpl_next = gpl->next;
199
200                 /* free layers and their data */
201                 BKE_gpencil_free_frames(gpl);
202                 BLI_freelinkN(list, gpl);
203         }
204 }
205
206 /** Free (or release) any data used by this grease pencil (does not free the gpencil itself). */
207 void BKE_gpencil_free(bGPdata *gpd, bool free_all)
208 {
209         /* clear animation data */
210         BKE_animdata_free(&gpd->id, false);
211
212         /* free layers */
213         BKE_gpencil_free_layers(&gpd->layers);
214
215         /* materials */
216         MEM_SAFE_FREE(gpd->mat);
217
218         /* free all data */
219         if (free_all) {
220                 /* clear cache */
221                 BKE_gpencil_batch_cache_free(gpd);
222         }
223 }
224
225 /* ************************************************** */
226 /* Container Creation */
227
228 /* add a new gp-frame to the given layer */
229 bGPDframe *BKE_gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
230 {
231         bGPDframe *gpf = NULL, *gf = NULL;
232         short state = 0;
233
234         /* error checking */
235         if (gpl == NULL)
236                 return NULL;
237
238         /* allocate memory for this frame */
239         gpf = MEM_callocN(sizeof(bGPDframe), "bGPDframe");
240         gpf->framenum = cframe;
241
242         /* find appropriate place to add frame */
243         if (gpl->frames.first) {
244                 for (gf = gpl->frames.first; gf; gf = gf->next) {
245                         /* check if frame matches one that is supposed to be added */
246                         if (gf->framenum == cframe) {
247                                 state = -1;
248                                 break;
249                         }
250
251                         /* if current frame has already exceeded the frame to add, add before */
252                         if (gf->framenum > cframe) {
253                                 BLI_insertlinkbefore(&gpl->frames, gf, gpf);
254                                 state = 1;
255                                 break;
256                         }
257                 }
258         }
259
260         /* check whether frame was added successfully */
261         if (state == -1) {
262                 CLOG_ERROR(&LOG, "Frame (%d) existed already for this layer. Using existing frame", cframe);
263
264                 /* free the newly created one, and use the old one instead */
265                 MEM_freeN(gpf);
266
267                 /* return existing frame instead... */
268                 BLI_assert(gf != NULL);
269                 gpf = gf;
270         }
271         else if (state == 0) {
272                 /* add to end then! */
273                 BLI_addtail(&gpl->frames, gpf);
274         }
275
276         /* return frame */
277         return gpf;
278 }
279
280 /* add a copy of the active gp-frame to the given layer */
281 bGPDframe *BKE_gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
282 {
283         bGPDframe *new_frame;
284         bool found = false;
285
286         /* Error checking/handling */
287         if (gpl == NULL) {
288                 /* no layer */
289                 return NULL;
290         }
291         else if (gpl->actframe == NULL) {
292                 /* no active frame, so just create a new one from scratch */
293                 return BKE_gpencil_frame_addnew(gpl, cframe);
294         }
295
296         /* Create a copy of the frame */
297         new_frame = BKE_gpencil_frame_duplicate(gpl->actframe);
298
299         /* Find frame to insert it before */
300         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
301                 if (gpf->framenum > cframe) {
302                         /* Add it here */
303                         BLI_insertlinkbefore(&gpl->frames, gpf, new_frame);
304
305                         found = true;
306                         break;
307                 }
308                 else if (gpf->framenum == cframe) {
309                         /* This only happens when we're editing with framelock on...
310                          * - Delete the new frame and don't do anything else here...
311                          */
312                         BKE_gpencil_free_strokes(new_frame);
313                         MEM_freeN(new_frame);
314                         new_frame = NULL;
315
316                         found = true;
317                         break;
318                 }
319         }
320
321         if (found == false) {
322                 /* Add new frame to the end */
323                 BLI_addtail(&gpl->frames, new_frame);
324         }
325
326         /* Ensure that frame is set up correctly, and return it */
327         if (new_frame) {
328                 new_frame->framenum = cframe;
329                 gpl->actframe = new_frame;
330         }
331
332         return new_frame;
333 }
334
335 /* add a new gp-layer and make it the active layer */
336 bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setactive)
337 {
338         bGPDlayer *gpl = NULL;
339         bGPDlayer *gpl_active = NULL;
340
341         /* check that list is ok */
342         if (gpd == NULL)
343                 return NULL;
344
345         /* allocate memory for frame and add to end of list */
346         gpl = MEM_callocN(sizeof(bGPDlayer), "bGPDlayer");
347
348         gpl_active = BKE_gpencil_layer_getactive(gpd);
349
350         /* add to datablock */
351         if (gpl_active == NULL) {
352                 BLI_addtail(&gpd->layers, gpl);
353         }
354         else {
355                 /* if active layer, add after that layer */
356                 BLI_insertlinkafter(&gpd->layers, gpl_active, gpl);
357         }
358
359         /* annotation vs GP Object behavior is slightly different */
360         if (gpd->flag & GP_DATA_ANNOTATIONS) {
361                 /* set default color of new strokes for this layer */
362                 copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
363                 gpl->opacity = 1.0f;
364
365                 /* set default thickness of new strokes for this layer */
366                 gpl->thickness = 3;
367
368                 /* Onion colors */
369                 ARRAY_SET_ITEMS(gpl->gcolor_prev, 0.302f, 0.851f, 0.302f);
370                 ARRAY_SET_ITEMS(gpl->gcolor_next, 0.250f, 0.1f, 1.0f);
371         }
372         else {
373                 /* thickness parameter represents "thickness change", not absolute thickness */
374                 gpl->thickness = 0;
375                 gpl->opacity = 1.0f;
376         }
377
378         /* auto-name */
379         BLI_strncpy(gpl->info, name, sizeof(gpl->info));
380         BLI_uniquename(&gpd->layers, gpl,
381                        (gpd->flag & GP_DATA_ANNOTATIONS) ? DATA_("Note") : DATA_("GP_Layer"),
382                        '.',
383                        offsetof(bGPDlayer, info),
384                        sizeof(gpl->info));
385
386         /* make this one the active one */
387         if (setactive)
388                 BKE_gpencil_layer_setactive(gpd, gpl);
389
390         /* return layer */
391         return gpl;
392 }
393
394 /* add a new gp-datablock */
395 bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
396 {
397         bGPdata *gpd;
398
399         /* allocate memory for a new block */
400         gpd = BKE_libblock_alloc(bmain, ID_GD, name, 0);
401
402         /* initial settings */
403         gpd->flag = (GP_DATA_DISPINFO | GP_DATA_EXPAND);
404
405         /* general flags */
406         gpd->flag |= GP_DATA_VIEWALIGN;
407         gpd->flag |= GP_DATA_STROKE_FORCE_RECALC;
408         /* always enable object onion skin swith */
409         gpd->flag |= GP_DATA_SHOW_ONIONSKINS;
410         /* GP object specific settings */
411         ARRAY_SET_ITEMS(gpd->line_color, 0.6f, 0.6f, 0.6f, 0.5f);
412
413         gpd->xray_mode = GP_XRAY_3DSPACE;
414         gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
415
416         /* grid settings */
417         ARRAY_SET_ITEMS(gpd->grid.color, 0.5f, 0.5f, 0.5f); // Color
418         ARRAY_SET_ITEMS(gpd->grid.scale, 1.0f, 1.0f); // Scale
419         gpd->grid.lines = GP_DEFAULT_GRID_LINES; // Number of lines
420
421         /* onion-skinning settings (datablock level) */
422         gpd->onion_flag |= (GP_ONION_GHOST_PREVCOL | GP_ONION_GHOST_NEXTCOL);
423         gpd->onion_flag |= GP_ONION_FADE;
424         gpd->onion_mode = GP_ONION_MODE_RELATIVE;
425         gpd->onion_factor = 0.5f;
426         ARRAY_SET_ITEMS(gpd->gcolor_prev, 0.145098f, 0.419608f, 0.137255f); /* green */
427         ARRAY_SET_ITEMS(gpd->gcolor_next, 0.125490f, 0.082353f, 0.529412f); /* blue */
428         gpd->gstep = 1;
429         gpd->gstep_next = 1;
430
431         return gpd;
432 }
433
434
435 /* ************************************************** */
436 /* Primitive Creation */
437 /* Utilities for easier bulk-creation of geometry */
438
439 /**
440  * Populate stroke with point data from data buffers
441  *
442  * \param array: Flat array of point data values. Each entry has GP_PRIM_DATABUF_SIZE values
443  * \param mat: 4x4 transform matrix to transform points into the right coordinate space
444  */
445 void BKE_gpencil_stroke_add_points(bGPDstroke *gps, const float *array, const int totpoints, const float mat[4][4])
446 {
447         for (int i = 0; i < totpoints; i++) {
448                 bGPDspoint *pt = &gps->points[i];
449                 const int x = GP_PRIM_DATABUF_SIZE * i;
450
451                 pt->x = array[x];
452                 pt->y = array[x + 1];
453                 pt->z = array[x + 2];
454                 mul_m4_v3(mat, &pt->x);
455
456                 pt->pressure = array[x + 3];
457                 pt->strength = array[x + 4];
458         }
459 }
460
461 /* Create a new stroke, with pre-allocated data buffers */
462 bGPDstroke *BKE_gpencil_add_stroke(bGPDframe *gpf, int mat_idx, int totpoints, short thickness)
463 {
464         /* allocate memory for a new stroke */
465         bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
466
467         gps->thickness = thickness;
468         gps->inittime = 0;
469
470         /* enable recalculation flag by default */
471         gps->flag = GP_STROKE_RECALC_GEOMETRY | GP_STROKE_3DSPACE;
472
473         gps->totpoints = totpoints;
474         gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
475
476         /* initialize triangle memory to dummy data */
477         gps->triangles = MEM_callocN(sizeof(bGPDtriangle), "GP Stroke triangulation");
478         gps->flag |= GP_STROKE_RECALC_GEOMETRY;
479         gps->tot_triangles = 0;
480
481         gps->mat_nr = mat_idx;
482
483         /* add to frame */
484         BLI_addtail(&gpf->strokes, gps);
485
486         return gps;
487 }
488
489
490 /* ************************************************** */
491 /* Data Duplication */
492
493 /* make a copy of a given gpencil weights */
494 void BKE_gpencil_stroke_weights_duplicate(bGPDstroke *gps_src, bGPDstroke *gps_dst)
495 {
496         if (gps_src == NULL) {
497                 return;
498         }
499         BLI_assert(gps_src->totpoints == gps_dst->totpoints);
500
501         BKE_defvert_array_copy(gps_dst->dvert, gps_src->dvert, gps_src->totpoints);
502 }
503
504 /* make a copy of a given gpencil stroke */
505 bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src)
506 {
507         bGPDstroke *gps_dst = NULL;
508
509         gps_dst = MEM_dupallocN(gps_src);
510         gps_dst->prev = gps_dst->next = NULL;
511
512         gps_dst->points = MEM_dupallocN(gps_src->points);
513
514         if (gps_src->dvert != NULL) {
515                 gps_dst->dvert = MEM_dupallocN(gps_src->dvert);
516                 BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst);
517         }
518         else {
519                 gps_dst->dvert = NULL;
520         }
521
522         /* Don't clear triangles, so that modifier evaluation can just use
523          * this without extra work first. Most places that need to force
524          * this data to get recalculated will destroy the data anyway though.
525          */
526         gps_dst->triangles = MEM_dupallocN(gps_dst->triangles);
527         /* gps_dst->flag |= GP_STROKE_RECALC_GEOMETRY; */
528
529         /* return new stroke */
530         return gps_dst;
531 }
532
533 /* make a copy of a given gpencil frame */
534 bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src)
535 {
536         bGPDstroke *gps_dst = NULL;
537         bGPDframe *gpf_dst;
538
539         /* error checking */
540         if (gpf_src == NULL) {
541                 return NULL;
542         }
543
544         /* make a copy of the source frame */
545         gpf_dst = MEM_dupallocN(gpf_src);
546         gpf_dst->prev = gpf_dst->next = NULL;
547
548         /* copy strokes */
549         BLI_listbase_clear(&gpf_dst->strokes);
550         for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
551                 /* make copy of source stroke */
552                 gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
553                 BLI_addtail(&gpf_dst->strokes, gps_dst);
554         }
555
556         /* return new frame */
557         return gpf_dst;
558 }
559
560 /* make a copy of strokes between gpencil frames */
561 void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, struct bGPDframe *gpf_dst)
562 {
563         bGPDstroke *gps_dst = NULL;
564         /* error checking */
565         if ((gpf_src == NULL) || (gpf_dst == NULL)) {
566                 return;
567         }
568
569         /* copy strokes */
570         BLI_listbase_clear(&gpf_dst->strokes);
571         for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
572                 /* make copy of source stroke */
573                 gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
574                 BLI_addtail(&gpf_dst->strokes, gps_dst);
575         }
576 }
577
578 /* make a copy of a given gpencil layer */
579 bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src)
580 {
581         const bGPDframe *gpf_src;
582         bGPDframe *gpf_dst;
583         bGPDlayer *gpl_dst;
584
585         /* error checking */
586         if (gpl_src == NULL) {
587                 return NULL;
588         }
589
590         /* make a copy of source layer */
591         gpl_dst = MEM_dupallocN(gpl_src);
592         gpl_dst->prev = gpl_dst->next = NULL;
593
594         /* copy frames */
595         BLI_listbase_clear(&gpl_dst->frames);
596         for (gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) {
597                 /* make a copy of source frame */
598                 gpf_dst = BKE_gpencil_frame_duplicate(gpf_src);
599                 BLI_addtail(&gpl_dst->frames, gpf_dst);
600
601                 /* if source frame was the current layer's 'active' frame, reassign that too */
602                 if (gpf_src == gpl_dst->actframe)
603                         gpl_dst->actframe = gpf_dst;
604         }
605
606         /* return new layer */
607         return gpl_dst;
608 }
609
610 /**
611  * Only copy internal data of GreasePencil ID from source to already allocated/initialized destination.
612  * You probably never want to use that directly, use BKE_id_copy or BKE_id_copy_ex for typical needs.
613  *
614  * WARNING! This function will not handle ID user count!
615  *
616  * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
617  */
618 void BKE_gpencil_copy_data(bGPdata *gpd_dst, const bGPdata *gpd_src, const int UNUSED(flag))
619 {
620         /* duplicate material array */
621         if (gpd_src->mat) {
622                 gpd_dst->mat = MEM_dupallocN(gpd_src->mat);
623         }
624
625         /* copy layers */
626         BLI_listbase_clear(&gpd_dst->layers);
627         for (const bGPDlayer *gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) {
628                 /* make a copy of source layer and its data */
629                 bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src);  /* TODO here too could add unused flags... */
630                 BLI_addtail(&gpd_dst->layers, gpl_dst);
631         }
632
633 }
634
635 /* Standard API to make a copy of GP datablock, separate from copying its data */
636 bGPdata *BKE_gpencil_copy(Main *bmain, const bGPdata *gpd)
637 {
638         bGPdata *gpd_copy;
639         BKE_id_copy(bmain, &gpd->id, (ID **)&gpd_copy);
640         return gpd_copy;
641 }
642
643 /* make a copy of a given gpencil datablock */
644 // XXX: Should this be deprecated?
645 bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy)
646 {
647         bGPdata *gpd_dst;
648
649         /* Yuck and super-uber-hyper yuck!!!
650          * Should be replaceable with a no-main copy (LIB_ID_COPY_NO_MAIN etc.), but not sure about it,
651          * so for now keep old code for that one. */
652
653         /* error checking */
654         if (gpd_src == NULL) {
655                 return NULL;
656         }
657
658         if (internal_copy) {
659                 /* make a straight copy for undo buffers used during stroke drawing */
660                 gpd_dst = MEM_dupallocN(gpd_src);
661         }
662         else {
663                 BLI_assert(bmain != NULL);
664                 BKE_id_copy(bmain, &gpd_src->id, (ID **)&gpd_dst);
665         }
666
667         /* Copy internal data (layers, etc.) */
668         BKE_gpencil_copy_data(gpd_dst, gpd_src, 0);
669
670         /* return new */
671         return gpd_dst;
672 }
673
674 void BKE_gpencil_make_local(Main *bmain, bGPdata *gpd, const bool lib_local)
675 {
676         BKE_id_make_local_generic(bmain, &gpd->id, true, lib_local);
677 }
678
679 /* ************************************************** */
680 /* GP Stroke API */
681
682 /* ensure selection status of stroke is in sync with its points */
683 void BKE_gpencil_stroke_sync_selection(bGPDstroke *gps)
684 {
685         bGPDspoint *pt;
686         int i;
687
688         /* error checking */
689         if (gps == NULL)
690                 return;
691
692         /* we'll stop when we find the first selected point,
693          * so initially, we must deselect
694          */
695         gps->flag &= ~GP_STROKE_SELECT;
696
697         for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
698                 if (pt->flag & GP_SPOINT_SELECT) {
699                         gps->flag |= GP_STROKE_SELECT;
700                         break;
701                 }
702         }
703 }
704
705 /* ************************************************** */
706 /* GP Frame API */
707
708 /* delete the last stroke of the given frame */
709 void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
710 {
711         bGPDstroke *gps = (gpf) ? gpf->strokes.last : NULL;
712         int cfra = (gpf) ? gpf->framenum : 0; /* assume that the current frame was not locked */
713
714         /* error checking */
715         if (ELEM(NULL, gpf, gps))
716                 return;
717
718         /* free the stroke and its data */
719         if (gps->points) {
720                 MEM_freeN(gps->points);
721         }
722         if (gps->dvert) {
723                 BKE_gpencil_free_stroke_weights(gps);
724                 MEM_freeN(gps->dvert);
725         }
726         MEM_freeN(gps->triangles);
727         BLI_freelinkN(&gpf->strokes, gps);
728
729         /* if frame has no strokes after this, delete it */
730         if (BLI_listbase_is_empty(&gpf->strokes)) {
731                 BKE_gpencil_layer_delframe(gpl, gpf);
732                 BKE_gpencil_layer_getframe(gpl, cfra, GP_GETFRAME_USE_PREV);
733         }
734 }
735
736 /* ************************************************** */
737 /* GP Layer API */
738
739 /* Check if the given layer is able to be edited or not */
740 bool gpencil_layer_is_editable(const bGPDlayer *gpl)
741 {
742         /* Sanity check */
743         if (gpl == NULL)
744                 return false;
745
746         /* Layer must be: Visible + Editable */
747         if ((gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) == 0) {
748                 /* Opacity must be sufficiently high that it is still "visible"
749                  * Otherwise, it's not really "visible" to the user, so no point editing...
750                  */
751                 if (gpl->opacity > GPENCIL_ALPHA_OPACITY_THRESH) {
752                         return true;
753                 }
754         }
755
756         /* Something failed */
757         return false;
758 }
759
760 /* Look up the gp-frame on the requested frame number, but don't add a new one */
761 bGPDframe *BKE_gpencil_layer_find_frame(bGPDlayer *gpl, int cframe)
762 {
763         bGPDframe *gpf;
764
765         /* Search in reverse order, since this is often used for playback/adding,
766          * where it's less likely that we're interested in the earlier frames
767          */
768         for (gpf = gpl->frames.last; gpf; gpf = gpf->prev) {
769                 if (gpf->framenum == cframe) {
770                         return gpf;
771                 }
772         }
773
774         return NULL;
775 }
776
777 /* get the appropriate gp-frame from a given layer
778  * - this sets the layer's actframe var (if allowed to)
779  * - extension beyond range (if first gp-frame is after all frame in interest and cannot add)
780  */
781 bGPDframe *BKE_gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
782 {
783         bGPDframe *gpf = NULL;
784         short found = 0;
785
786         /* error checking */
787         if (gpl == NULL) return NULL;
788
789         /* check if there is already an active frame */
790         if (gpl->actframe) {
791                 gpf = gpl->actframe;
792
793                 /* do not allow any changes to layer's active frame if layer is locked from changes
794                  * or if the layer has been set to stay on the current frame
795                  */
796                 if (gpl->flag & GP_LAYER_FRAMELOCK)
797                         return gpf;
798                 /* do not allow any changes to actframe if frame has painting tag attached to it */
799                 if (gpf->flag & GP_FRAME_PAINT)
800                         return gpf;
801
802                 /* try to find matching frame */
803                 if (gpf->framenum < cframe) {
804                         for (; gpf; gpf = gpf->next) {
805                                 if (gpf->framenum == cframe) {
806                                         found = 1;
807                                         break;
808                                 }
809                                 else if ((gpf->next) && (gpf->next->framenum > cframe)) {
810                                         found = 1;
811                                         break;
812                                 }
813                         }
814
815                         /* set the appropriate frame */
816                         if (addnew) {
817                                 if ((found) && (gpf->framenum == cframe))
818                                         gpl->actframe = gpf;
819                                 else if (addnew == GP_GETFRAME_ADD_COPY)
820                                         gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe);
821                                 else
822                                         gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
823                         }
824                         else if (found)
825                                 gpl->actframe = gpf;
826                         else
827                                 gpl->actframe = gpl->frames.last;
828                 }
829                 else {
830                         for (; gpf; gpf = gpf->prev) {
831                                 if (gpf->framenum <= cframe) {
832                                         found = 1;
833                                         break;
834                                 }
835                         }
836
837                         /* set the appropriate frame */
838                         if (addnew) {
839                                 if ((found) && (gpf->framenum == cframe))
840                                         gpl->actframe = gpf;
841                                 else if (addnew == GP_GETFRAME_ADD_COPY)
842                                         gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe);
843                                 else
844                                         gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
845                         }
846                         else if (found)
847                                 gpl->actframe = gpf;
848                         else
849                                 gpl->actframe = gpl->frames.first;
850                 }
851         }
852         else if (gpl->frames.first) {
853                 /* check which of the ends to start checking from */
854                 const int first = ((bGPDframe *)(gpl->frames.first))->framenum;
855                 const int last = ((bGPDframe *)(gpl->frames.last))->framenum;
856
857                 if (abs(cframe - first) > abs(cframe - last)) {
858                         /* find gp-frame which is less than or equal to cframe */
859                         for (gpf = gpl->frames.last; gpf; gpf = gpf->prev) {
860                                 if (gpf->framenum <= cframe) {
861                                         found = 1;
862                                         break;
863                                 }
864                         }
865                 }
866                 else {
867                         /* find gp-frame which is less than or equal to cframe */
868                         for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
869                                 if (gpf->framenum <= cframe) {
870                                         found = 1;
871                                         break;
872                                 }
873                         }
874                 }
875
876                 /* set the appropriate frame */
877                 if (addnew) {
878                         if ((found) && (gpf->framenum == cframe))
879                                 gpl->actframe = gpf;
880                         else
881                                 gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
882                 }
883                 else if (found)
884                         gpl->actframe = gpf;
885                 else {
886                         /* unresolved errogenous situation! */
887                         CLOG_STR_ERROR(&LOG, "cannot find appropriate gp-frame");
888                         /* gpl->actframe should still be NULL */
889                 }
890         }
891         else {
892                 /* currently no frames (add if allowed to) */
893                 if (addnew)
894                         gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
895                 else {
896                         /* don't do anything... this may be when no frames yet! */
897                         /* gpl->actframe should still be NULL */
898                 }
899         }
900
901         /* return */
902         return gpl->actframe;
903 }
904
905 /* delete the given frame from a layer */
906 bool BKE_gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
907 {
908         bool changed = false;
909
910         /* error checking */
911         if (ELEM(NULL, gpl, gpf))
912                 return false;
913
914         /* if this frame was active, make the previous frame active instead
915          * since it's tricky to set active frame otherwise
916          */
917         if (gpl->actframe == gpf)
918                 gpl->actframe = gpf->prev;
919
920         /* free the frame and its data */
921         changed = BKE_gpencil_free_strokes(gpf);
922         BLI_freelinkN(&gpl->frames, gpf);
923
924         return changed;
925 }
926
927 /* get the active gp-layer for editing */
928 bGPDlayer *BKE_gpencil_layer_getactive(bGPdata *gpd)
929 {
930         bGPDlayer *gpl;
931
932         /* error checking */
933         if (ELEM(NULL, gpd, gpd->layers.first))
934                 return NULL;
935
936         /* loop over layers until found (assume only one active) */
937         for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
938                 if (gpl->flag & GP_LAYER_ACTIVE)
939                         return gpl;
940         }
941
942         /* no active layer found */
943         return NULL;
944 }
945
946 /* set the active gp-layer */
947 void BKE_gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active)
948 {
949         bGPDlayer *gpl;
950
951         /* error checking */
952         if (ELEM(NULL, gpd, gpd->layers.first, active))
953                 return;
954
955         /* loop over layers deactivating all */
956         for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
957                 gpl->flag &= ~GP_LAYER_ACTIVE;
958                 if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
959                         gpl->flag |= GP_LAYER_LOCKED;
960                 }
961         }
962
963         /* set as active one */
964         active->flag |= GP_LAYER_ACTIVE;
965         if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
966                 active->flag &= ~GP_LAYER_LOCKED;
967         }
968 }
969
970 /* delete the active gp-layer */
971 void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl)
972 {
973         /* error checking */
974         if (ELEM(NULL, gpd, gpl))
975                 return;
976
977         /* free layer */
978         BKE_gpencil_free_frames(gpl);
979
980         /* free icon providing preview of icon color */
981         BKE_icon_delete(gpl->runtime.icon_id);
982
983         BLI_freelinkN(&gpd->layers, gpl);
984 }
985
986 Material *BKE_gpencil_get_material_from_brush(Brush *brush)
987 {
988         Material *ma = NULL;
989
990         if ((brush != NULL) && (brush->gpencil_settings != NULL) &&
991             (brush->gpencil_settings->material != NULL))
992         {
993                 ma = brush->gpencil_settings->material;
994         }
995
996         return ma;
997 }
998
999 /* Get active color, and add all default settings if we don't find anything */
1000 Material *BKE_gpencil_material_ensure(Main *bmain, Object *ob)
1001 {
1002         Material *ma = NULL;
1003
1004         /* sanity checks */
1005         if (ELEM(NULL, bmain, ob))
1006                 return NULL;
1007
1008         ma = give_current_material(ob, ob->actcol);
1009         if (ma == NULL) {
1010                 if (ob->totcol == 0) {
1011                         BKE_object_material_slot_add(bmain, ob);
1012                 }
1013                 ma = BKE_material_add_gpencil(bmain, DATA_("Material"));
1014                 assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
1015         }
1016         else if (ma->gp_style == NULL) {
1017                 BKE_material_init_gpencil_settings(ma);
1018         }
1019
1020         return ma;
1021 }
1022
1023 /* ************************************************** */
1024 /* GP Object - Boundbox Support */
1025
1026 /**
1027  * Get min/max coordinate bounds for single stroke
1028  * \return Returns whether we found any selected points
1029  */
1030 bool BKE_gpencil_stroke_minmax(
1031         const bGPDstroke *gps, const bool use_select,
1032         float r_min[3], float r_max[3])
1033 {
1034         const bGPDspoint *pt;
1035         int i;
1036         bool changed = false;
1037
1038         if (ELEM(NULL, gps, r_min, r_max))
1039                 return false;
1040
1041         for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1042                 if ((use_select == false) || (pt->flag & GP_SPOINT_SELECT)) {
1043                         minmax_v3v3_v3(r_min, r_max, &pt->x);
1044                         changed = true;
1045                 }
1046         }
1047         return changed;
1048 }
1049
1050 /* get min/max bounds of all strokes in GP datablock */
1051 bool BKE_gpencil_data_minmax(Object *ob, const bGPdata *gpd, float r_min[3], float r_max[3])
1052 {
1053         float bmat[3][3];
1054         bool changed = false;
1055
1056         INIT_MINMAX(r_min, r_max);
1057
1058         if (gpd == NULL)
1059                 return changed;
1060
1061         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1062                 bGPDframe *gpf = gpl->actframe;
1063
1064                 if (gpf != NULL) {
1065                         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1066                                 changed = BKE_gpencil_stroke_minmax(gps, false, r_min, r_max);
1067                         }
1068                 }
1069         }
1070
1071         if ((changed) && (ob)) {
1072                 copy_m3_m4(bmat, ob->obmat);
1073                 mul_m3_v3(bmat, r_min);
1074                 add_v3_v3(r_min, ob->obmat[3]);
1075                 mul_m3_v3(bmat, r_max);
1076                 add_v3_v3(r_max, ob->obmat[3]);
1077         }
1078
1079         return changed;
1080 }
1081
1082 bool BKE_gpencil_stroke_select_check(
1083         const bGPDstroke *gps)
1084 {
1085         const bGPDspoint *pt;
1086         int i;
1087         for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1088                 if (pt->flag & GP_SPOINT_SELECT) {
1089                         return true;
1090                 }
1091         }
1092         return false;
1093 }
1094
1095 /* compute center of bounding box */
1096 void BKE_gpencil_centroid_3d(bGPdata *gpd, float r_centroid[3])
1097 {
1098         float min[3], max[3], tot[3];
1099
1100         BKE_gpencil_data_minmax(NULL, gpd, min, max);
1101
1102         add_v3_v3v3(tot, min, max);
1103         mul_v3_v3fl(r_centroid, tot, 0.5f);
1104 }
1105
1106
1107 /* create bounding box values */
1108 static void boundbox_gpencil(Object *ob)
1109 {
1110         BoundBox *bb;
1111         bGPdata *gpd;
1112         float min[3], max[3];
1113
1114         if (ob->bb == NULL) {
1115                 ob->bb = MEM_callocN(sizeof(BoundBox), "GPencil boundbox");
1116         }
1117
1118         bb  = ob->bb;
1119         gpd = ob->data;
1120
1121         BKE_gpencil_data_minmax(NULL, gpd, min, max);
1122         BKE_boundbox_init_from_minmax(bb, min, max);
1123
1124         bb->flag &= ~BOUNDBOX_DIRTY;
1125 }
1126
1127 /* get bounding box */
1128 BoundBox *BKE_gpencil_boundbox_get(Object *ob)
1129 {
1130         bGPdata *gpd;
1131
1132         if (ELEM(NULL, ob, ob->data))
1133                 return NULL;
1134
1135         gpd = ob->data;
1136         if ((ob->bb) && ((ob->bb->flag & BOUNDBOX_DIRTY) == 0) &&
1137             ((gpd->flag & GP_DATA_CACHE_IS_DIRTY) == 0))
1138         {
1139                 return ob->bb;
1140         }
1141
1142         boundbox_gpencil(ob);
1143
1144         return ob->bb;
1145 }
1146
1147 /* ************************************************** */
1148 /* Apply Transforms */
1149
1150 void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4])
1151 {
1152         if (gpd == NULL)
1153                 return;
1154
1155         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1156                 /* FIXME: For now, we just skip parented layers.
1157                  * Otherwise, we have to update each frame to find
1158                  * the current parent position/effects.
1159                  */
1160                 if (gpl->parent) {
1161                         continue;
1162                 }
1163
1164                 for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1165                         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1166                                 bGPDspoint *pt;
1167                                 int i;
1168
1169                                 for (pt = gps->points, i = 0; i < gps->totpoints; pt++, i++) {
1170                                         mul_m4_v3(mat, &pt->x);
1171                                 }
1172
1173                                 /* TODO: Do we need to do this? distortion may mean we need to re-triangulate */
1174                                 gps->flag |= GP_STROKE_RECALC_GEOMETRY;
1175                                 gps->tot_triangles = 0;
1176                         }
1177                 }
1178         }
1179
1180 }
1181
1182 /* ************************************************** */
1183 /* GP Object - Vertex Groups */
1184
1185 /* remove a vertex group */
1186 void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup)
1187 {
1188         bGPdata *gpd = ob->data;
1189         MDeformVert *dvert = NULL;
1190         const int def_nr = BLI_findindex(&ob->defbase, defgroup);
1191
1192         /* Remove points data */
1193         if (gpd) {
1194                 for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1195                         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1196                                 for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1197                                         if (gps->dvert != NULL) {
1198                                                 for (int i = 0; i < gps->totpoints; i++) {
1199                                                         dvert = &gps->dvert[i];
1200                                                         MDeformWeight *dw = defvert_find_index(dvert, def_nr);
1201                                                         if (dw != NULL) {
1202                                                                 defvert_remove_group(dvert, dw);
1203                                                         }
1204                                                         else {
1205                                                                 /* reorganize weights in other strokes */
1206                                                                 for (int g = 0; g < gps->dvert->totweight; g++) {
1207                                                                         dw = &dvert->dw[g];
1208                                                                         if ((dw != NULL) && (dw->def_nr > def_nr)) {
1209                                                                                 dw->def_nr--;
1210                                                                         }
1211                                                                 }
1212                                                         }
1213                                                 }
1214                                         }
1215                                 }
1216                         }
1217                 }
1218         }
1219
1220         /* Remove the group */
1221         BLI_freelinkN(&ob->defbase, defgroup);
1222         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1223 }
1224
1225
1226 void BKE_gpencil_dvert_ensure(bGPDstroke *gps)
1227 {
1228         if (gps->dvert == NULL) {
1229                 gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
1230         }
1231 }
1232
1233 /* ************************************************** */
1234
1235 /**
1236  * Apply smooth to stroke point
1237  * \param gps: Stroke to smooth
1238  * \param i: Point index
1239  * \param inf: Amount of smoothing to apply
1240  */
1241 bool BKE_gpencil_smooth_stroke(bGPDstroke *gps, int i, float inf)
1242 {
1243         bGPDspoint *pt = &gps->points[i];
1244         // float pressure = 0.0f;
1245         float sco[3] = { 0.0f };
1246
1247         /* Do nothing if not enough points to smooth out */
1248         if (gps->totpoints <= 2) {
1249                 return false;
1250         }
1251
1252         /* Only affect endpoints by a fraction of the normal strength,
1253          * to prevent the stroke from shrinking too much
1254          */
1255         if ((i == 0) || (i == gps->totpoints - 1)) {
1256                 inf *= 0.1f;
1257         }
1258
1259         /* Compute smoothed coordinate by taking the ones nearby */
1260         /* XXX: This is potentially slow, and suffers from accumulation error as earlier points are handled before later ones */
1261         {
1262                 // XXX: this is hardcoded to look at 2 points on either side of the current one (i.e. 5 items total)
1263                 const int   steps = 2;
1264                 const float average_fac = 1.0f / (float)(steps * 2 + 1);
1265                 int step;
1266
1267                 /* add the point itself */
1268                 madd_v3_v3fl(sco, &pt->x, average_fac);
1269
1270                 /* n-steps before/after current point */
1271                 // XXX: review how the endpoints are treated by this algorithm
1272                 // XXX: falloff measures should also introduce some weighting variations, so that further-out points get less weight
1273                 for (step = 1; step <= steps; step++) {
1274                         bGPDspoint *pt1, *pt2;
1275                         int before = i - step;
1276                         int after = i + step;
1277
1278                         CLAMP_MIN(before, 0);
1279                         CLAMP_MAX(after, gps->totpoints - 1);
1280
1281                         pt1 = &gps->points[before];
1282                         pt2 = &gps->points[after];
1283
1284                         /* add both these points to the average-sum (s += p[i]/n) */
1285                         madd_v3_v3fl(sco, &pt1->x, average_fac);
1286                         madd_v3_v3fl(sco, &pt2->x, average_fac);
1287
1288                 }
1289         }
1290
1291         /* Based on influence factor, blend between original and optimal smoothed coordinate */
1292         interp_v3_v3v3(&pt->x, &pt->x, sco, inf);
1293
1294         return true;
1295 }
1296
1297 /**
1298  * Apply smooth for strength to stroke point */
1299 bool BKE_gpencil_smooth_stroke_strength(bGPDstroke *gps, int point_index, float influence)
1300 {
1301         bGPDspoint *ptb = &gps->points[point_index];
1302
1303         /* Do nothing if not enough points */
1304         if (gps->totpoints <= 2) {
1305                 return false;
1306         }
1307
1308         /* Compute theoretical optimal value using distances */
1309         bGPDspoint *pta, *ptc;
1310         int before = point_index - 1;
1311         int after = point_index + 1;
1312
1313         CLAMP_MIN(before, 0);
1314         CLAMP_MAX(after, gps->totpoints - 1);
1315
1316         pta = &gps->points[before];
1317         ptc = &gps->points[after];
1318
1319         /* the optimal value is the corresponding to the interpolation of the strength
1320          * at the distance of point b
1321          */
1322         float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
1323         /* sometimes the factor can be wrong due stroke geometry, so use middle point */
1324         if ((fac < 0.0f) || (fac > 1.0f)) {
1325                 fac = 0.5f;
1326         }
1327         const float optimal = (1.0f - fac) * pta->strength + fac * ptc->strength;
1328
1329         /* Based on influence factor, blend between original and optimal */
1330         ptb->strength = (1.0f - influence) * ptb->strength + influence * optimal;
1331
1332         return true;
1333 }
1334
1335 /**
1336  * Apply smooth for thickness to stroke point (use pressure) */
1337 bool BKE_gpencil_smooth_stroke_thickness(bGPDstroke *gps, int point_index, float influence)
1338 {
1339         bGPDspoint *ptb = &gps->points[point_index];
1340
1341         /* Do nothing if not enough points */
1342         if ((gps->totpoints <= 2) || (point_index < 1)) {
1343                 return false;
1344         }
1345
1346         /* Compute theoretical optimal value using distances */
1347         bGPDspoint *pta, *ptc;
1348         int before = point_index - 1;
1349         int after = point_index + 1;
1350
1351         CLAMP_MIN(before, 0);
1352         CLAMP_MAX(after, gps->totpoints - 1);
1353
1354         pta = &gps->points[before];
1355         ptc = &gps->points[after];
1356
1357         /* the optimal value is the corresponding to the interpolation of the pressure
1358          * at the distance of point b
1359          */
1360         float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
1361         /* sometimes the factor can be wrong due stroke geometry, so use middle point */
1362         if ((fac < 0.0f) || (fac > 1.0f)) {
1363                 fac = 0.5f;
1364         }
1365         float optimal = interpf(ptc->pressure, pta->pressure, fac);
1366
1367         /* Based on influence factor, blend between original and optimal */
1368         ptb->pressure = interpf(optimal, ptb->pressure, influence);
1369
1370         return true;
1371 }
1372
1373 /**
1374 * Apply smooth for UV rotation to stroke point (use pressure) */
1375 bool BKE_gpencil_smooth_stroke_uv(bGPDstroke *gps, int point_index, float influence)
1376 {
1377         bGPDspoint *ptb = &gps->points[point_index];
1378
1379         /* Do nothing if not enough points */
1380         if (gps->totpoints <= 2) {
1381                 return false;
1382         }
1383
1384         /* Compute theoretical optimal value */
1385         bGPDspoint *pta, *ptc;
1386         int before = point_index - 1;
1387         int after = point_index + 1;
1388
1389         CLAMP_MIN(before, 0);
1390         CLAMP_MAX(after, gps->totpoints - 1);
1391
1392         pta = &gps->points[before];
1393         ptc = &gps->points[after];
1394
1395         /* the optimal value is the corresponding to the interpolation of the pressure
1396          * at the distance of point b
1397          */
1398         float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
1399         /* sometimes the factor can be wrong due stroke geometry, so use middle point */
1400         if ((fac < 0.0f) || (fac > 1.0f)) {
1401                 fac = 0.5f;
1402         }
1403         float optimal = interpf(ptc->uv_rot, pta->uv_rot, fac);
1404
1405         /* Based on influence factor, blend between original and optimal */
1406         ptb->uv_rot = interpf(optimal, ptb->uv_rot, influence);
1407         CLAMP(ptb->uv_rot, -M_PI_2, M_PI_2);
1408
1409         return true;
1410 }
1411
1412 /**
1413  * Get range of selected frames in layer.
1414  * Always the active frame is considered as selected, so if no more selected the range
1415  * will be equal to the current active frame.
1416  * \param gpl: Layer
1417  * \param r_initframe: Number of first selected frame
1418  * \param r_endframe: Number of last selected frame
1419  */
1420 void BKE_gpencil_get_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_endframe)
1421 {
1422         *r_initframe = gpl->actframe->framenum;
1423         *r_endframe = gpl->actframe->framenum;
1424
1425         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1426                 if (gpf->flag & GP_FRAME_SELECT) {
1427                         if (gpf->framenum < *r_initframe) {
1428                                 *r_initframe = gpf->framenum;
1429                         }
1430                         if (gpf->framenum > *r_endframe) {
1431                                 *r_endframe = gpf->framenum;
1432                         }
1433                 }
1434         }
1435 }
1436
1437 /**
1438  * Get Falloff factor base on frame range
1439  * \param gpf: Frame
1440  * \param actnum: Number of active frame in layer
1441  * \param f_init: Number of first selected frame
1442  * \param f_end: Number of last selected frame
1443  * \param cur_falloff: Curve with falloff factors
1444  */
1445 float BKE_gpencil_multiframe_falloff_calc(bGPDframe *gpf, int actnum, int f_init, int f_end, CurveMapping *cur_falloff)
1446 {
1447         float fnum = 0.5f; /* default mid curve */
1448         float value;
1449
1450         /* check curve is available */
1451         if (cur_falloff == NULL) {
1452                 return 1.0f;
1453         }
1454
1455         /* frames to the right of the active frame */
1456         if (gpf->framenum < actnum) {
1457                 fnum = (float)(gpf->framenum - f_init) / (actnum - f_init);
1458                 fnum *= 0.5f;
1459                 value = curvemapping_evaluateF(cur_falloff, 0, fnum);
1460         }
1461         /* frames to the left of the active frame */
1462         else if (gpf->framenum > actnum) {
1463                 fnum = (float)(gpf->framenum - actnum) / (f_end - actnum);
1464                 fnum *= 0.5f;
1465                 value = curvemapping_evaluateF(cur_falloff, 0, fnum + 0.5f);
1466         }
1467         else {
1468                 value = 1.0f;
1469         }
1470
1471         return value;
1472 }
1473
1474 /* remove strokes using a material */
1475 void BKE_gpencil_material_index_remove(bGPdata *gpd, int index)
1476 {
1477         bGPDstroke *gps, *gpsn;
1478
1479                 for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1480                         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1481                                 for (gps = gpf->strokes.first; gps; gps = gpsn) {
1482                                         gpsn = gps->next;
1483                                         if (gps->mat_nr == index) {
1484                                                 if (gps->points) {
1485                                                         MEM_freeN(gps->points);
1486                                                 }
1487                                                 if (gps->dvert) {
1488                                                         BKE_gpencil_free_stroke_weights(gps);
1489                                                         MEM_freeN(gps->dvert);
1490                                                 }
1491                                                 if (gps->triangles) MEM_freeN(gps->triangles);
1492                                                 BLI_freelinkN(&gpf->strokes, gps);
1493                                         }
1494                                         else {
1495                                                 /* reassign strokes */
1496                                                 if (gps->mat_nr > index) {
1497                                                         gps->mat_nr--;
1498                                                 }
1499                                         }
1500                                 }
1501                         }
1502                 }
1503 }
1504
1505 void BKE_gpencil_material_remap(struct bGPdata *gpd, const unsigned int *remap, unsigned int remap_len)
1506 {
1507         const short remap_len_short = (short)remap_len;
1508
1509 #define MAT_NR_REMAP(n) \
1510         if (n < remap_len_short) { \
1511                 BLI_assert(n >= 0 && remap[n] < remap_len_short); \
1512                 n = remap[n]; \
1513         } ((void)0)
1514
1515         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1516                 for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1517                         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1518                                 /* reassign strokes */
1519                                 MAT_NR_REMAP(gps->mat_nr);
1520                         }
1521                 }
1522         }
1523
1524 #undef MAT_NR_REMAP
1525
1526 }
1527
1528 /* statistics functions */
1529 void BKE_gpencil_stats_update(bGPdata *gpd)
1530 {
1531         gpd->totlayer = 0;
1532         gpd->totframe = 0;
1533         gpd->totstroke = 0;
1534         gpd->totpoint = 0;
1535
1536         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1537                 gpd->totlayer++;
1538                 for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1539                         gpd->totframe++;
1540                         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1541                                 gpd->totstroke++;
1542                                 gpd->totpoint += gps->totpoints;
1543                         }
1544                 }
1545         }
1546
1547 }
1548
1549 /* get material index */
1550 int BKE_gpencil_get_material_index(Object *ob, Material *ma)
1551 {
1552         short *totcol = give_totcolp(ob);
1553         Material *read_ma = NULL;
1554         for (short i = 0; i < *totcol; i++) {
1555                 read_ma = give_current_material(ob, i + 1);
1556                 if (ma == read_ma) {
1557                         return i + 1;
1558                 }
1559         }
1560
1561         return 0;
1562 }
1563
1564 /* Get points of stroke always flat to view not affected by camera view or view position */
1565 void BKE_gpencil_stroke_2d_flat(const bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction)
1566 {
1567         BLI_assert(totpoints >= 2);
1568
1569         const bGPDspoint *pt0 = &points[0];
1570         const bGPDspoint *pt1 = &points[1];
1571         const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
1572
1573         float locx[3];
1574         float locy[3];
1575         float loc3[3];
1576         float normal[3];
1577
1578         /* local X axis (p0 -> p1) */
1579         sub_v3_v3v3(locx, &pt1->x, &pt0->x);
1580
1581         /* point vector at 3/4 */
1582         float v3[3];
1583         if (totpoints == 2) {
1584                 mul_v3_v3fl(v3, &pt3->x, 0.001f);
1585         }
1586         else {
1587                 copy_v3_v3(v3, &pt3->x);
1588         }
1589
1590         sub_v3_v3v3(loc3, v3, &pt0->x);
1591
1592         /* vector orthogonal to polygon plane */
1593         cross_v3_v3v3(normal, locx, loc3);
1594
1595         /* local Y axis (cross to normal/x axis) */
1596         cross_v3_v3v3(locy, normal, locx);
1597
1598         /* Normalize vectors */
1599         normalize_v3(locx);
1600         normalize_v3(locy);
1601
1602         /* Get all points in local space */
1603         for (int i = 0; i < totpoints; i++) {
1604                 const bGPDspoint *pt = &points[i];
1605                 float loc[3];
1606
1607                 /* Get local space using first point as origin */
1608                 sub_v3_v3v3(loc, &pt->x, &pt0->x);
1609
1610                 points2d[i][0] = dot_v3v3(loc, locx);
1611                 points2d[i][1] = dot_v3v3(loc, locy);
1612         }
1613
1614         /* Concave (-1), Convex (1), or Autodetect (0)? */
1615         *r_direction = (int)locy[2];
1616 }
1617
1618 /* Get points of stroke always flat to view not affected by camera view or view position
1619  * using another stroke as reference
1620  */
1621 void BKE_gpencil_stroke_2d_flat_ref(
1622         const bGPDspoint *ref_points, int ref_totpoints,
1623         const bGPDspoint *points, int totpoints,
1624         float(*points2d)[2], const float scale, int *r_direction)
1625 {
1626         BLI_assert(totpoints >= 2);
1627
1628         const bGPDspoint *pt0 = &ref_points[0];
1629         const bGPDspoint *pt1 = &ref_points[1];
1630         const bGPDspoint *pt3 = &ref_points[(int)(ref_totpoints * 0.75)];
1631
1632         float locx[3];
1633         float locy[3];
1634         float loc3[3];
1635         float normal[3];
1636
1637         /* local X axis (p0 -> p1) */
1638         sub_v3_v3v3(locx, &pt1->x, &pt0->x);
1639
1640         /* point vector at 3/4 */
1641         float v3[3];
1642         if (totpoints == 2) {
1643                 mul_v3_v3fl(v3, &pt3->x, 0.001f);
1644         }
1645         else {
1646                 copy_v3_v3(v3, &pt3->x);
1647         }
1648
1649         sub_v3_v3v3(loc3, v3, &pt0->x);
1650
1651         /* vector orthogonal to polygon plane */
1652         cross_v3_v3v3(normal, locx, loc3);
1653
1654         /* local Y axis (cross to normal/x axis) */
1655         cross_v3_v3v3(locy, normal, locx);
1656
1657         /* Normalize vectors */
1658         normalize_v3(locx);
1659         normalize_v3(locy);
1660
1661         /* Get all points in local space */
1662         for (int i = 0; i < totpoints; i++) {
1663                 const bGPDspoint *pt = &points[i];
1664                 float loc[3];
1665                 float v1[3];
1666                 float vn[3] = { 0.0f, 0.0f, 0.0f };
1667
1668                 /* apply scale to extremes of the stroke to get better collision detection
1669                  * the scale is divided to get more control in the UI parameter
1670                  */
1671                 /* first point */
1672                 if (i == 0) {
1673                         const bGPDspoint *pt_next = &points[i + 1];
1674                         sub_v3_v3v3(vn, &pt->x, &pt_next->x);
1675                         normalize_v3(vn);
1676                         mul_v3_fl(vn, scale / 10.0f);
1677                         add_v3_v3v3(v1, &pt->x, vn);
1678                 }
1679                 /* last point */
1680                 else if (i == totpoints - 1) {
1681                         const bGPDspoint *pt_prev = &points[i - 1];
1682                         sub_v3_v3v3(vn, &pt->x, &pt_prev->x);
1683                         normalize_v3(vn);
1684                         mul_v3_fl(vn, scale / 10.0f);
1685                         add_v3_v3v3(v1, &pt->x, vn);
1686                 }
1687                 else {
1688                         copy_v3_v3(v1, &pt->x);
1689                 }
1690
1691                 /* Get local space using first point as origin (ref stroke) */
1692                 sub_v3_v3v3(loc, v1, &pt0->x);
1693
1694                 points2d[i][0] = dot_v3v3(loc, locx);
1695                 points2d[i][1] = dot_v3v3(loc, locy);
1696         }
1697
1698         /* Concave (-1), Convex (1), or Autodetect (0)? */
1699         *r_direction = (int)locy[2];
1700 }