GPencil: Implement custom channel color in Dopesheet
[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                 /* default channel color */
378                 ARRAY_SET_ITEMS(gpl->color, 0.2f, 0.2f, 0.2f);
379         }
380
381         /* auto-name */
382         BLI_strncpy(gpl->info, name, sizeof(gpl->info));
383         BLI_uniquename(&gpd->layers, gpl,
384                        (gpd->flag & GP_DATA_ANNOTATIONS) ? DATA_("Note") : DATA_("GP_Layer"),
385                        '.',
386                        offsetof(bGPDlayer, info),
387                        sizeof(gpl->info));
388
389         /* make this one the active one */
390         if (setactive)
391                 BKE_gpencil_layer_setactive(gpd, gpl);
392
393         /* return layer */
394         return gpl;
395 }
396
397 /* add a new gp-datablock */
398 bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
399 {
400         bGPdata *gpd;
401
402         /* allocate memory for a new block */
403         gpd = BKE_libblock_alloc(bmain, ID_GD, name, 0);
404
405         /* initial settings */
406         gpd->flag = (GP_DATA_DISPINFO | GP_DATA_EXPAND);
407
408         /* general flags */
409         gpd->flag |= GP_DATA_VIEWALIGN;
410         gpd->flag |= GP_DATA_STROKE_FORCE_RECALC;
411         /* always enable object onion skin swith */
412         gpd->flag |= GP_DATA_SHOW_ONIONSKINS;
413         /* GP object specific settings */
414         ARRAY_SET_ITEMS(gpd->line_color, 0.6f, 0.6f, 0.6f, 0.5f);
415
416         gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
417
418         /* grid settings */
419         ARRAY_SET_ITEMS(gpd->grid.color, 0.5f, 0.5f, 0.5f); // Color
420         ARRAY_SET_ITEMS(gpd->grid.scale, 1.0f, 1.0f); // Scale
421         gpd->grid.lines = GP_DEFAULT_GRID_LINES; // Number of lines
422
423         /* onion-skinning settings (datablock level) */
424         gpd->onion_flag |= (GP_ONION_GHOST_PREVCOL | GP_ONION_GHOST_NEXTCOL);
425         gpd->onion_flag |= GP_ONION_FADE;
426         gpd->onion_mode = GP_ONION_MODE_RELATIVE;
427         gpd->onion_factor = 0.5f;
428         ARRAY_SET_ITEMS(gpd->gcolor_prev, 0.145098f, 0.419608f, 0.137255f); /* green */
429         ARRAY_SET_ITEMS(gpd->gcolor_next, 0.125490f, 0.082353f, 0.529412f); /* blue */
430         gpd->gstep = 1;
431         gpd->gstep_next = 1;
432
433         return gpd;
434 }
435
436
437 /* ************************************************** */
438 /* Primitive Creation */
439 /* Utilities for easier bulk-creation of geometry */
440
441 /**
442  * Populate stroke with point data from data buffers
443  *
444  * \param array: Flat array of point data values. Each entry has GP_PRIM_DATABUF_SIZE values
445  * \param mat: 4x4 transform matrix to transform points into the right coordinate space
446  */
447 void BKE_gpencil_stroke_add_points(bGPDstroke *gps, const float *array, const int totpoints, const float mat[4][4])
448 {
449         for (int i = 0; i < totpoints; i++) {
450                 bGPDspoint *pt = &gps->points[i];
451                 const int x = GP_PRIM_DATABUF_SIZE * i;
452
453                 pt->x = array[x];
454                 pt->y = array[x + 1];
455                 pt->z = array[x + 2];
456                 mul_m4_v3(mat, &pt->x);
457
458                 pt->pressure = array[x + 3];
459                 pt->strength = array[x + 4];
460         }
461 }
462
463 /* Create a new stroke, with pre-allocated data buffers */
464 bGPDstroke *BKE_gpencil_add_stroke(bGPDframe *gpf, int mat_idx, int totpoints, short thickness)
465 {
466         /* allocate memory for a new stroke */
467         bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
468
469         gps->thickness = thickness;
470         gps->inittime = 0;
471
472         /* enable recalculation flag by default */
473         gps->flag = GP_STROKE_RECALC_GEOMETRY | GP_STROKE_3DSPACE;
474
475         gps->totpoints = totpoints;
476         gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
477
478         /* initialize triangle memory to dummy data */
479         gps->triangles = MEM_callocN(sizeof(bGPDtriangle), "GP Stroke triangulation");
480         gps->flag |= GP_STROKE_RECALC_GEOMETRY;
481         gps->tot_triangles = 0;
482
483         gps->mat_nr = mat_idx;
484
485         /* add to frame */
486         BLI_addtail(&gpf->strokes, gps);
487
488         return gps;
489 }
490
491
492 /* ************************************************** */
493 /* Data Duplication */
494
495 /* make a copy of a given gpencil weights */
496 void BKE_gpencil_stroke_weights_duplicate(bGPDstroke *gps_src, bGPDstroke *gps_dst)
497 {
498         if (gps_src == NULL) {
499                 return;
500         }
501         BLI_assert(gps_src->totpoints == gps_dst->totpoints);
502
503         BKE_defvert_array_copy(gps_dst->dvert, gps_src->dvert, gps_src->totpoints);
504 }
505
506 /* make a copy of a given gpencil stroke */
507 bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src)
508 {
509         bGPDstroke *gps_dst = NULL;
510
511         gps_dst = MEM_dupallocN(gps_src);
512         gps_dst->prev = gps_dst->next = NULL;
513
514         gps_dst->points = MEM_dupallocN(gps_src->points);
515
516         if (gps_src->dvert != NULL) {
517                 gps_dst->dvert = MEM_dupallocN(gps_src->dvert);
518                 BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst);
519         }
520         else {
521                 gps_dst->dvert = NULL;
522         }
523
524         /* Don't clear triangles, so that modifier evaluation can just use
525          * this without extra work first. Most places that need to force
526          * this data to get recalculated will destroy the data anyway though.
527          */
528         gps_dst->triangles = MEM_dupallocN(gps_dst->triangles);
529         /* gps_dst->flag |= GP_STROKE_RECALC_GEOMETRY; */
530
531         /* return new stroke */
532         return gps_dst;
533 }
534
535 /* make a copy of a given gpencil frame */
536 bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src)
537 {
538         bGPDstroke *gps_dst = NULL;
539         bGPDframe *gpf_dst;
540
541         /* error checking */
542         if (gpf_src == NULL) {
543                 return NULL;
544         }
545
546         /* make a copy of the source frame */
547         gpf_dst = MEM_dupallocN(gpf_src);
548         gpf_dst->prev = gpf_dst->next = NULL;
549
550         /* copy strokes */
551         BLI_listbase_clear(&gpf_dst->strokes);
552         for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
553                 /* make copy of source stroke */
554                 gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
555                 BLI_addtail(&gpf_dst->strokes, gps_dst);
556         }
557
558         /* return new frame */
559         return gpf_dst;
560 }
561
562 /* make a copy of strokes between gpencil frames */
563 void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, struct bGPDframe *gpf_dst)
564 {
565         bGPDstroke *gps_dst = NULL;
566         /* error checking */
567         if ((gpf_src == NULL) || (gpf_dst == NULL)) {
568                 return;
569         }
570
571         /* copy strokes */
572         BLI_listbase_clear(&gpf_dst->strokes);
573         for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
574                 /* make copy of source stroke */
575                 gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
576                 BLI_addtail(&gpf_dst->strokes, gps_dst);
577         }
578 }
579
580 /* make a copy of a given gpencil layer */
581 bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src)
582 {
583         const bGPDframe *gpf_src;
584         bGPDframe *gpf_dst;
585         bGPDlayer *gpl_dst;
586
587         /* error checking */
588         if (gpl_src == NULL) {
589                 return NULL;
590         }
591
592         /* make a copy of source layer */
593         gpl_dst = MEM_dupallocN(gpl_src);
594         gpl_dst->prev = gpl_dst->next = NULL;
595
596         /* copy frames */
597         BLI_listbase_clear(&gpl_dst->frames);
598         for (gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) {
599                 /* make a copy of source frame */
600                 gpf_dst = BKE_gpencil_frame_duplicate(gpf_src);
601                 BLI_addtail(&gpl_dst->frames, gpf_dst);
602
603                 /* if source frame was the current layer's 'active' frame, reassign that too */
604                 if (gpf_src == gpl_dst->actframe)
605                         gpl_dst->actframe = gpf_dst;
606         }
607
608         /* return new layer */
609         return gpl_dst;
610 }
611
612 /**
613  * Only copy internal data of GreasePencil ID from source to already allocated/initialized destination.
614  * You probably never want to use that directly, use BKE_id_copy or BKE_id_copy_ex for typical needs.
615  *
616  * WARNING! This function will not handle ID user count!
617  *
618  * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
619  */
620 void BKE_gpencil_copy_data(bGPdata *gpd_dst, const bGPdata *gpd_src, const int UNUSED(flag))
621 {
622         /* duplicate material array */
623         if (gpd_src->mat) {
624                 gpd_dst->mat = MEM_dupallocN(gpd_src->mat);
625         }
626
627         /* copy layers */
628         BLI_listbase_clear(&gpd_dst->layers);
629         for (const bGPDlayer *gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) {
630                 /* make a copy of source layer and its data */
631                 bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src);  /* TODO here too could add unused flags... */
632                 BLI_addtail(&gpd_dst->layers, gpl_dst);
633         }
634
635 }
636
637 /* Standard API to make a copy of GP datablock, separate from copying its data */
638 bGPdata *BKE_gpencil_copy(Main *bmain, const bGPdata *gpd)
639 {
640         bGPdata *gpd_copy;
641         BKE_id_copy(bmain, &gpd->id, (ID **)&gpd_copy);
642         return gpd_copy;
643 }
644
645 /* make a copy of a given gpencil datablock */
646 // XXX: Should this be deprecated?
647 bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy)
648 {
649         bGPdata *gpd_dst;
650
651         /* Yuck and super-uber-hyper yuck!!!
652          * Should be replaceable with a no-main copy (LIB_ID_COPY_NO_MAIN etc.), but not sure about it,
653          * so for now keep old code for that one. */
654
655         /* error checking */
656         if (gpd_src == NULL) {
657                 return NULL;
658         }
659
660         if (internal_copy) {
661                 /* make a straight copy for undo buffers used during stroke drawing */
662                 gpd_dst = MEM_dupallocN(gpd_src);
663         }
664         else {
665                 BLI_assert(bmain != NULL);
666                 BKE_id_copy(bmain, &gpd_src->id, (ID **)&gpd_dst);
667         }
668
669         /* Copy internal data (layers, etc.) */
670         BKE_gpencil_copy_data(gpd_dst, gpd_src, 0);
671
672         /* return new */
673         return gpd_dst;
674 }
675
676 void BKE_gpencil_make_local(Main *bmain, bGPdata *gpd, const bool lib_local)
677 {
678         BKE_id_make_local_generic(bmain, &gpd->id, true, lib_local);
679 }
680
681 /* ************************************************** */
682 /* GP Stroke API */
683
684 /* ensure selection status of stroke is in sync with its points */
685 void BKE_gpencil_stroke_sync_selection(bGPDstroke *gps)
686 {
687         bGPDspoint *pt;
688         int i;
689
690         /* error checking */
691         if (gps == NULL)
692                 return;
693
694         /* we'll stop when we find the first selected point,
695          * so initially, we must deselect
696          */
697         gps->flag &= ~GP_STROKE_SELECT;
698
699         for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
700                 if (pt->flag & GP_SPOINT_SELECT) {
701                         gps->flag |= GP_STROKE_SELECT;
702                         break;
703                 }
704         }
705 }
706
707 /* ************************************************** */
708 /* GP Frame API */
709
710 /* delete the last stroke of the given frame */
711 void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
712 {
713         bGPDstroke *gps = (gpf) ? gpf->strokes.last : NULL;
714         int cfra = (gpf) ? gpf->framenum : 0; /* assume that the current frame was not locked */
715
716         /* error checking */
717         if (ELEM(NULL, gpf, gps))
718                 return;
719
720         /* free the stroke and its data */
721         if (gps->points) {
722                 MEM_freeN(gps->points);
723         }
724         if (gps->dvert) {
725                 BKE_gpencil_free_stroke_weights(gps);
726                 MEM_freeN(gps->dvert);
727         }
728         MEM_freeN(gps->triangles);
729         BLI_freelinkN(&gpf->strokes, gps);
730
731         /* if frame has no strokes after this, delete it */
732         if (BLI_listbase_is_empty(&gpf->strokes)) {
733                 BKE_gpencil_layer_delframe(gpl, gpf);
734                 BKE_gpencil_layer_getframe(gpl, cfra, GP_GETFRAME_USE_PREV);
735         }
736 }
737
738 /* ************************************************** */
739 /* GP Layer API */
740
741 /* Check if the given layer is able to be edited or not */
742 bool gpencil_layer_is_editable(const bGPDlayer *gpl)
743 {
744         /* Sanity check */
745         if (gpl == NULL)
746                 return false;
747
748         /* Layer must be: Visible + Editable */
749         if ((gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) == 0) {
750                 /* Opacity must be sufficiently high that it is still "visible"
751                  * Otherwise, it's not really "visible" to the user, so no point editing...
752                  */
753                 if (gpl->opacity > GPENCIL_ALPHA_OPACITY_THRESH) {
754                         return true;
755                 }
756         }
757
758         /* Something failed */
759         return false;
760 }
761
762 /* Look up the gp-frame on the requested frame number, but don't add a new one */
763 bGPDframe *BKE_gpencil_layer_find_frame(bGPDlayer *gpl, int cframe)
764 {
765         bGPDframe *gpf;
766
767         /* Search in reverse order, since this is often used for playback/adding,
768          * where it's less likely that we're interested in the earlier frames
769          */
770         for (gpf = gpl->frames.last; gpf; gpf = gpf->prev) {
771                 if (gpf->framenum == cframe) {
772                         return gpf;
773                 }
774         }
775
776         return NULL;
777 }
778
779 /* get the appropriate gp-frame from a given layer
780  * - this sets the layer's actframe var (if allowed to)
781  * - extension beyond range (if first gp-frame is after all frame in interest and cannot add)
782  */
783 bGPDframe *BKE_gpencil_layer_getframe(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
784 {
785         bGPDframe *gpf = NULL;
786         short found = 0;
787
788         /* error checking */
789         if (gpl == NULL) return NULL;
790
791         /* check if there is already an active frame */
792         if (gpl->actframe) {
793                 gpf = gpl->actframe;
794
795                 /* do not allow any changes to layer's active frame if layer is locked from changes
796                  * or if the layer has been set to stay on the current frame
797                  */
798                 if (gpl->flag & GP_LAYER_FRAMELOCK)
799                         return gpf;
800                 /* do not allow any changes to actframe if frame has painting tag attached to it */
801                 if (gpf->flag & GP_FRAME_PAINT)
802                         return gpf;
803
804                 /* try to find matching frame */
805                 if (gpf->framenum < cframe) {
806                         for (; gpf; gpf = gpf->next) {
807                                 if (gpf->framenum == cframe) {
808                                         found = 1;
809                                         break;
810                                 }
811                                 else if ((gpf->next) && (gpf->next->framenum > cframe)) {
812                                         found = 1;
813                                         break;
814                                 }
815                         }
816
817                         /* set the appropriate frame */
818                         if (addnew) {
819                                 if ((found) && (gpf->framenum == cframe))
820                                         gpl->actframe = gpf;
821                                 else if (addnew == GP_GETFRAME_ADD_COPY)
822                                         gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe);
823                                 else
824                                         gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
825                         }
826                         else if (found)
827                                 gpl->actframe = gpf;
828                         else
829                                 gpl->actframe = gpl->frames.last;
830                 }
831                 else {
832                         for (; gpf; gpf = gpf->prev) {
833                                 if (gpf->framenum <= cframe) {
834                                         found = 1;
835                                         break;
836                                 }
837                         }
838
839                         /* set the appropriate frame */
840                         if (addnew) {
841                                 if ((found) && (gpf->framenum == cframe))
842                                         gpl->actframe = gpf;
843                                 else if (addnew == GP_GETFRAME_ADD_COPY)
844                                         gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe);
845                                 else
846                                         gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
847                         }
848                         else if (found)
849                                 gpl->actframe = gpf;
850                         else
851                                 gpl->actframe = gpl->frames.first;
852                 }
853         }
854         else if (gpl->frames.first) {
855                 /* check which of the ends to start checking from */
856                 const int first = ((bGPDframe *)(gpl->frames.first))->framenum;
857                 const int last = ((bGPDframe *)(gpl->frames.last))->framenum;
858
859                 if (abs(cframe - first) > abs(cframe - last)) {
860                         /* find gp-frame which is less than or equal to cframe */
861                         for (gpf = gpl->frames.last; gpf; gpf = gpf->prev) {
862                                 if (gpf->framenum <= cframe) {
863                                         found = 1;
864                                         break;
865                                 }
866                         }
867                 }
868                 else {
869                         /* find gp-frame which is less than or equal to cframe */
870                         for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
871                                 if (gpf->framenum <= cframe) {
872                                         found = 1;
873                                         break;
874                                 }
875                         }
876                 }
877
878                 /* set the appropriate frame */
879                 if (addnew) {
880                         if ((found) && (gpf->framenum == cframe))
881                                 gpl->actframe = gpf;
882                         else
883                                 gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
884                 }
885                 else if (found)
886                         gpl->actframe = gpf;
887                 else {
888                         /* unresolved errogenous situation! */
889                         CLOG_STR_ERROR(&LOG, "cannot find appropriate gp-frame");
890                         /* gpl->actframe should still be NULL */
891                 }
892         }
893         else {
894                 /* currently no frames (add if allowed to) */
895                 if (addnew)
896                         gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
897                 else {
898                         /* don't do anything... this may be when no frames yet! */
899                         /* gpl->actframe should still be NULL */
900                 }
901         }
902
903         /* return */
904         return gpl->actframe;
905 }
906
907 /* delete the given frame from a layer */
908 bool BKE_gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf)
909 {
910         bool changed = false;
911
912         /* error checking */
913         if (ELEM(NULL, gpl, gpf))
914                 return false;
915
916         /* if this frame was active, make the previous frame active instead
917          * since it's tricky to set active frame otherwise
918          */
919         if (gpl->actframe == gpf)
920                 gpl->actframe = gpf->prev;
921
922         /* free the frame and its data */
923         changed = BKE_gpencil_free_strokes(gpf);
924         BLI_freelinkN(&gpl->frames, gpf);
925
926         return changed;
927 }
928
929 /* get the active gp-layer for editing */
930 bGPDlayer *BKE_gpencil_layer_getactive(bGPdata *gpd)
931 {
932         bGPDlayer *gpl;
933
934         /* error checking */
935         if (ELEM(NULL, gpd, gpd->layers.first))
936                 return NULL;
937
938         /* loop over layers until found (assume only one active) */
939         for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
940                 if (gpl->flag & GP_LAYER_ACTIVE)
941                         return gpl;
942         }
943
944         /* no active layer found */
945         return NULL;
946 }
947
948 /* set the active gp-layer */
949 void BKE_gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active)
950 {
951         bGPDlayer *gpl;
952
953         /* error checking */
954         if (ELEM(NULL, gpd, gpd->layers.first, active))
955                 return;
956
957         /* loop over layers deactivating all */
958         for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
959                 gpl->flag &= ~GP_LAYER_ACTIVE;
960                 if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
961                         gpl->flag |= GP_LAYER_LOCKED;
962                 }
963         }
964
965         /* set as active one */
966         active->flag |= GP_LAYER_ACTIVE;
967         if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
968                 active->flag &= ~GP_LAYER_LOCKED;
969         }
970 }
971
972 /* delete the active gp-layer */
973 void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl)
974 {
975         /* error checking */
976         if (ELEM(NULL, gpd, gpl))
977                 return;
978
979         /* free layer */
980         BKE_gpencil_free_frames(gpl);
981
982         /* free icon providing preview of icon color */
983         BKE_icon_delete(gpl->runtime.icon_id);
984
985         BLI_freelinkN(&gpd->layers, gpl);
986 }
987
988 Material *BKE_gpencil_get_material_from_brush(Brush *brush)
989 {
990         Material *ma = NULL;
991
992         if ((brush != NULL) && (brush->gpencil_settings != NULL) &&
993             (brush->gpencil_settings->material != NULL))
994         {
995                 ma = brush->gpencil_settings->material;
996         }
997
998         return ma;
999 }
1000
1001 void BKE_gpencil_brush_set_material(Brush *brush, Material *ma)
1002 {
1003         BLI_assert(brush);
1004         BLI_assert(brush->gpencil_settings);
1005         if (brush->gpencil_settings->material != ma) {
1006                 if (brush->gpencil_settings->material) {
1007                         id_us_min(&brush->gpencil_settings->material->id);
1008                 }
1009                 if (ma) {
1010                         id_us_plus(&ma->id);
1011                 }
1012                 brush->gpencil_settings->material = ma;
1013         }
1014 }
1015
1016 /* Adds the pinned material to the object if necessary. */
1017 Material *BKE_gpencil_handle_brush_material(Main *bmain, Object *ob, Brush *brush)
1018 {
1019         if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) {
1020                 Material *ma = BKE_gpencil_get_material_from_brush(brush);
1021
1022                 /* check if the material is already on object material slots and add it if missing */
1023                 if (ma && BKE_gpencil_get_material_index(ob, ma) < 0) {
1024                         BKE_object_material_slot_add(bmain, ob);
1025                         assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
1026                 }
1027
1028                 return ma;
1029         }
1030         else {
1031                 /* using active material instead */
1032                 return give_current_material(ob, ob->actcol);
1033         }
1034 }
1035
1036 /* Assigns the material to object (if not already present) and returns its index (mat_nr). */
1037 int BKE_gpencil_handle_material(Main *bmain, Object *ob, Material *material)
1038 {
1039         if (!material) {
1040                 return -1;
1041         }
1042         int index = BKE_gpencil_get_material_index(ob, material);
1043         if (index < 0) {
1044                 BKE_object_material_slot_add(bmain, ob);
1045                 assign_material(bmain, ob, material, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
1046                 return ob->totcol - 1;
1047         }
1048         return index;
1049 }
1050
1051 /** Creates a new gpencil material and assigns it to object.
1052  *
1053  * \param *r_index: value is set to zero based index of the new material if r_index is not NULL
1054  */
1055 Material *BKE_gpencil_handle_new_material(Main *bmain, Object *ob, const char *name, int *r_index)
1056 {
1057         Material *ma = BKE_material_add_gpencil(bmain, name);
1058         id_us_min(&ma->id); /* no users yet */
1059
1060         BKE_object_material_slot_add(bmain, ob);
1061         assign_material(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
1062
1063         if (r_index) {
1064                 *r_index = ob->actcol - 1;
1065         }
1066         return ma;
1067 }
1068
1069 /* Returns the material for a brush with respect to its pinned state. */
1070 Material *BKE_gpencil_get_material_for_brush(Object *ob, Brush *brush)
1071 {
1072         if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) {
1073                 Material *ma = BKE_gpencil_get_material_from_brush(brush);
1074                 return ma;
1075         }
1076         else {
1077                 return give_current_material(ob, ob->actcol);
1078         }
1079 }
1080
1081 /* Returns the material index for a brush with respect to its pinned state. */
1082 int BKE_gpencil_get_material_index_for_brush(Object *ob, Brush *brush)
1083 {
1084         if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) {
1085                 return BKE_gpencil_get_material_index(ob, brush->gpencil_settings->material);
1086         }
1087         else {
1088                 return ob->actcol - 1;
1089         }
1090 }
1091
1092 /* Guaranteed to return a material assigned to object. Returns never NULL. */
1093 Material *BKE_gpencil_current_input_toolsettings_material(Main *bmain, Object *ob, ToolSettings *ts)
1094 {
1095         if (ts && ts->gp_paint && ts->gp_paint->paint.brush) {
1096                 return BKE_gpencil_current_input_brush_material(bmain, ob, ts->gp_paint->paint.brush);
1097         }
1098         else {
1099                 return BKE_gpencil_current_input_brush_material(bmain, ob, NULL);
1100         }
1101 }
1102
1103 /* Guaranteed to return a material assigned to object. Returns never NULL. */
1104 Material *BKE_gpencil_current_input_brush_material(Main *bmain, Object *ob, Brush *brush)
1105 {
1106         if (brush) {
1107                 Material *ma = BKE_gpencil_handle_brush_material(bmain, ob, brush);
1108                 if (ma) {
1109                         return ma;
1110                 }
1111                 else if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) {
1112                         /* it is easier to just unpin a NULL material, instead of setting a new one */
1113                         brush->gpencil_settings->flag &= ~GP_BRUSH_MATERIAL_PINNED;
1114                 }
1115         }
1116         return BKE_gpencil_current_input_material(bmain, ob);
1117 }
1118
1119 /* Guaranteed to return a material assigned to object. Returns never NULL. Only use this for materials unrelated to user input */
1120 Material *BKE_gpencil_current_input_material(Main *bmain, Object *ob)
1121 {
1122         Material *ma = give_current_material(ob, ob->actcol);
1123         if (ma) {
1124                 return ma;
1125         }
1126         return BKE_gpencil_handle_new_material(bmain, ob, "Material", NULL);
1127 }
1128
1129 /* Get active color, and add all default settings if we don't find anything */
1130 Material *BKE_gpencil_material_ensure(Main *bmain, Object *ob)
1131 {
1132         Material *ma = NULL;
1133
1134         /* sanity checks */
1135         if (ELEM(NULL, bmain, ob))
1136                 return NULL;
1137
1138         ma = BKE_gpencil_current_input_material(bmain, ob);
1139         if (ma->gp_style == NULL) {
1140                 BKE_material_init_gpencil_settings(ma);
1141         }
1142
1143         return ma;
1144 }
1145
1146 /* ************************************************** */
1147 /* GP Object - Boundbox Support */
1148
1149 /**
1150  * Get min/max coordinate bounds for single stroke
1151  * \return Returns whether we found any selected points
1152  */
1153 bool BKE_gpencil_stroke_minmax(
1154         const bGPDstroke *gps, const bool use_select,
1155         float r_min[3], float r_max[3])
1156 {
1157         const bGPDspoint *pt;
1158         int i;
1159         bool changed = false;
1160
1161         if (ELEM(NULL, gps, r_min, r_max))
1162                 return false;
1163
1164         for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1165                 if ((use_select == false) || (pt->flag & GP_SPOINT_SELECT)) {
1166                         minmax_v3v3_v3(r_min, r_max, &pt->x);
1167                         changed = true;
1168                 }
1169         }
1170         return changed;
1171 }
1172
1173 /* get min/max bounds of all strokes in GP datablock */
1174 bool BKE_gpencil_data_minmax(const bGPdata *gpd, float r_min[3], float r_max[3])
1175 {
1176         bool changed = false;
1177
1178         INIT_MINMAX(r_min, r_max);
1179
1180         if (gpd == NULL)
1181                 return changed;
1182
1183         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1184                 bGPDframe *gpf = gpl->actframe;
1185
1186                 if (gpf != NULL) {
1187                         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1188                                 changed = BKE_gpencil_stroke_minmax(gps, false, r_min, r_max);
1189                         }
1190                 }
1191         }
1192
1193         return changed;
1194 }
1195
1196 bool BKE_gpencil_stroke_select_check(
1197         const bGPDstroke *gps)
1198 {
1199         const bGPDspoint *pt;
1200         int i;
1201         for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1202                 if (pt->flag & GP_SPOINT_SELECT) {
1203                         return true;
1204                 }
1205         }
1206         return false;
1207 }
1208
1209 /* compute center of bounding box */
1210 void BKE_gpencil_centroid_3d(bGPdata *gpd, float r_centroid[3])
1211 {
1212         float min[3], max[3], tot[3];
1213
1214         BKE_gpencil_data_minmax(gpd, min, max);
1215
1216         add_v3_v3v3(tot, min, max);
1217         mul_v3_v3fl(r_centroid, tot, 0.5f);
1218 }
1219
1220
1221 /* create bounding box values */
1222 static void boundbox_gpencil(Object *ob)
1223 {
1224         BoundBox *bb;
1225         bGPdata *gpd;
1226         float min[3], max[3];
1227
1228         if (ob->runtime.bb == NULL) {
1229                 ob->runtime.bb = MEM_callocN(sizeof(BoundBox), "GPencil boundbox");
1230         }
1231
1232         bb  = ob->runtime.bb;
1233         gpd = ob->data;
1234
1235         if (!BKE_gpencil_data_minmax(gpd, min, max)) {
1236                 min[0] = min[1] = min[2] = -1.0f;
1237                 max[0] = max[1] = max[2] = 1.0f;
1238         }
1239
1240         BKE_boundbox_init_from_minmax(bb, min, max);
1241
1242         bb->flag &= ~BOUNDBOX_DIRTY;
1243 }
1244
1245 /* get bounding box */
1246 BoundBox *BKE_gpencil_boundbox_get(Object *ob)
1247 {
1248         if (ELEM(NULL, ob, ob->data))
1249                 return NULL;
1250
1251         bGPdata *gpd = (bGPdata *)ob->data;
1252         if ((ob->runtime.bb) && ((gpd->flag & GP_DATA_CACHE_IS_DIRTY) == 0)) {
1253                 return ob->runtime.bb;
1254         }
1255
1256         boundbox_gpencil(ob);
1257
1258         return ob->runtime.bb;
1259 }
1260
1261 /* ************************************************** */
1262 /* Apply Transforms */
1263
1264 void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4])
1265 {
1266         if (gpd == NULL)
1267                 return;
1268
1269         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1270                 /* FIXME: For now, we just skip parented layers.
1271                  * Otherwise, we have to update each frame to find
1272                  * the current parent position/effects.
1273                  */
1274                 if (gpl->parent) {
1275                         continue;
1276                 }
1277
1278                 for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1279                         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1280                                 bGPDspoint *pt;
1281                                 int i;
1282
1283                                 for (pt = gps->points, i = 0; i < gps->totpoints; pt++, i++) {
1284                                         mul_m4_v3(mat, &pt->x);
1285                                 }
1286
1287                                 /* TODO: Do we need to do this? distortion may mean we need to re-triangulate */
1288                                 gps->flag |= GP_STROKE_RECALC_GEOMETRY;
1289                                 gps->tot_triangles = 0;
1290                         }
1291                 }
1292         }
1293
1294 }
1295
1296 /* ************************************************** */
1297 /* GP Object - Vertex Groups */
1298
1299 /* remove a vertex group */
1300 void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup)
1301 {
1302         bGPdata *gpd = ob->data;
1303         MDeformVert *dvert = NULL;
1304         const int def_nr = BLI_findindex(&ob->defbase, defgroup);
1305
1306         /* Remove points data */
1307         if (gpd) {
1308                 for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1309                         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1310                                 for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1311                                         if (gps->dvert != NULL) {
1312                                                 for (int i = 0; i < gps->totpoints; i++) {
1313                                                         dvert = &gps->dvert[i];
1314                                                         MDeformWeight *dw = defvert_find_index(dvert, def_nr);
1315                                                         if (dw != NULL) {
1316                                                                 defvert_remove_group(dvert, dw);
1317                                                         }
1318                                                         else {
1319                                                                 /* reorganize weights in other strokes */
1320                                                                 for (int g = 0; g < gps->dvert->totweight; g++) {
1321                                                                         dw = &dvert->dw[g];
1322                                                                         if ((dw != NULL) && (dw->def_nr > def_nr)) {
1323                                                                                 dw->def_nr--;
1324                                                                         }
1325                                                                 }
1326                                                         }
1327                                                 }
1328                                         }
1329                                 }
1330                         }
1331                 }
1332         }
1333
1334         /* Remove the group */
1335         BLI_freelinkN(&ob->defbase, defgroup);
1336         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1337 }
1338
1339
1340 void BKE_gpencil_dvert_ensure(bGPDstroke *gps)
1341 {
1342         if (gps->dvert == NULL) {
1343                 gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
1344         }
1345 }
1346
1347 /* ************************************************** */
1348
1349 /**
1350  * Apply smooth to stroke point
1351  * \param gps: Stroke to smooth
1352  * \param i: Point index
1353  * \param inf: Amount of smoothing to apply
1354  */
1355 bool BKE_gpencil_smooth_stroke(bGPDstroke *gps, int i, float inf)
1356 {
1357         bGPDspoint *pt = &gps->points[i];
1358         // float pressure = 0.0f;
1359         float sco[3] = { 0.0f };
1360
1361         /* Do nothing if not enough points to smooth out */
1362         if (gps->totpoints <= 2) {
1363                 return false;
1364         }
1365
1366         /* Only affect endpoints by a fraction of the normal strength,
1367          * to prevent the stroke from shrinking too much
1368          */
1369         if ((i == 0) || (i == gps->totpoints - 1)) {
1370                 inf *= 0.1f;
1371         }
1372
1373         /* Compute smoothed coordinate by taking the ones nearby */
1374         /* XXX: This is potentially slow, and suffers from accumulation error as earlier points are handled before later ones */
1375         {
1376                 // XXX: this is hardcoded to look at 2 points on either side of the current one (i.e. 5 items total)
1377                 const int   steps = 2;
1378                 const float average_fac = 1.0f / (float)(steps * 2 + 1);
1379                 int step;
1380
1381                 /* add the point itself */
1382                 madd_v3_v3fl(sco, &pt->x, average_fac);
1383
1384                 /* n-steps before/after current point */
1385                 // XXX: review how the endpoints are treated by this algorithm
1386                 // XXX: falloff measures should also introduce some weighting variations, so that further-out points get less weight
1387                 for (step = 1; step <= steps; step++) {
1388                         bGPDspoint *pt1, *pt2;
1389                         int before = i - step;
1390                         int after = i + step;
1391
1392                         CLAMP_MIN(before, 0);
1393                         CLAMP_MAX(after, gps->totpoints - 1);
1394
1395                         pt1 = &gps->points[before];
1396                         pt2 = &gps->points[after];
1397
1398                         /* add both these points to the average-sum (s += p[i]/n) */
1399                         madd_v3_v3fl(sco, &pt1->x, average_fac);
1400                         madd_v3_v3fl(sco, &pt2->x, average_fac);
1401
1402                 }
1403         }
1404
1405         /* Based on influence factor, blend between original and optimal smoothed coordinate */
1406         interp_v3_v3v3(&pt->x, &pt->x, sco, inf);
1407
1408         return true;
1409 }
1410
1411 /**
1412  * Apply smooth for strength to stroke point */
1413 bool BKE_gpencil_smooth_stroke_strength(bGPDstroke *gps, int point_index, float influence)
1414 {
1415         bGPDspoint *ptb = &gps->points[point_index];
1416
1417         /* Do nothing if not enough points */
1418         if (gps->totpoints <= 2) {
1419                 return false;
1420         }
1421
1422         /* Compute theoretical optimal value using distances */
1423         bGPDspoint *pta, *ptc;
1424         int before = point_index - 1;
1425         int after = point_index + 1;
1426
1427         CLAMP_MIN(before, 0);
1428         CLAMP_MAX(after, gps->totpoints - 1);
1429
1430         pta = &gps->points[before];
1431         ptc = &gps->points[after];
1432
1433         /* the optimal value is the corresponding to the interpolation of the strength
1434          * at the distance of point b
1435          */
1436         float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
1437         /* sometimes the factor can be wrong due stroke geometry, so use middle point */
1438         if ((fac < 0.0f) || (fac > 1.0f)) {
1439                 fac = 0.5f;
1440         }
1441         const float optimal = (1.0f - fac) * pta->strength + fac * ptc->strength;
1442
1443         /* Based on influence factor, blend between original and optimal */
1444         ptb->strength = (1.0f - influence) * ptb->strength + influence * optimal;
1445
1446         return true;
1447 }
1448
1449 /**
1450  * Apply smooth for thickness to stroke point (use pressure) */
1451 bool BKE_gpencil_smooth_stroke_thickness(bGPDstroke *gps, int point_index, float influence)
1452 {
1453         bGPDspoint *ptb = &gps->points[point_index];
1454
1455         /* Do nothing if not enough points */
1456         if ((gps->totpoints <= 2) || (point_index < 1)) {
1457                 return false;
1458         }
1459
1460         /* Compute theoretical optimal value using distances */
1461         bGPDspoint *pta, *ptc;
1462         int before = point_index - 1;
1463         int after = point_index + 1;
1464
1465         CLAMP_MIN(before, 0);
1466         CLAMP_MAX(after, gps->totpoints - 1);
1467
1468         pta = &gps->points[before];
1469         ptc = &gps->points[after];
1470
1471         /* the optimal value is the corresponding to the interpolation of the pressure
1472          * at the distance of point b
1473          */
1474         float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
1475         /* sometimes the factor can be wrong due stroke geometry, so use middle point */
1476         if ((fac < 0.0f) || (fac > 1.0f)) {
1477                 fac = 0.5f;
1478         }
1479         float optimal = interpf(ptc->pressure, pta->pressure, fac);
1480
1481         /* Based on influence factor, blend between original and optimal */
1482         ptb->pressure = interpf(optimal, ptb->pressure, influence);
1483
1484         return true;
1485 }
1486
1487 /**
1488  * Apply smooth for UV rotation to stroke point (use pressure).
1489  */
1490 bool BKE_gpencil_smooth_stroke_uv(bGPDstroke *gps, int point_index, float influence)
1491 {
1492         bGPDspoint *ptb = &gps->points[point_index];
1493
1494         /* Do nothing if not enough points */
1495         if (gps->totpoints <= 2) {
1496                 return false;
1497         }
1498
1499         /* Compute theoretical optimal value */
1500         bGPDspoint *pta, *ptc;
1501         int before = point_index - 1;
1502         int after = point_index + 1;
1503
1504         CLAMP_MIN(before, 0);
1505         CLAMP_MAX(after, gps->totpoints - 1);
1506
1507         pta = &gps->points[before];
1508         ptc = &gps->points[after];
1509
1510         /* the optimal value is the corresponding to the interpolation of the pressure
1511          * at the distance of point b
1512          */
1513         float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
1514         /* sometimes the factor can be wrong due stroke geometry, so use middle point */
1515         if ((fac < 0.0f) || (fac > 1.0f)) {
1516                 fac = 0.5f;
1517         }
1518         float optimal = interpf(ptc->uv_rot, pta->uv_rot, fac);
1519
1520         /* Based on influence factor, blend between original and optimal */
1521         ptb->uv_rot = interpf(optimal, ptb->uv_rot, influence);
1522         CLAMP(ptb->uv_rot, -M_PI_2, M_PI_2);
1523
1524         return true;
1525 }
1526
1527 /**
1528  * Get range of selected frames in layer.
1529  * Always the active frame is considered as selected, so if no more selected the range
1530  * will be equal to the current active frame.
1531  * \param gpl: Layer
1532  * \param r_initframe: Number of first selected frame
1533  * \param r_endframe: Number of last selected frame
1534  */
1535 void BKE_gpencil_get_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_endframe)
1536 {
1537         *r_initframe = gpl->actframe->framenum;
1538         *r_endframe = gpl->actframe->framenum;
1539
1540         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1541                 if (gpf->flag & GP_FRAME_SELECT) {
1542                         if (gpf->framenum < *r_initframe) {
1543                                 *r_initframe = gpf->framenum;
1544                         }
1545                         if (gpf->framenum > *r_endframe) {
1546                                 *r_endframe = gpf->framenum;
1547                         }
1548                 }
1549         }
1550 }
1551
1552 /**
1553  * Get Falloff factor base on frame range
1554  * \param gpf: Frame
1555  * \param actnum: Number of active frame in layer
1556  * \param f_init: Number of first selected frame
1557  * \param f_end: Number of last selected frame
1558  * \param cur_falloff: Curve with falloff factors
1559  */
1560 float BKE_gpencil_multiframe_falloff_calc(bGPDframe *gpf, int actnum, int f_init, int f_end, CurveMapping *cur_falloff)
1561 {
1562         float fnum = 0.5f; /* default mid curve */
1563         float value;
1564
1565         /* check curve is available */
1566         if (cur_falloff == NULL) {
1567                 return 1.0f;
1568         }
1569
1570         /* frames to the right of the active frame */
1571         if (gpf->framenum < actnum) {
1572                 fnum = (float)(gpf->framenum - f_init) / (actnum - f_init);
1573                 fnum *= 0.5f;
1574                 value = curvemapping_evaluateF(cur_falloff, 0, fnum);
1575         }
1576         /* frames to the left of the active frame */
1577         else if (gpf->framenum > actnum) {
1578                 fnum = (float)(gpf->framenum - actnum) / (f_end - actnum);
1579                 fnum *= 0.5f;
1580                 value = curvemapping_evaluateF(cur_falloff, 0, fnum + 0.5f);
1581         }
1582         else {
1583                 value = 1.0f;
1584         }
1585
1586         return value;
1587 }
1588
1589 /* remove strokes using a material */
1590 void BKE_gpencil_material_index_remove(bGPdata *gpd, int index)
1591 {
1592         bGPDstroke *gps, *gpsn;
1593
1594                 for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1595                         for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1596                                 for (gps = gpf->strokes.first; gps; gps = gpsn) {
1597                                         gpsn = gps->next;
1598                                         if (gps->mat_nr == index) {
1599                                                 if (gps->points) {
1600                                                         MEM_freeN(gps->points);
1601                                                 }
1602                                                 if (gps->dvert) {
1603                                                         BKE_gpencil_free_stroke_weights(gps);
1604                                                         MEM_freeN(gps->dvert);
1605                                                 }
1606                                                 if (gps->triangles) MEM_freeN(gps->triangles);
1607                                                 BLI_freelinkN(&gpf->strokes, gps);
1608                                         }
1609                                         else {
1610                                                 /* reassign strokes */
1611                                                 if (gps->mat_nr > index) {
1612                                                         gps->mat_nr--;
1613                                                 }
1614                                         }
1615                                 }
1616                         }
1617                 }
1618 }
1619
1620 void BKE_gpencil_material_remap(struct bGPdata *gpd, const unsigned int *remap, unsigned int remap_len)
1621 {
1622         const short remap_len_short = (short)remap_len;
1623
1624 #define MAT_NR_REMAP(n) \
1625         if (n < remap_len_short) { \
1626                 BLI_assert(n >= 0 && remap[n] < remap_len_short); \
1627                 n = remap[n]; \
1628         } ((void)0)
1629
1630         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1631                 for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1632                         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1633                                 /* reassign strokes */
1634                                 MAT_NR_REMAP(gps->mat_nr);
1635                         }
1636                 }
1637         }
1638
1639 #undef MAT_NR_REMAP
1640
1641 }
1642
1643 /* statistics functions */
1644 void BKE_gpencil_stats_update(bGPdata *gpd)
1645 {
1646         gpd->totlayer = 0;
1647         gpd->totframe = 0;
1648         gpd->totstroke = 0;
1649         gpd->totpoint = 0;
1650
1651         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1652                 gpd->totlayer++;
1653                 for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1654                         gpd->totframe++;
1655                         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1656                                 gpd->totstroke++;
1657                                 gpd->totpoint += gps->totpoints;
1658                         }
1659                 }
1660         }
1661
1662 }
1663
1664 /* get material index (0-based like mat_nr not actcol) */
1665 int BKE_gpencil_get_material_index(Object *ob, Material *ma)
1666 {
1667         short *totcol = give_totcolp(ob);
1668         Material *read_ma = NULL;
1669         for (short i = 0; i < *totcol; i++) {
1670                 read_ma = give_current_material(ob, i + 1);
1671                 if (ma == read_ma) {
1672                         return i;
1673                 }
1674         }
1675
1676         return -1;
1677 }
1678
1679 /* Get points of stroke always flat to view not affected by camera view or view position */
1680 void BKE_gpencil_stroke_2d_flat(const bGPDspoint *points, int totpoints, float(*points2d)[2], int *r_direction)
1681 {
1682         BLI_assert(totpoints >= 2);
1683
1684         const bGPDspoint *pt0 = &points[0];
1685         const bGPDspoint *pt1 = &points[1];
1686         const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
1687
1688         float locx[3];
1689         float locy[3];
1690         float loc3[3];
1691         float normal[3];
1692
1693         /* local X axis (p0 -> p1) */
1694         sub_v3_v3v3(locx, &pt1->x, &pt0->x);
1695
1696         /* point vector at 3/4 */
1697         float v3[3];
1698         if (totpoints == 2) {
1699                 mul_v3_v3fl(v3, &pt3->x, 0.001f);
1700         }
1701         else {
1702                 copy_v3_v3(v3, &pt3->x);
1703         }
1704
1705         sub_v3_v3v3(loc3, v3, &pt0->x);
1706
1707         /* vector orthogonal to polygon plane */
1708         cross_v3_v3v3(normal, locx, loc3);
1709
1710         /* local Y axis (cross to normal/x axis) */
1711         cross_v3_v3v3(locy, normal, locx);
1712
1713         /* Normalize vectors */
1714         normalize_v3(locx);
1715         normalize_v3(locy);
1716
1717         /* Get all points in local space */
1718         for (int i = 0; i < totpoints; i++) {
1719                 const bGPDspoint *pt = &points[i];
1720                 float loc[3];
1721
1722                 /* Get local space using first point as origin */
1723                 sub_v3_v3v3(loc, &pt->x, &pt0->x);
1724
1725                 points2d[i][0] = dot_v3v3(loc, locx);
1726                 points2d[i][1] = dot_v3v3(loc, locy);
1727         }
1728
1729         /* Concave (-1), Convex (1), or Autodetect (0)? */
1730         *r_direction = (int)locy[2];
1731 }
1732
1733 /* Get points of stroke always flat to view not affected by camera view or view position
1734  * using another stroke as reference
1735  */
1736 void BKE_gpencil_stroke_2d_flat_ref(
1737         const bGPDspoint *ref_points, int ref_totpoints,
1738         const bGPDspoint *points, int totpoints,
1739         float(*points2d)[2], const float scale, int *r_direction)
1740 {
1741         BLI_assert(totpoints >= 2);
1742
1743         const bGPDspoint *pt0 = &ref_points[0];
1744         const bGPDspoint *pt1 = &ref_points[1];
1745         const bGPDspoint *pt3 = &ref_points[(int)(ref_totpoints * 0.75)];
1746
1747         float locx[3];
1748         float locy[3];
1749         float loc3[3];
1750         float normal[3];
1751
1752         /* local X axis (p0 -> p1) */
1753         sub_v3_v3v3(locx, &pt1->x, &pt0->x);
1754
1755         /* point vector at 3/4 */
1756         float v3[3];
1757         if (totpoints == 2) {
1758                 mul_v3_v3fl(v3, &pt3->x, 0.001f);
1759         }
1760         else {
1761                 copy_v3_v3(v3, &pt3->x);
1762         }
1763
1764         sub_v3_v3v3(loc3, v3, &pt0->x);
1765
1766         /* vector orthogonal to polygon plane */
1767         cross_v3_v3v3(normal, locx, loc3);
1768
1769         /* local Y axis (cross to normal/x axis) */
1770         cross_v3_v3v3(locy, normal, locx);
1771
1772         /* Normalize vectors */
1773         normalize_v3(locx);
1774         normalize_v3(locy);
1775
1776         /* Get all points in local space */
1777         for (int i = 0; i < totpoints; i++) {
1778                 const bGPDspoint *pt = &points[i];
1779                 float loc[3];
1780                 float v1[3];
1781                 float vn[3] = { 0.0f, 0.0f, 0.0f };
1782
1783                 /* apply scale to extremes of the stroke to get better collision detection
1784                  * the scale is divided to get more control in the UI parameter
1785                  */
1786                 /* first point */
1787                 if (i == 0) {
1788                         const bGPDspoint *pt_next = &points[i + 1];
1789                         sub_v3_v3v3(vn, &pt->x, &pt_next->x);
1790                         normalize_v3(vn);
1791                         mul_v3_fl(vn, scale / 10.0f);
1792                         add_v3_v3v3(v1, &pt->x, vn);
1793                 }
1794                 /* last point */
1795                 else if (i == totpoints - 1) {
1796                         const bGPDspoint *pt_prev = &points[i - 1];
1797                         sub_v3_v3v3(vn, &pt->x, &pt_prev->x);
1798                         normalize_v3(vn);
1799                         mul_v3_fl(vn, scale / 10.0f);
1800                         add_v3_v3v3(v1, &pt->x, vn);
1801                 }
1802                 else {
1803                         copy_v3_v3(v1, &pt->x);
1804                 }
1805
1806                 /* Get local space using first point as origin (ref stroke) */
1807                 sub_v3_v3v3(loc, v1, &pt0->x);
1808
1809                 points2d[i][0] = dot_v3v3(loc, locx);
1810                 points2d[i][1] = dot_v3v3(loc, locy);
1811         }
1812
1813         /* Concave (-1), Convex (1), or Autodetect (0)? */
1814         *r_direction = (int)locy[2];
1815 }
1816
1817 /**
1818  * Trim stroke to the first intersection or loop
1819  * \param gps: Stroke data
1820  */
1821 bool BKE_gpencil_trim_stroke(bGPDstroke *gps)
1822 {
1823         if (gps->totpoints < 4) {
1824                 return false;
1825         }
1826         bool intersect = false;
1827         int start, end;
1828         float point[3];
1829         /* loop segments from start until we have an intersection */
1830         for (int i = 0; i < gps->totpoints - 2; i++) {
1831                 start = i;
1832                 bGPDspoint *a = &gps->points[start];
1833                 bGPDspoint *b = &gps->points[start + 1];
1834                 for (int j = start + 2; j < gps->totpoints - 1; j++) {
1835                         end = j + 1;
1836                         bGPDspoint *c = &gps->points[j];
1837                         bGPDspoint *d = &gps->points[end];
1838                         float pointb[3];
1839                         /* get intersection */
1840                         if (isect_line_line_v3(&a->x, &b->x, &c->x, &d->x, point, pointb)) {
1841                                 if (len_v3(point) > 0.0f) {
1842                                         float closest[3];
1843                                         /* check intersection is on both lines */
1844                                         float lambda = closest_to_line_v3(closest, point, &a->x, &b->x);
1845                                         if ((lambda <= 0.0f) || (lambda >= 1.0f)) {
1846                                                 continue;
1847                                         }
1848                                         lambda = closest_to_line_v3(closest, point, &c->x, &d->x);
1849                                         if ((lambda <= 0.0f) || (lambda >= 1.0f)) {
1850                                                 continue;
1851                                         }
1852                                         else {
1853                                                 intersect = true;
1854                                                 break;
1855                                         }
1856                                 }
1857                         }
1858                 }
1859                 if (intersect) {
1860                         break;
1861                 }
1862         }
1863
1864         /* trim unwanted points */
1865         if (intersect) {
1866
1867                 /* save points */
1868                 bGPDspoint *old_points = MEM_dupallocN(gps->points);
1869                 MDeformVert *old_dvert = NULL;
1870                 MDeformVert *dvert_src = NULL;
1871
1872                 if (gps->dvert != NULL) {
1873                         old_dvert = MEM_dupallocN(gps->dvert);
1874                 }
1875
1876                 /* resize gps */
1877                 int newtot = end - start + 1;
1878
1879                 gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * newtot);
1880                 if (gps->dvert != NULL) {
1881                         gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * newtot);
1882                 }
1883
1884                 for (int i = 0; i < newtot; i++) {
1885                         int idx = start + i;
1886                         bGPDspoint *pt_src = &old_points[idx];
1887                         bGPDspoint *pt_new = &gps->points[i];
1888                         memcpy(pt_new, pt_src, sizeof(bGPDspoint));
1889                         if (gps->dvert != NULL) {
1890                                 dvert_src = &old_dvert[idx];
1891                                 MDeformVert *dvert = &gps->dvert[i];
1892                                 memcpy(dvert, dvert_src, sizeof(MDeformVert));
1893                                 if (dvert_src->dw) {
1894                                         memcpy(dvert->dw, dvert_src->dw, sizeof(MDeformWeight));
1895                                 }
1896                         }
1897                         if (idx == start || idx == end) {
1898                                 copy_v3_v3(&pt_new->x, point);
1899                         }
1900                 }
1901
1902                 gps->flag |= GP_STROKE_RECALC_GEOMETRY;
1903                 gps->tot_triangles = 0;
1904                 gps->totpoints = newtot;
1905
1906                 MEM_SAFE_FREE(old_points);
1907                 MEM_SAFE_FREE(old_dvert);
1908         }
1909         return intersect;
1910 }