6981d70019aca51ae5c0753399fba3d441558fcf
[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
21  * \ingroup bke
22  */
23
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <stddef.h>
29 #include <math.h>
30
31 #include "CLG_log.h"
32
33 #include "MEM_guardedalloc.h"
34
35 #include "BLI_blenlib.h"
36 #include "BLI_utildefines.h"
37 #include "BLI_math_vector.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_deform.h"
53 #include "BKE_gpencil.h"
54 #include "BKE_colortools.h"
55 #include "BKE_icons.h"
56 #include "BKE_library.h"
57 #include "BKE_main.h"
58 #include "BKE_object.h"
59 #include "BKE_material.h"
60
61 #include "DEG_depsgraph.h"
62
63 static CLG_LogRef LOG = {"bke.gpencil"};
64
65 /* ************************************************** */
66 /* Draw Engine */
67
68 void(*BKE_gpencil_batch_cache_dirty_tag_cb)(bGPdata *gpd) = NULL;
69 void(*BKE_gpencil_batch_cache_free_cb)(bGPdata *gpd) = NULL;
70
71 void BKE_gpencil_batch_cache_dirty_tag(bGPdata *gpd)
72 {
73         if (gpd) {
74                 DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
75                 BKE_gpencil_batch_cache_dirty_tag_cb(gpd);
76         }
77 }
78
79 void BKE_gpencil_batch_cache_free(bGPdata *gpd)
80 {
81         if (gpd) {
82                 BKE_gpencil_batch_cache_free_cb(gpd);
83         }
84 }
85
86 /* ************************************************** */
87 /* Memory Management */
88
89 /* clean vertex groups weights */
90 void BKE_gpencil_free_point_weights(MDeformVert *dvert)
91 {
92         if (dvert == NULL) {
93                 return;
94         }
95         MEM_SAFE_FREE(dvert->dw);
96 }
97
98 void BKE_gpencil_free_stroke_weights(bGPDstroke *gps)
99 {
100         if (gps == NULL) {
101                 return;
102         }
103
104         if (gps->dvert == NULL) {
105                 return;
106         }
107
108         for (int i = 0; i < gps->totpoints; i++) {
109                 MDeformVert *dvert = &gps->dvert[i];
110                 BKE_gpencil_free_point_weights(dvert);
111         }
112 }
113
114 /* free stroke, doesn't unlink from any listbase */
115 void BKE_gpencil_free_stroke(bGPDstroke *gps)
116 {
117         if (gps == NULL) {
118                 return;
119         }
120         /* free stroke memory arrays, then stroke itself */
121         if (gps->points) {
122                 MEM_freeN(gps->points);
123         }
124         if (gps->dvert) {
125                 BKE_gpencil_free_stroke_weights(gps);
126                 MEM_freeN(gps->dvert);
127         }
128         if (gps->triangles)
129                 MEM_freeN(gps->triangles);
130
131         MEM_freeN(gps);
132 }
133
134 /* Free strokes belonging to a gp-frame */
135 bool BKE_gpencil_free_strokes(bGPDframe *gpf)
136 {
137         bGPDstroke *gps_next;
138         bool changed = (BLI_listbase_is_empty(&gpf->strokes) == false);
139
140         /* free strokes */
141         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps_next) {
142                 gps_next = gps->next;
143                 BKE_gpencil_free_stroke(gps);
144         }
145         BLI_listbase_clear(&gpf->strokes);
146
147         return changed;
148 }
149
150 /* Free strokes and colors belonging to a gp-frame */
151 bool BKE_gpencil_free_frame_runtime_data(bGPDframe *derived_gpf)
152 {
153         bGPDstroke *gps_next;
154         if (!derived_gpf) {
155                 return false;
156         }
157
158         /* free strokes */
159         for (bGPDstroke *gps = derived_gpf->strokes.first; gps; gps = gps_next) {
160                 gps_next = gps->next;
161                 BKE_gpencil_free_stroke(gps);
162         }
163         BLI_listbase_clear(&derived_gpf->strokes);
164
165         return true;
166 }
167
168 /* Free all of a gp-layer's frames */
169 void BKE_gpencil_free_frames(bGPDlayer *gpl)
170 {
171         bGPDframe *gpf_next;
172
173         /* error checking */
174         if (gpl == NULL) return;
175
176         /* free frames */
177         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf_next) {
178                 gpf_next = gpf->next;
179
180                 /* free strokes and their associated memory */
181                 BKE_gpencil_free_strokes(gpf);
182                 BLI_freelinkN(&gpl->frames, gpf);
183         }
184         gpl->actframe = NULL;
185 }
186
187
188
189 /* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */
190 void BKE_gpencil_free_layers(ListBase *list)
191 {
192         bGPDlayer *gpl_next;
193
194         /* error checking */
195         if (list == NULL) return;
196
197         /* delete layers */
198         for (bGPDlayer *gpl = list->first; gpl; gpl = gpl_next) {
199                 gpl_next = gpl->next;
200
201                 /* free layers and their data */
202                 BKE_gpencil_free_frames(gpl);
203                 BLI_freelinkN(list, gpl);
204         }
205 }
206
207 /** Free (or release) any data used by this grease pencil (does not free the gpencil itself). */
208 void BKE_gpencil_free(bGPdata *gpd, bool free_all)
209 {
210         /* clear animation data */
211         BKE_animdata_free(&gpd->id, false);
212
213         /* free layers */
214         BKE_gpencil_free_layers(&gpd->layers);
215
216         /* materials */
217         MEM_SAFE_FREE(gpd->mat);
218
219         /* free all data */
220         if (free_all) {
221                 /* clear cache */
222                 BKE_gpencil_batch_cache_free(gpd);
223         }
224 }
225
226 /* ************************************************** */
227 /* Container Creation */
228
229 /* add a new gp-frame to the given layer */
230 bGPDframe *BKE_gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
231 {
232         bGPDframe *gpf = NULL, *gf = NULL;
233         short state = 0;
234
235         /* error checking */
236         if (gpl == NULL)
237                 return NULL;
238
239         /* allocate memory for this frame */
240         gpf = MEM_callocN(sizeof(bGPDframe), "bGPDframe");
241         gpf->framenum = cframe;
242
243         /* find appropriate place to add frame */
244         if (gpl->frames.first) {
245                 for (gf = gpl->frames.first; gf; gf = gf->next) {
246                         /* check if frame matches one that is supposed to be added */
247                         if (gf->framenum == cframe) {
248                                 state = -1;
249                                 break;
250                         }
251
252                         /* if current frame has already exceeded the frame to add, add before */
253                         if (gf->framenum > cframe) {
254                                 BLI_insertlinkbefore(&gpl->frames, gf, gpf);
255                                 state = 1;
256                                 break;
257                         }
258                 }
259         }
260
261         /* check whether frame was added successfully */
262         if (state == -1) {
263                 CLOG_ERROR(&LOG, "Frame (%d) existed already for this layer. Using existing frame", cframe);
264
265                 /* free the newly created one, and use the old one instead */
266                 MEM_freeN(gpf);
267
268                 /* return existing frame instead... */
269                 BLI_assert(gf != NULL);
270                 gpf = gf;
271         }
272         else if (state == 0) {
273                 /* add to end then! */
274                 BLI_addtail(&gpl->frames, gpf);
275         }
276
277         /* return frame */
278         return gpf;
279 }
280
281 /* add a copy of the active gp-frame to the given layer */
282 bGPDframe *BKE_gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
283 {
284         bGPDframe *new_frame;
285         bool found = false;
286
287         /* Error checking/handling */
288         if (gpl == NULL) {
289                 /* no layer */
290                 return NULL;
291         }
292         else if (gpl->actframe == NULL) {
293                 /* no active frame, so just create a new one from scratch */
294                 return BKE_gpencil_frame_addnew(gpl, cframe);
295         }
296
297         /* Create a copy of the frame */
298         new_frame = BKE_gpencil_frame_duplicate(gpl->actframe);
299
300         /* Find frame to insert it before */
301         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
302                 if (gpf->framenum > cframe) {
303                         /* Add it here */
304                         BLI_insertlinkbefore(&gpl->frames, gpf, new_frame);
305
306                         found = true;
307                         break;
308                 }
309                 else if (gpf->framenum == cframe) {
310                         /* This only happens when we're editing with framelock on...
311                          * - Delete the new frame and don't do anything else here...
312                          */
313                         BKE_gpencil_free_strokes(new_frame);
314                         MEM_freeN(new_frame);
315                         new_frame = NULL;
316
317                         found = true;
318                         break;
319                 }
320         }
321
322         if (found == false) {
323                 /* Add new frame to the end */
324                 BLI_addtail(&gpl->frames, new_frame);
325         }
326
327         /* Ensure that frame is set up correctly, and return it */
328         if (new_frame) {
329                 new_frame->framenum = cframe;
330                 gpl->actframe = new_frame;
331         }
332
333         return new_frame;
334 }
335
336 /* add a new gp-layer and make it the active layer */
337 bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setactive)
338 {
339         bGPDlayer *gpl = NULL;
340         bGPDlayer *gpl_active = NULL;
341
342         /* check that list is ok */
343         if (gpd == NULL)
344                 return NULL;
345
346         /* allocate memory for frame and add to end of list */
347         gpl = MEM_callocN(sizeof(bGPDlayer), "bGPDlayer");
348
349         gpl_active = BKE_gpencil_layer_getactive(gpd);
350
351         /* add to datablock */
352         if (gpl_active == NULL) {
353                 BLI_addtail(&gpd->layers, gpl);
354         }
355         else {
356                 /* if active layer, add after that layer */
357                 BLI_insertlinkafter(&gpd->layers, gpl_active, gpl);
358         }
359
360         /* annotation vs GP Object behavior is slightly different */
361         if (gpd->flag & GP_DATA_ANNOTATIONS) {
362                 /* set default color of new strokes for this layer */
363                 copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
364                 gpl->opacity = 1.0f;
365
366                 /* set default thickness of new strokes for this layer */
367                 gpl->thickness = 3;
368
369                 /* Onion colors */
370                 ARRAY_SET_ITEMS(gpl->gcolor_prev, 0.302f, 0.851f, 0.302f);
371                 ARRAY_SET_ITEMS(gpl->gcolor_next, 0.250f, 0.1f, 1.0f);
372         }
373         else {
374                 /* thickness parameter represents "thickness change", not absolute thickness */
375                 gpl->thickness = 0;
376                 gpl->opacity = 1.0f;
377         }
378
379         /* auto-name */
380         BLI_strncpy(gpl->info, name, sizeof(gpl->info));
381         BLI_uniquename(&gpd->layers, gpl,
382                        (gpd->flag & GP_DATA_ANNOTATIONS) ? DATA_("Note") : DATA_("GP_Layer"),
383                        '.',
384                        offsetof(bGPDlayer, info),
385                        sizeof(gpl->info));
386
387         /* make this one the active one */
388         if (setactive)
389                 BKE_gpencil_layer_setactive(gpd, gpl);
390
391         /* return layer */
392         return gpl;
393 }
394
395 /* add a new gp-datablock */
396 bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
397 {
398         bGPdata *gpd;
399
400         /* allocate memory for a new block */
401         gpd = BKE_libblock_alloc(bmain, ID_GD, name, 0);
402
403         /* initial settings */
404         gpd->flag = (GP_DATA_DISPINFO | GP_DATA_EXPAND);
405
406         /* general flags */
407         gpd->flag |= GP_DATA_VIEWALIGN;
408         gpd->flag |= GP_DATA_STROKE_FORCE_RECALC;
409         /* always enable object onion skin swith */
410         gpd->flag |= GP_DATA_SHOW_ONIONSKINS;
411         /* GP object specific settings */
412         ARRAY_SET_ITEMS(gpd->line_color, 0.6f, 0.6f, 0.6f, 0.5f);
413
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 void BKE_gpencil_brush_set_material(Brush *brush, Material *ma)
1000 {
1001         BLI_assert(brush);
1002         BLI_assert(brush->gpencil_settings);
1003         if (brush->gpencil_settings->material != ma) {
1004                 if (brush->gpencil_settings->material) {
1005                         id_us_min(&brush->gpencil_settings->material->id);
1006                 }
1007                 if (ma) {
1008                         id_us_plus(&ma->id);
1009                 }
1010                 brush->gpencil_settings->material = ma;
1011         }
1012 }
1013
1014 /* Adds the pinned material to the object if necessary. */
1015 Material *BKE_gpencil_handle_brush_material(Main *bmain, Object *ob, Brush *brush)
1016 {
1017         if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) {
1018                 Material *ma = BKE_gpencil_get_material_from_brush(brush);
1019
1020                 /* check if the material is already on object material slots and add it if missing */
1021                 if (ma && BKE_gpencil_get_material_index(ob, ma) < 0) {
1022                         BKE_object_material_slot_add(bmain, ob);
1023                         assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
1024                 }
1025
1026                 return ma;
1027         }
1028         else {
1029                 /* using active material instead */
1030                 return give_current_material(ob, ob->actcol);
1031         }
1032 }
1033
1034 /* Assigns the material to object (if not already present) and returns its index (mat_nr). */
1035 int BKE_gpencil_handle_material(Main *bmain, Object *ob, Material *material)
1036 {
1037         if (!material) {
1038                 return -1;
1039         }
1040         int index = BKE_gpencil_get_material_index(ob, material);
1041         if (index < 0) {
1042                 BKE_object_material_slot_add(bmain, ob);
1043                 assign_material(bmain, ob, material, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
1044                 return ob->totcol - 1;
1045         }
1046         return index;
1047 }
1048
1049 /** Creates a new gpencil material and assigns it to object.
1050  *
1051  * \param *r_index: value is set to zero based index of the new material if r_index is not NULL
1052  */
1053 Material *BKE_gpencil_handle_new_material(Main *bmain, Object *ob, const char *name, int *r_index)
1054 {
1055         Material *ma = BKE_material_add_gpencil(bmain, name);
1056         id_us_min(&ma->id); /* no users yet */
1057
1058         BKE_object_material_slot_add(bmain, ob);
1059         assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
1060
1061         if (r_index) {
1062                 *r_index = ob->actcol - 1;
1063         }
1064         return ma;
1065 }
1066
1067 /* Returns the material for a brush with respect to its pinned state. */
1068 Material *BKE_gpencil_get_material_for_brush(Object *ob, Brush *brush)
1069 {
1070         if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) {
1071                 Material *ma = BKE_gpencil_get_material_from_brush(brush);
1072                 return ma;
1073         }
1074         else {
1075                 return give_current_material(ob, ob->actcol);
1076         }
1077 }
1078
1079 /* Returns the material index for a brush with respect to its pinned state. */
1080 int BKE_gpencil_get_material_index_for_brush(Object *ob, Brush *brush)
1081 {
1082         if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) {
1083                 return BKE_gpencil_get_material_index(ob, brush->gpencil_settings->material);
1084         }
1085         else {
1086                 return ob->actcol - 1;
1087         }
1088 }
1089
1090 /* Guaranteed to return a material assigned to object. Returns never NULL. */
1091 Material *BKE_gpencil_current_input_toolsettings_material(Main *bmain, Object *ob, ToolSettings *ts)
1092 {
1093         if (ts && ts->gp_paint && ts->gp_paint->paint.brush) {
1094                 return BKE_gpencil_current_input_brush_material(bmain, ob, ts->gp_paint->paint.brush);
1095         }
1096         else {
1097                 return BKE_gpencil_current_input_brush_material(bmain, ob, NULL);
1098         }
1099 }
1100
1101 /* Guaranteed to return a material assigned to object. Returns never NULL. */
1102 Material *BKE_gpencil_current_input_brush_material(Main *bmain, Object *ob, Brush *brush)
1103 {
1104         if (brush) {
1105                 Material *ma = BKE_gpencil_handle_brush_material(bmain, ob, brush);
1106                 if (ma) {
1107                         return ma;
1108                 }
1109                 else if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) {
1110                         /* it is easier to just unpin a NULL material, instead of setting a new one */
1111                         brush->gpencil_settings->flag &= ~GP_BRUSH_MATERIAL_PINNED;
1112                 }
1113         }
1114         return BKE_gpencil_current_input_material(bmain, ob);
1115 }
1116
1117 /* Guaranteed to return a material assigned to object. Returns never NULL. Only use this for materials unrelated to user input */
1118 Material *BKE_gpencil_current_input_material(Main *bmain, Object *ob)
1119 {
1120         Material *ma = give_current_material(ob, ob->actcol);
1121         if (ma) {
1122                 return ma;
1123         }
1124         return BKE_gpencil_handle_new_material(bmain, ob, "Material", NULL);
1125 }
1126
1127 /* Get active color, and add all default settings if we don't find anything */
1128 Material *BKE_gpencil_material_ensure(Main *bmain, Object *ob)
1129 {
1130         Material *ma = NULL;
1131
1132         /* sanity checks */
1133         if (ELEM(NULL, bmain, ob))
1134                 return NULL;
1135
1136         ma = BKE_gpencil_current_input_material(bmain, ob);
1137         if (ma->gp_style == NULL) {
1138                 BKE_material_init_gpencil_settings(ma);
1139         }
1140
1141         return ma;
1142 }
1143
1144 /* ************************************************** */
1145 /* GP Object - Boundbox Support */
1146
1147 /**
1148  * Get min/max coordinate bounds for single stroke
1149  * \return Returns whether we found any selected points
1150  */
1151 bool BKE_gpencil_stroke_minmax(
1152         const bGPDstroke *gps, const bool use_select,
1153         float r_min[3], float r_max[3])
1154 {
1155         const bGPDspoint *pt;
1156         int i;
1157         bool changed = false;
1158
1159         if (ELEM(NULL, gps, r_min, r_max))
1160                 return false;
1161
1162         for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1163                 if ((use_select == false) || (pt->flag & GP_SPOINT_SELECT)) {
1164                         minmax_v3v3_v3(r_min, r_max, &pt->x);
1165                         changed = true;
1166                 }
1167         }
1168         return changed;
1169 }
1170
1171 /* get min/max bounds of all strokes in GP datablock */
1172 bool BKE_gpencil_data_minmax(const bGPdata *gpd, float r_min[3], float r_max[3])
1173 {
1174         bool changed = false;
1175
1176         INIT_MINMAX(r_min, r_max);
1177
1178         if (gpd == NULL)
1179                 return changed;
1180
1181         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1182                 bGPDframe *gpf = gpl->actframe;
1183
1184                 if (gpf != NULL) {
1185                         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1186                                 changed = BKE_gpencil_stroke_minmax(gps, false, r_min, r_max);
1187                         }
1188                 }
1189         }
1190
1191         return changed;
1192 }
1193
1194 bool BKE_gpencil_stroke_select_check(
1195         const bGPDstroke *gps)
1196 {
1197         const bGPDspoint *pt;
1198         int i;
1199         for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1200                 if (pt->flag & GP_SPOINT_SELECT) {
1201                         return true;
1202                 }
1203         }
1204         return false;
1205 }
1206
1207 /* compute center of bounding box */
1208 void BKE_gpencil_centroid_3d(bGPdata *gpd, float r_centroid[3])
1209 {
1210         float min[3], max[3], tot[3];
1211
1212         BKE_gpencil_data_minmax(gpd, min, max);
1213
1214         add_v3_v3v3(tot, min, max);
1215         mul_v3_v3fl(r_centroid, tot, 0.5f);
1216 }
1217
1218
1219 /* create bounding box values */
1220 static void boundbox_gpencil(Object *ob)
1221 {
1222         BoundBox *bb;
1223         bGPdata *gpd;
1224         float min[3], max[3];
1225
1226         if (ob->runtime.bb == NULL) {
1227                 ob->runtime.bb = MEM_callocN(sizeof(BoundBox), "GPencil boundbox");
1228         }
1229
1230         bb  = ob->runtime.bb;
1231         gpd = ob->data;
1232
1233         if (!BKE_gpencil_data_minmax(gpd, min, max)) {
1234                 min[0] = min[1] = min[2] = -1.0f;
1235                 max[0] = max[1] = max[2] = 1.0f;
1236         }
1237
1238         BKE_boundbox_init_from_minmax(bb, min, max);
1239
1240         bb->flag &= ~BOUNDBOX_DIRTY;
1241 }
1242
1243 /* get bounding box */
1244 BoundBox *BKE_gpencil_boundbox_get(Object *ob)
1245 {
1246         if (ELEM(NULL, ob, ob->data))
1247                 return NULL;
1248
1249         bGPdata *gpd = (bGPdata *)ob->data;
1250         if ((ob->runtime.bb) && ((gpd->flag & GP_DATA_CACHE_IS_DIRTY) == 0)) {
1251                 return ob->runtime.bb;
1252         }
1253
1254         boundbox_gpencil(ob);
1255
1256         return ob->runtime.bb;
1257 }
1258
1259 /* ************************************************** */
1260 /* Apply Transforms */
1261
1262 void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4])
1263 {
1264         if (gpd == NULL)
1265                 return;
1266
1267         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1268                 /* FIXME: For now, we just skip parented layers.
1269                  * Otherwise, we have to update each frame to find
1270                  * the current parent position/effects.
1271                  */
1272                 if (gpl->parent) {
1273                         continue;
1274                 }
1275
1276                 for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1277                         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1278                                 bGPDspoint *pt;
1279                                 int i;
1280
1281                                 for (pt = gps->points, i = 0; i < gps->totpoints; pt++, i++) {
1282                                         mul_m4_v3(mat, &pt->x);
1283                                 }
1284
1285                                 /* TODO: Do we need to do this? distortion may mean we need to re-triangulate */
1286                                 gps->flag |= GP_STROKE_RECALC_GEOMETRY;
1287                                 gps->tot_triangles = 0;
1288                         }
1289                 }
1290         }
1291
1292 }
1293
1294 /* ************************************************** */
1295 /* GP Object - Vertex Groups */
1296
1297 /* remove a vertex group */
1298 void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup)
1299 {
1300         bGPdata *gpd = ob->data;
1301         MDeformVert *dvert = NULL;
1302         const int def_nr = BLI_findindex(&ob->defbase, defgroup);
1303
1304         /* Remove points data */
1305         if (gpd) {
1306                 for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1307                         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1308                                 for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1309                                         if (gps->dvert != NULL) {
1310                                                 for (int i = 0; i < gps->totpoints; i++) {
1311                                                         dvert = &gps->dvert[i];
1312                                                         MDeformWeight *dw = defvert_find_index(dvert, def_nr);
1313                                                         if (dw != NULL) {
1314                                                                 defvert_remove_group(dvert, dw);
1315                                                         }
1316                                                         else {
1317                                                                 /* reorganize weights in other strokes */
1318                                                                 for (int g = 0; g < gps->dvert->totweight; g++) {
1319                                                                         dw = &dvert->dw[g];
1320                                                                         if ((dw != NULL) && (dw->def_nr > def_nr)) {
1321                                                                                 dw->def_nr--;
1322                                                                         }
1323                                                                 }
1324                                                         }
1325                                                 }
1326                                         }
1327                                 }
1328                         }
1329                 }
1330         }
1331
1332         /* Remove the group */
1333         BLI_freelinkN(&ob->defbase, defgroup);
1334         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1335 }
1336
1337
1338 void BKE_gpencil_dvert_ensure(bGPDstroke *gps)
1339 {
1340         if (gps->dvert == NULL) {
1341                 gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
1342         }
1343 }
1344
1345 /* ************************************************** */
1346
1347 /**
1348  * Apply smooth to stroke point
1349  * \param gps: Stroke to smooth
1350  * \param i: Point index
1351  * \param inf: Amount of smoothing to apply
1352  */
1353 bool BKE_gpencil_smooth_stroke(bGPDstroke *gps, int i, float inf)
1354 {
1355         bGPDspoint *pt = &gps->points[i];
1356         // float pressure = 0.0f;
1357         float sco[3] = { 0.0f };
1358
1359         /* Do nothing if not enough points to smooth out */
1360         if (gps->totpoints <= 2) {
1361                 return false;
1362         }
1363
1364         /* Only affect endpoints by a fraction of the normal strength,
1365          * to prevent the stroke from shrinking too much
1366          */
1367         if ((i == 0) || (i == gps->totpoints - 1)) {
1368                 inf *= 0.1f;
1369         }
1370
1371         /* Compute smoothed coordinate by taking the ones nearby */
1372         /* XXX: This is potentially slow, and suffers from accumulation error as earlier points are handled before later ones */
1373         {
1374                 // XXX: this is hardcoded to look at 2 points on either side of the current one (i.e. 5 items total)
1375                 const int   steps = 2;
1376                 const float average_fac = 1.0f / (float)(steps * 2 + 1);
1377                 int step;
1378
1379                 /* add the point itself */
1380                 madd_v3_v3fl(sco, &pt->x, average_fac);
1381
1382                 /* n-steps before/after current point */
1383                 // XXX: review how the endpoints are treated by this algorithm
1384                 // XXX: falloff measures should also introduce some weighting variations, so that further-out points get less weight
1385                 for (step = 1; step <= steps; step++) {
1386                         bGPDspoint *pt1, *pt2;
1387                         int before = i - step;
1388                         int after = i + step;
1389
1390                         CLAMP_MIN(before, 0);
1391                         CLAMP_MAX(after, gps->totpoints - 1);
1392
1393                         pt1 = &gps->points[before];
1394                         pt2 = &gps->points[after];
1395
1396                         /* add both these points to the average-sum (s += p[i]/n) */
1397                         madd_v3_v3fl(sco, &pt1->x, average_fac);
1398                         madd_v3_v3fl(sco, &pt2->x, average_fac);
1399
1400                 }
1401         }
1402
1403         /* Based on influence factor, blend between original and optimal smoothed coordinate */
1404         interp_v3_v3v3(&pt->x, &pt->x, sco, inf);
1405
1406         return true;
1407 }
1408
1409 /**
1410  * Apply smooth for strength to stroke point */
1411 bool BKE_gpencil_smooth_stroke_strength(bGPDstroke *gps, int point_index, float influence)
1412 {
1413         bGPDspoint *ptb = &gps->points[point_index];
1414
1415         /* Do nothing if not enough points */
1416         if (gps->totpoints <= 2) {
1417                 return false;
1418         }
1419
1420         /* Compute theoretical optimal value using distances */
1421         bGPDspoint *pta, *ptc;
1422         int before = point_index - 1;
1423         int after = point_index + 1;
1424
1425         CLAMP_MIN(before, 0);
1426         CLAMP_MAX(after, gps->totpoints - 1);
1427
1428         pta = &gps->points[before];
1429         ptc = &gps->points[after];
1430
1431         /* the optimal value is the corresponding to the interpolation of the strength
1432          * at the distance of point b
1433          */
1434         float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
1435         /* sometimes the factor can be wrong due stroke geometry, so use middle point */
1436         if ((fac < 0.0f) || (fac > 1.0f)) {
1437                 fac = 0.5f;
1438         }
1439         const float optimal = (1.0f - fac) * pta->strength + fac * ptc->strength;
1440
1441         /* Based on influence factor, blend between original and optimal */
1442         ptb->strength = (1.0f - influence) * ptb->strength + influence * optimal;
1443
1444         return true;
1445 }
1446
1447 /**
1448  * Apply smooth for thickness to stroke point (use pressure) */
1449 bool BKE_gpencil_smooth_stroke_thickness(bGPDstroke *gps, int point_index, float influence)
1450 {
1451         bGPDspoint *ptb = &gps->points[point_index];
1452
1453         /* Do nothing if not enough points */
1454         if ((gps->totpoints <= 2) || (point_index < 1)) {
1455                 return false;
1456         }
1457
1458         /* Compute theoretical optimal value using distances */
1459         bGPDspoint *pta, *ptc;
1460         int before = point_index - 1;
1461         int after = point_index + 1;
1462
1463         CLAMP_MIN(before, 0);
1464         CLAMP_MAX(after, gps->totpoints - 1);
1465
1466         pta = &gps->points[before];
1467         ptc = &gps->points[after];
1468
1469         /* the optimal value is the corresponding to the interpolation of the pressure
1470          * at the distance of point b
1471          */
1472         float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
1473         /* sometimes the factor can be wrong due stroke geometry, so use middle point */
1474         if ((fac < 0.0f) || (fac > 1.0f)) {
1475                 fac = 0.5f;
1476         }
1477         float optimal = interpf(ptc->pressure, pta->pressure, fac);
1478
1479         /* Based on influence factor, blend between original and optimal */
1480         ptb->pressure = interpf(optimal, ptb->pressure, influence);
1481
1482         return true;
1483 }
1484
1485 /**
1486  * Apply smooth for UV rotation to stroke point (use pressure).
1487  */
1488 bool BKE_gpencil_smooth_stroke_uv(bGPDstroke *gps, int point_index, float influence)
1489 {
1490         bGPDspoint *ptb = &gps->points[point_index];
1491
1492         /* Do nothing if not enough points */
1493         if (gps->totpoints <= 2) {
1494                 return false;
1495         }
1496
1497         /* Compute theoretical optimal value */
1498         bGPDspoint *pta, *ptc;
1499         int before = point_index - 1;
1500         int after = point_index + 1;
1501
1502         CLAMP_MIN(before, 0);
1503         CLAMP_MAX(after, gps->totpoints - 1);
1504
1505         pta = &gps->points[before];
1506         ptc = &gps->points[after];
1507
1508         /* the optimal value is the corresponding to the interpolation of the pressure
1509          * at the distance of point b
1510          */
1511         float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
1512         /* sometimes the factor can be wrong due stroke geometry, so use middle point */
1513         if ((fac < 0.0f) || (fac > 1.0f)) {
1514                 fac = 0.5f;
1515         }
1516         float optimal = interpf(ptc->uv_rot, pta->uv_rot, fac);
1517
1518         /* Based on influence factor, blend between original and optimal */
1519         ptb->uv_rot = interpf(optimal, ptb->uv_rot, influence);
1520         CLAMP(ptb->uv_rot, -M_PI_2, M_PI_2);
1521
1522         return true;
1523 }
1524
1525 /**
1526  * Get range of selected frames in layer.
1527  * Always the active frame is considered as selected, so if no more selected the range
1528  * will be equal to the current active frame.
1529  * \param gpl: Layer
1530  * \param r_initframe: Number of first selected frame
1531  * \param r_endframe: Number of last selected frame
1532  */
1533 void BKE_gpencil_get_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_endframe)
1534 {
1535         *r_initframe = gpl->actframe->framenum;
1536         *r_endframe = gpl->actframe->framenum;
1537
1538         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1539                 if (gpf->flag & GP_FRAME_SELECT) {
1540                         if (gpf->framenum < *r_initframe) {
1541                                 *r_initframe = gpf->framenum;
1542                         }
1543                         if (gpf->framenum > *r_endframe) {
1544                                 *r_endframe = gpf->framenum;
1545                         }
1546                 }
1547         }
1548 }
1549
1550 /**
1551  * Get Falloff factor base on frame range
1552  * \param gpf: Frame
1553  * \param actnum: Number of active frame in layer
1554  * \param f_init: Number of first selected frame
1555  * \param f_end: Number of last selected frame
1556  * \param cur_falloff: Curve with falloff factors
1557  */
1558 float BKE_gpencil_multiframe_falloff_calc(bGPDframe *gpf, int actnum, int f_init, int f_end, CurveMapping *cur_falloff)
1559 {
1560         float fnum = 0.5f; /* default mid curve */
1561         float value;
1562
1563         /* check curve is available */
1564         if (cur_falloff == NULL) {
1565                 return 1.0f;
1566         }
1567
1568         /* frames to the right of the active frame */
1569         if (gpf->framenum < actnum) {
1570                 fnum = (float)(gpf->framenum - f_init) / (actnum - f_init);
1571                 fnum *= 0.5f;
1572                 value = curvemapping_evaluateF(cur_falloff, 0, fnum);
1573         }
1574         /* frames to the left of the active frame */
1575         else if (gpf->framenum > actnum) {
1576                 fnum = (float)(gpf->framenum - actnum) / (f_end - actnum);
1577                 fnum *= 0.5f;
1578                 value = curvemapping_evaluateF(cur_falloff, 0, fnum + 0.5f);
1579         }
1580         else {
1581                 value = 1.0f;
1582         }
1583
1584         return value;
1585 }
1586
1587 /* remove strokes using a material */
1588 void BKE_gpencil_material_index_remove(bGPdata *gpd, int index)
1589 {
1590         bGPDstroke *gps, *gpsn;
1591
1592                 for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1593                         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1594                                 for (gps = gpf->strokes.first; gps; gps = gpsn) {
1595                                         gpsn = gps->next;
1596                                         if (gps->mat_nr == index) {
1597                                                 if (gps->points) {
1598                                                         MEM_freeN(gps->points);
1599                                                 }
1600                                                 if (gps->dvert) {
1601                                                         BKE_gpencil_free_stroke_weights(gps);
1602                                                         MEM_freeN(gps->dvert);
1603                                                 }
1604                                                 if (gps->triangles) MEM_freeN(gps->triangles);
1605                                                 BLI_freelinkN(&gpf->strokes, gps);
1606                                         }
1607                                         else {
1608                                                 /* reassign strokes */
1609                                                 if (gps->mat_nr > index) {
1610                                                         gps->mat_nr--;
1611                                                 }
1612                                         }
1613                                 }
1614                         }
1615                 }
1616 }
1617
1618 void BKE_gpencil_material_remap(struct bGPdata *gpd, const unsigned int *remap, unsigned int remap_len)
1619 {
1620         const short remap_len_short = (short)remap_len;
1621
1622 #define MAT_NR_REMAP(n) \
1623         if (n < remap_len_short) { \
1624                 BLI_assert(n >= 0 && remap[n] < remap_len_short); \
1625                 n = remap[n]; \
1626         } ((void)0)
1627
1628         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1629                 for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1630                         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1631                                 /* reassign strokes */
1632                                 MAT_NR_REMAP(gps->mat_nr);
1633                         }
1634                 }
1635         }
1636
1637 #undef MAT_NR_REMAP
1638
1639 }
1640
1641 /* statistics functions */
1642 void BKE_gpencil_stats_update(bGPdata *gpd)
1643 {
1644         gpd->totlayer = 0;
1645         gpd->totframe = 0;
1646         gpd->totstroke = 0;
1647         gpd->totpoint = 0;
1648
1649         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1650                 gpd->totlayer++;
1651                 for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1652                         gpd->totframe++;
1653                         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1654                                 gpd->totstroke++;
1655                                 gpd->totpoint += gps->totpoints;
1656                         }
1657                 }
1658         }
1659
1660 }
1661
1662 /* get material index (0-based like mat_nr not actcol) */
1663 int BKE_gpencil_get_material_index(Object *ob, Material *ma)
1664 {
1665         short *totcol = give_totcolp(ob);
1666         Material *read_ma = NULL;
1667         for (short i = 0; i < *totcol; i++) {
1668                 read_ma = give_current_material(ob, i + 1);
1669                 if (ma == read_ma) {
1670                         return i;
1671                 }
1672         }
1673
1674         return -1;
1675 }
1676
1677 /* Get points of stroke always flat to view not affected by camera view or view position */
1678 void BKE_gpencil_stroke_2d_flat(const bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction)
1679 {
1680         BLI_assert(totpoints >= 2);
1681
1682         const bGPDspoint *pt0 = &points[0];
1683         const bGPDspoint *pt1 = &points[1];
1684         const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
1685
1686         float locx[3];
1687         float locy[3];
1688         float loc3[3];
1689         float normal[3];
1690
1691         /* local X axis (p0 -> p1) */
1692         sub_v3_v3v3(locx, &pt1->x, &pt0->x);
1693
1694         /* point vector at 3/4 */
1695         float v3[3];
1696         if (totpoints == 2) {
1697                 mul_v3_v3fl(v3, &pt3->x, 0.001f);
1698         }
1699         else {
1700                 copy_v3_v3(v3, &pt3->x);
1701         }
1702
1703         sub_v3_v3v3(loc3, v3, &pt0->x);
1704
1705         /* vector orthogonal to polygon plane */
1706         cross_v3_v3v3(normal, locx, loc3);
1707
1708         /* local Y axis (cross to normal/x axis) */
1709         cross_v3_v3v3(locy, normal, locx);
1710
1711         /* Normalize vectors */
1712         normalize_v3(locx);
1713         normalize_v3(locy);
1714
1715         /* Get all points in local space */
1716         for (int i = 0; i < totpoints; i++) {
1717                 const bGPDspoint *pt = &points[i];
1718                 float loc[3];
1719
1720                 /* Get local space using first point as origin */
1721                 sub_v3_v3v3(loc, &pt->x, &pt0->x);
1722
1723                 points2d[i][0] = dot_v3v3(loc, locx);
1724                 points2d[i][1] = dot_v3v3(loc, locy);
1725         }
1726
1727         /* Concave (-1), Convex (1), or Autodetect (0)? */
1728         *r_direction = (int)locy[2];
1729 }
1730
1731 /* Get points of stroke always flat to view not affected by camera view or view position
1732  * using another stroke as reference
1733  */
1734 void BKE_gpencil_stroke_2d_flat_ref(
1735         const bGPDspoint *ref_points, int ref_totpoints,
1736         const bGPDspoint *points, int totpoints,
1737         float(*points2d)[2], const float scale, int *r_direction)
1738 {
1739         BLI_assert(totpoints >= 2);
1740
1741         const bGPDspoint *pt0 = &ref_points[0];
1742         const bGPDspoint *pt1 = &ref_points[1];
1743         const bGPDspoint *pt3 = &ref_points[(int)(ref_totpoints * 0.75)];
1744
1745         float locx[3];
1746         float locy[3];
1747         float loc3[3];
1748         float normal[3];
1749
1750         /* local X axis (p0 -> p1) */
1751         sub_v3_v3v3(locx, &pt1->x, &pt0->x);
1752
1753         /* point vector at 3/4 */
1754         float v3[3];
1755         if (totpoints == 2) {
1756                 mul_v3_v3fl(v3, &pt3->x, 0.001f);
1757         }
1758         else {
1759                 copy_v3_v3(v3, &pt3->x);
1760         }
1761
1762         sub_v3_v3v3(loc3, v3, &pt0->x);
1763
1764         /* vector orthogonal to polygon plane */
1765         cross_v3_v3v3(normal, locx, loc3);
1766
1767         /* local Y axis (cross to normal/x axis) */
1768         cross_v3_v3v3(locy, normal, locx);
1769
1770         /* Normalize vectors */
1771         normalize_v3(locx);
1772         normalize_v3(locy);
1773
1774         /* Get all points in local space */
1775         for (int i = 0; i < totpoints; i++) {
1776                 const bGPDspoint *pt = &points[i];
1777                 float loc[3];
1778                 float v1[3];
1779                 float vn[3] = { 0.0f, 0.0f, 0.0f };
1780
1781                 /* apply scale to extremes of the stroke to get better collision detection
1782                  * the scale is divided to get more control in the UI parameter
1783                  */
1784                 /* first point */
1785                 if (i == 0) {
1786                         const bGPDspoint *pt_next = &points[i + 1];
1787                         sub_v3_v3v3(vn, &pt->x, &pt_next->x);
1788                         normalize_v3(vn);
1789                         mul_v3_fl(vn, scale / 10.0f);
1790                         add_v3_v3v3(v1, &pt->x, vn);
1791                 }
1792                 /* last point */
1793                 else if (i == totpoints - 1) {
1794                         const bGPDspoint *pt_prev = &points[i - 1];
1795                         sub_v3_v3v3(vn, &pt->x, &pt_prev->x);
1796                         normalize_v3(vn);
1797                         mul_v3_fl(vn, scale / 10.0f);
1798                         add_v3_v3v3(v1, &pt->x, vn);
1799                 }
1800                 else {
1801                         copy_v3_v3(v1, &pt->x);
1802                 }
1803
1804                 /* Get local space using first point as origin (ref stroke) */
1805                 sub_v3_v3v3(loc, v1, &pt0->x);
1806
1807                 points2d[i][0] = dot_v3v3(loc, locx);
1808                 points2d[i][1] = dot_v3v3(loc, locy);
1809         }
1810
1811         /* Concave (-1), Convex (1), or Autodetect (0)? */
1812         *r_direction = (int)locy[2];
1813 }
1814
1815 /**
1816  * Trim stroke to the first intersection or loop
1817  * \param gps: Stroke data
1818  */
1819 bool BKE_gpencil_trim_stroke(bGPDstroke *gps)
1820 {
1821         if (gps->totpoints < 4) {
1822                 return false;
1823         }
1824         bool intersect = false;
1825         int start, end;
1826         float point[3];
1827         /* loop segments from start until we have an intersection */
1828         for (int i = 0; i < gps->totpoints - 2; i++) {
1829                 start = i;
1830                 bGPDspoint *a = &gps->points[start];
1831                 bGPDspoint *b = &gps->points[start + 1];
1832                 for (int j = start + 2; j < gps->totpoints - 1; j++) {
1833                         end = j + 1;
1834                         bGPDspoint *c = &gps->points[j];
1835                         bGPDspoint *d = &gps->points[end];
1836                         float pointb[3];
1837                         /* get intersection */
1838                         if (isect_line_line_v3(&a->x, &b->x, &c->x, &d->x, point, pointb)) {
1839                                 if (len_v3(point) > 0.0f) {
1840                                         float closest[3];
1841                                         /* check intersection is on both lines */
1842                                         float lambda = closest_to_line_v3(closest, point, &a->x, &b->x);
1843                                         if ((lambda <= 0.0f) || (lambda >= 1.0f)) {
1844                                                 continue;
1845                                         }
1846                                         lambda = closest_to_line_v3(closest, point, &c->x, &d->x);
1847                                         if ((lambda <= 0.0f) || (lambda >= 1.0f)) {
1848                                                 continue;
1849                                         }
1850                                         else {
1851                                                 intersect = true;
1852                                                 break;
1853                                         }
1854                                 }
1855                         }
1856                 }
1857                 if (intersect) {
1858                         break;
1859                 }
1860         }
1861
1862         /* trim unwanted points */
1863         if (intersect) {
1864
1865                 /* save points */
1866                 bGPDspoint *old_points = MEM_dupallocN(gps->points);
1867                 MDeformVert *old_dvert = NULL;
1868                 MDeformVert *dvert_src = NULL;
1869
1870                 if (gps->dvert != NULL) {
1871                         old_dvert = MEM_dupallocN(gps->dvert);
1872                 }
1873
1874                 /* resize gps */
1875                 int newtot = end - start + 1;
1876
1877                 gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * newtot);
1878                 if (gps->dvert != NULL) {
1879                         gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot);
1880                 }
1881
1882                 for (int i = 0; i < newtot; i++) {
1883                         int idx = start + i;
1884                         bGPDspoint *pt_src = &old_points[idx];
1885                         bGPDspoint *pt_new = &gps->points[i];
1886                         memcpy(pt_new, pt_src, sizeof(bGPDspoint));
1887                         if (gps->dvert != NULL) {
1888                                 dvert_src = &old_dvert[idx];
1889                                 MDeformVert *dvert = &gps->dvert[i];
1890                                 memcpy(dvert, dvert_src, sizeof(MDeformVert));
1891                                 if (dvert_src->dw) {
1892                                         memcpy(dvert->dw, dvert_src->dw, sizeof(MDeformWeight));
1893                                 }
1894                         }
1895                         if (idx == start || idx == end) {
1896                                 copy_v3_v3(&pt_new->x, point);
1897                         }
1898                 }
1899
1900                 gps->flag |= GP_STROKE_RECALC_GEOMETRY;
1901                 gps->tot_triangles = 0;
1902                 gps->totpoints = newtot;
1903
1904                 MEM_SAFE_FREE(old_points);
1905                 MEM_SAFE_FREE(old_dvert);
1906         }
1907         return intersect;
1908 }