1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2008, Blender Foundation
17  * This is a new part of Blender
18  */
19 
20 /** \file
21  * \ingroup bke
22  */
23 
24 #include <math.h>
25 #include <stddef.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include "CLG_log.h"
31 
32 #include "MEM_guardedalloc.h"
33 
34 #include "BLI_blenlib.h"
35 #include "BLI_math_vector.h"
36 #include "BLI_string_utils.h"
37 
38 #include "BLT_translation.h"
39 
40 #include "IMB_imbuf.h"
41 #include "IMB_imbuf_types.h"
42 
43 /* Allow using deprecated functionality for .blend file I/O. */
44 #define DNA_DEPRECATED_ALLOW
45 
46 #include "DNA_gpencil_types.h"
47 #include "DNA_material_types.h"
48 #include "DNA_meshdata_types.h"
49 #include "DNA_space_types.h"
50 
51 #include "BKE_action.h"
52 #include "BKE_anim_data.h"
53 #include "BKE_collection.h"
54 #include "BKE_colortools.h"
55 #include "BKE_deform.h"
56 #include "BKE_gpencil.h"
57 #include "BKE_gpencil_geom.h"
58 #include "BKE_icons.h"
59 #include "BKE_idtype.h"
60 #include "BKE_image.h"
61 #include "BKE_lib_id.h"
62 #include "BKE_lib_query.h"
63 #include "BKE_main.h"
64 #include "BKE_material.h"
65 #include "BKE_paint.h"
66 
67 #include "BLI_math_color.h"
68 
69 #include "DEG_depsgraph_query.h"
70 
71 #include "BLO_read_write.h"
72 
73 #include "BKE_gpencil.h"
74 
75 static CLG_LogRef LOG = {"bke.gpencil"};
76 
greasepencil_copy_data(Main * UNUSED (bmain),ID * id_dst,const ID * id_src,const int UNUSED (flag))77 static void greasepencil_copy_data(Main *UNUSED(bmain),
78                                    ID *id_dst,
79                                    const ID *id_src,
80                                    const int UNUSED(flag))
81 {
82   bGPdata *gpd_dst = (bGPdata *)id_dst;
83   const bGPdata *gpd_src = (const bGPdata *)id_src;
84 
85   /* duplicate material array */
86   if (gpd_src->mat) {
87     gpd_dst->mat = MEM_dupallocN(gpd_src->mat);
88   }
89 
90   /* copy layers */
91   BLI_listbase_clear(&gpd_dst->layers);
92   LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) {
93     /* make a copy of source layer and its data */
94 
95     /* TODO here too could add unused flags... */
96     bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src);
97 
98     BLI_addtail(&gpd_dst->layers, gpl_dst);
99   }
100 }
101 
greasepencil_free_data(ID * id)102 static void greasepencil_free_data(ID *id)
103 {
104   /* Really not ideal, but for now will do... In theory custom behaviors like not freeing cache
105    * should be handled through specific API, and not be part of the generic one. */
106   BKE_gpencil_free((bGPdata *)id, true);
107 }
108 
greasepencil_foreach_id(ID * id,LibraryForeachIDData * data)109 static void greasepencil_foreach_id(ID *id, LibraryForeachIDData *data)
110 {
111   bGPdata *gpencil = (bGPdata *)id;
112   /* materials */
113   for (int i = 0; i < gpencil->totcol; i++) {
114     BKE_LIB_FOREACHID_PROCESS(data, gpencil->mat[i], IDWALK_CB_USER);
115   }
116 
117   LISTBASE_FOREACH (bGPDlayer *, gplayer, &gpencil->layers) {
118     BKE_LIB_FOREACHID_PROCESS(data, gplayer->parent, IDWALK_CB_NOP);
119   }
120 }
121 
greasepencil_blend_write(BlendWriter * writer,ID * id,const void * id_address)122 static void greasepencil_blend_write(BlendWriter *writer, ID *id, const void *id_address)
123 {
124   bGPdata *gpd = (bGPdata *)id;
125   if (gpd->id.us > 0 || BLO_write_is_undo(writer)) {
126     /* Clean up, important in undo case to reduce false detection of changed data-blocks. */
127     /* XXX not sure why the whole run-time data is not cleared in reading code,
128      * for now mimicking it here. */
129     gpd->runtime.sbuffer = NULL;
130     gpd->runtime.sbuffer_used = 0;
131     gpd->runtime.sbuffer_size = 0;
132     gpd->runtime.tot_cp_points = 0;
133 
134     /* write gpd data block to file */
135     BLO_write_id_struct(writer, bGPdata, id_address, &gpd->id);
136     BKE_id_blend_write(writer, &gpd->id);
137 
138     if (gpd->adt) {
139       BKE_animdata_blend_write(writer, gpd->adt);
140     }
141 
142     BLO_write_pointer_array(writer, gpd->totcol, gpd->mat);
143 
144     /* write grease-pencil layers to file */
145     BLO_write_struct_list(writer, bGPDlayer, &gpd->layers);
146     LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
147       /* Write mask list. */
148       BLO_write_struct_list(writer, bGPDlayer_Mask, &gpl->mask_layers);
149       /* write this layer's frames to file */
150       BLO_write_struct_list(writer, bGPDframe, &gpl->frames);
151       LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
152         /* write strokes */
153         BLO_write_struct_list(writer, bGPDstroke, &gpf->strokes);
154         LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
155           BLO_write_struct_array(writer, bGPDspoint, gps->totpoints, gps->points);
156           BLO_write_struct_array(writer, bGPDtriangle, gps->tot_triangles, gps->triangles);
157           BKE_defvert_blend_write(writer, gps->totpoints, gps->dvert);
158         }
159       }
160     }
161   }
162 }
163 
BKE_gpencil_blend_read_data(BlendDataReader * reader,bGPdata * gpd)164 void BKE_gpencil_blend_read_data(BlendDataReader *reader, bGPdata *gpd)
165 {
166   /* we must firstly have some grease-pencil data to link! */
167   if (gpd == NULL) {
168     return;
169   }
170 
171   /* relink animdata */
172   BLO_read_data_address(reader, &gpd->adt);
173   BKE_animdata_blend_read_data(reader, gpd->adt);
174 
175   /* Ensure full objectmode for linked grease pencil. */
176   if (gpd->id.lib != NULL) {
177     gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
178     gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
179     gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
180     gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
181     gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE;
182   }
183 
184   /* init stroke buffer */
185   gpd->runtime.sbuffer = NULL;
186   gpd->runtime.sbuffer_used = 0;
187   gpd->runtime.sbuffer_size = 0;
188   gpd->runtime.tot_cp_points = 0;
189 
190   /* relink palettes (old palettes deprecated, only to convert old files) */
191   BLO_read_list(reader, &gpd->palettes);
192   if (gpd->palettes.first != NULL) {
193     LISTBASE_FOREACH (Palette *, palette, &gpd->palettes) {
194       BLO_read_list(reader, &palette->colors);
195     }
196   }
197 
198   /* materials */
199   BLO_read_pointer_array(reader, (void **)&gpd->mat);
200 
201   /* relink layers */
202   BLO_read_list(reader, &gpd->layers);
203 
204   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
205     /* relink frames */
206     BLO_read_list(reader, &gpl->frames);
207 
208     BLO_read_data_address(reader, &gpl->actframe);
209 
210     gpl->runtime.icon_id = 0;
211 
212     /* Relink masks. */
213     BLO_read_list(reader, &gpl->mask_layers);
214 
215     LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
216       /* relink strokes (and their points) */
217       BLO_read_list(reader, &gpf->strokes);
218 
219       LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
220         /* relink stroke points array */
221         BLO_read_data_address(reader, &gps->points);
222         /* Relink geometry*/
223         BLO_read_data_address(reader, &gps->triangles);
224 
225         /* relink weight data */
226         if (gps->dvert) {
227           BLO_read_data_address(reader, &gps->dvert);
228           BKE_defvert_blend_read(reader, gps->totpoints, gps->dvert);
229         }
230       }
231     }
232   }
233 }
234 
greasepencil_blend_read_data(BlendDataReader * reader,ID * id)235 static void greasepencil_blend_read_data(BlendDataReader *reader, ID *id)
236 {
237   bGPdata *gpd = (bGPdata *)id;
238   BKE_gpencil_blend_read_data(reader, gpd);
239 }
240 
greasepencil_blend_read_lib(BlendLibReader * reader,ID * id)241 static void greasepencil_blend_read_lib(BlendLibReader *reader, ID *id)
242 {
243   bGPdata *gpd = (bGPdata *)id;
244 
245   /* Relink all data-lock linked by GP data-lock */
246   /* Layers */
247   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
248     /* Layer -> Parent References */
249     BLO_read_id_address(reader, gpd->id.lib, &gpl->parent);
250   }
251 
252   /* materials */
253   for (int a = 0; a < gpd->totcol; a++) {
254     BLO_read_id_address(reader, gpd->id.lib, &gpd->mat[a]);
255   }
256 }
257 
greasepencil_blend_read_expand(BlendExpander * expander,ID * id)258 static void greasepencil_blend_read_expand(BlendExpander *expander, ID *id)
259 {
260   bGPdata *gpd = (bGPdata *)id;
261   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
262     BLO_expand(expander, gpl->parent);
263   }
264 
265   for (int a = 0; a < gpd->totcol; a++) {
266     BLO_expand(expander, gpd->mat[a]);
267   }
268 }
269 
270 IDTypeInfo IDType_ID_GD = {
271     .id_code = ID_GD,
272     .id_filter = FILTER_ID_GD,
273     .main_listbase_index = INDEX_ID_GD,
274     .struct_size = sizeof(bGPdata),
275     .name = "GPencil",
276     .name_plural = "grease_pencils",
277     .translation_context = BLT_I18NCONTEXT_ID_GPENCIL,
278     .flags = 0,
279 
280     .init_data = NULL,
281     .copy_data = greasepencil_copy_data,
282     .free_data = greasepencil_free_data,
283     .make_local = NULL,
284     .foreach_id = greasepencil_foreach_id,
285     .foreach_cache = NULL,
286 
287     .blend_write = greasepencil_blend_write,
288     .blend_read_data = greasepencil_blend_read_data,
289     .blend_read_lib = greasepencil_blend_read_lib,
290     .blend_read_expand = greasepencil_blend_read_expand,
291 };
292 
293 /* ************************************************** */
294 /* Draw Engine */
295 
296 void (*BKE_gpencil_batch_cache_dirty_tag_cb)(bGPdata *gpd) = NULL;
297 void (*BKE_gpencil_batch_cache_free_cb)(bGPdata *gpd) = NULL;
298 
BKE_gpencil_batch_cache_dirty_tag(bGPdata * gpd)299 void BKE_gpencil_batch_cache_dirty_tag(bGPdata *gpd)
300 {
301   if (gpd) {
302     DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
303     BKE_gpencil_batch_cache_dirty_tag_cb(gpd);
304   }
305 }
306 
BKE_gpencil_batch_cache_free(bGPdata * gpd)307 void BKE_gpencil_batch_cache_free(bGPdata *gpd)
308 {
309   if (gpd) {
310     BKE_gpencil_batch_cache_free_cb(gpd);
311   }
312 }
313 
314 /* ************************************************** */
315 /* Memory Management */
316 
317 /* clean vertex groups weights */
BKE_gpencil_free_point_weights(MDeformVert * dvert)318 void BKE_gpencil_free_point_weights(MDeformVert *dvert)
319 {
320   if (dvert == NULL) {
321     return;
322   }
323   MEM_SAFE_FREE(dvert->dw);
324 }
325 
BKE_gpencil_free_stroke_weights(bGPDstroke * gps)326 void BKE_gpencil_free_stroke_weights(bGPDstroke *gps)
327 {
328   if (gps == NULL) {
329     return;
330   }
331 
332   if (gps->dvert == NULL) {
333     return;
334   }
335 
336   for (int i = 0; i < gps->totpoints; i++) {
337     MDeformVert *dvert = &gps->dvert[i];
338     BKE_gpencil_free_point_weights(dvert);
339   }
340 }
341 
342 /* free stroke, doesn't unlink from any listbase */
BKE_gpencil_free_stroke(bGPDstroke * gps)343 void BKE_gpencil_free_stroke(bGPDstroke *gps)
344 {
345   if (gps == NULL) {
346     return;
347   }
348   /* free stroke memory arrays, then stroke itself */
349   if (gps->points) {
350     MEM_freeN(gps->points);
351   }
352   if (gps->dvert) {
353     BKE_gpencil_free_stroke_weights(gps);
354     MEM_freeN(gps->dvert);
355   }
356   if (gps->triangles) {
357     MEM_freeN(gps->triangles);
358   }
359 
360   MEM_freeN(gps);
361 }
362 
363 /* Free strokes belonging to a gp-frame */
BKE_gpencil_free_strokes(bGPDframe * gpf)364 bool BKE_gpencil_free_strokes(bGPDframe *gpf)
365 {
366   bool changed = (BLI_listbase_is_empty(&gpf->strokes) == false);
367 
368   /* free strokes */
369   LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
370     BKE_gpencil_free_stroke(gps);
371   }
372   BLI_listbase_clear(&gpf->strokes);
373 
374   return changed;
375 }
376 
377 /* Free all of a gp-layer's frames */
BKE_gpencil_free_frames(bGPDlayer * gpl)378 void BKE_gpencil_free_frames(bGPDlayer *gpl)
379 {
380   bGPDframe *gpf_next;
381 
382   /* error checking */
383   if (gpl == NULL) {
384     return;
385   }
386 
387   /* free frames */
388   for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf_next) {
389     gpf_next = gpf->next;
390 
391     /* free strokes and their associated memory */
392     BKE_gpencil_free_strokes(gpf);
393     BLI_freelinkN(&gpl->frames, gpf);
394   }
395   gpl->actframe = NULL;
396 }
397 
BKE_gpencil_free_layer_masks(bGPDlayer * gpl)398 void BKE_gpencil_free_layer_masks(bGPDlayer *gpl)
399 {
400   /* Free masks.*/
401   bGPDlayer_Mask *mask_next = NULL;
402   for (bGPDlayer_Mask *mask = gpl->mask_layers.first; mask; mask = mask_next) {
403     mask_next = mask->next;
404     BLI_freelinkN(&gpl->mask_layers, mask);
405   }
406 }
407 /* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */
BKE_gpencil_free_layers(ListBase * list)408 void BKE_gpencil_free_layers(ListBase *list)
409 {
410   bGPDlayer *gpl_next;
411 
412   /* error checking */
413   if (list == NULL) {
414     return;
415   }
416 
417   /* delete layers */
418   for (bGPDlayer *gpl = list->first; gpl; gpl = gpl_next) {
419     gpl_next = gpl->next;
420 
421     /* free layers and their data */
422     BKE_gpencil_free_frames(gpl);
423 
424     /* Free masks.*/
425     BKE_gpencil_free_layer_masks(gpl);
426 
427     BLI_freelinkN(list, gpl);
428   }
429 }
430 
431 /** Free (or release) any data used by this grease pencil (does not free the gpencil itself). */
BKE_gpencil_free(bGPdata * gpd,bool free_all)432 void BKE_gpencil_free(bGPdata *gpd, bool free_all)
433 {
434   /* free layers */
435   BKE_gpencil_free_layers(&gpd->layers);
436 
437   /* materials */
438   MEM_SAFE_FREE(gpd->mat);
439 
440   /* free all data */
441   if (free_all) {
442     /* clear cache */
443     BKE_gpencil_batch_cache_free(gpd);
444   }
445 }
446 
447 /**
448  * Delete grease pencil evaluated data
449  * \param gpd_eval: Grease pencil data-block
450  */
BKE_gpencil_eval_delete(bGPdata * gpd_eval)451 void BKE_gpencil_eval_delete(bGPdata *gpd_eval)
452 {
453   BKE_gpencil_free(gpd_eval, true);
454   BKE_libblock_free_data(&gpd_eval->id, false);
455   MEM_freeN(gpd_eval);
456 }
457 
458 /**
459  * Tag data-block for depsgraph update.
460  * Wrapper to avoid include Depsgraph tag functions in other modules.
461  * \param gpd: Grease pencil data-block.
462  */
BKE_gpencil_tag(bGPdata * gpd)463 void BKE_gpencil_tag(bGPdata *gpd)
464 {
465   DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
466 }
467 
468 /* ************************************************** */
469 /* Container Creation */
470 
471 /**
472  * Add a new gp-frame to the given layer.
473  * \param gpl: Grease pencil layer
474  * \param cframe: Frame number
475  * \return Pointer to new frame
476  */
BKE_gpencil_frame_addnew(bGPDlayer * gpl,int cframe)477 bGPDframe *BKE_gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
478 {
479   bGPDframe *gpf = NULL, *gf = NULL;
480   short state = 0;
481 
482   /* error checking */
483   if (gpl == NULL) {
484     return NULL;
485   }
486 
487   /* allocate memory for this frame */
488   gpf = MEM_callocN(sizeof(bGPDframe), "bGPDframe");
489   gpf->framenum = cframe;
490 
491   /* find appropriate place to add frame */
492   if (gpl->frames.first) {
493     for (gf = gpl->frames.first; gf; gf = gf->next) {
494       /* check if frame matches one that is supposed to be added */
495       if (gf->framenum == cframe) {
496         state = -1;
497         break;
498       }
499 
500       /* if current frame has already exceeded the frame to add, add before */
501       if (gf->framenum > cframe) {
502         BLI_insertlinkbefore(&gpl->frames, gf, gpf);
503         state = 1;
504         break;
505       }
506     }
507   }
508 
509   /* check whether frame was added successfully */
510   if (state == -1) {
511     CLOG_ERROR(
512         &LOG, "Frame (%d) existed already for this layer_active. Using existing frame", cframe);
513 
514     /* free the newly created one, and use the old one instead */
515     MEM_freeN(gpf);
516 
517     /* return existing frame instead... */
518     BLI_assert(gf != NULL);
519     gpf = gf;
520   }
521   else if (state == 0) {
522     /* add to end then! */
523     BLI_addtail(&gpl->frames, gpf);
524   }
525 
526   /* return frame */
527   return gpf;
528 }
529 
530 /**
531  * Add a copy of the active gp-frame to the given layer.
532  * \param gpl: Grease pencil layer
533  * \param cframe: Frame number
534  * \return Pointer to new frame
535  */
BKE_gpencil_frame_addcopy(bGPDlayer * gpl,int cframe)536 bGPDframe *BKE_gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
537 {
538   bGPDframe *new_frame;
539   bool found = false;
540 
541   /* Error checking/handling */
542   if (gpl == NULL) {
543     /* no layer */
544     return NULL;
545   }
546   if (gpl->actframe == NULL) {
547     /* no active frame, so just create a new one from scratch */
548     return BKE_gpencil_frame_addnew(gpl, cframe);
549   }
550 
551   /* Create a copy of the frame */
552   new_frame = BKE_gpencil_frame_duplicate(gpl->actframe);
553 
554   /* Find frame to insert it before */
555   LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
556     if (gpf->framenum > cframe) {
557       /* Add it here */
558       BLI_insertlinkbefore(&gpl->frames, gpf, new_frame);
559 
560       found = true;
561       break;
562     }
563     if (gpf->framenum == cframe) {
564       /* This only happens when we're editing with framelock on...
565        * - Delete the new frame and don't do anything else here...
566        */
567       BKE_gpencil_free_strokes(new_frame);
568       MEM_freeN(new_frame);
569       new_frame = NULL;
570 
571       found = true;
572       break;
573     }
574   }
575 
576   if (found == false) {
577     /* Add new frame to the end */
578     BLI_addtail(&gpl->frames, new_frame);
579   }
580 
581   /* Ensure that frame is set up correctly, and return it */
582   if (new_frame) {
583     new_frame->framenum = cframe;
584     gpl->actframe = new_frame;
585   }
586 
587   return new_frame;
588 }
589 
590 /**
591  * Add a new gp-layer and make it the active layer.
592  * \param gpd: Grease pencil data-block
593  * \param name: Name of the layer
594  * \param setactive: Set as active
595  * \return Pointer to new layer
596  */
BKE_gpencil_layer_addnew(bGPdata * gpd,const char * name,bool setactive)597 bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setactive)
598 {
599   bGPDlayer *gpl = NULL;
600   bGPDlayer *gpl_active = NULL;
601 
602   /* check that list is ok */
603   if (gpd == NULL) {
604     return NULL;
605   }
606 
607   /* allocate memory for frame and add to end of list */
608   gpl = MEM_callocN(sizeof(bGPDlayer), "bGPDlayer");
609 
610   gpl_active = BKE_gpencil_layer_active_get(gpd);
611 
612   /* Add to data-block. */
613   if (gpl_active == NULL) {
614     BLI_addtail(&gpd->layers, gpl);
615   }
616   else {
617     /* if active layer, add after that layer */
618     BLI_insertlinkafter(&gpd->layers, gpl_active, gpl);
619   }
620 
621   /* annotation vs GP Object behavior is slightly different */
622   if (gpd->flag & GP_DATA_ANNOTATIONS) {
623     /* set default color of new strokes for this layer */
624     copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
625     gpl->opacity = 1.0f;
626 
627     /* set default thickness of new strokes for this layer */
628     gpl->thickness = 3;
629 
630     /* Onion colors */
631     ARRAY_SET_ITEMS(gpl->gcolor_prev, 0.302f, 0.851f, 0.302f);
632     ARRAY_SET_ITEMS(gpl->gcolor_next, 0.250f, 0.1f, 1.0f);
633   }
634   else {
635     /* thickness parameter represents "thickness change", not absolute thickness */
636     gpl->thickness = 0;
637     gpl->opacity = 1.0f;
638     /* default channel color */
639     ARRAY_SET_ITEMS(gpl->color, 0.2f, 0.2f, 0.2f);
640     /* Default vertex mix. */
641     gpl->vertex_paint_opacity = 1.0f;
642   }
643 
644   /* auto-name */
645   BLI_strncpy(gpl->info, name, sizeof(gpl->info));
646   BLI_uniquename(&gpd->layers,
647                  gpl,
648                  (gpd->flag & GP_DATA_ANNOTATIONS) ? DATA_("Note") : DATA_("GP_Layer"),
649                  '.',
650                  offsetof(bGPDlayer, info),
651                  sizeof(gpl->info));
652 
653   /* Enable always affected by scene lights. */
654   gpl->flag |= GP_LAYER_USE_LIGHTS;
655   /* make this one the active one */
656   if (setactive) {
657     BKE_gpencil_layer_active_set(gpd, gpl);
658   }
659 
660   /* return layer */
661   return gpl;
662 }
663 
664 /**
665  * Add a new grease pencil data-block.
666  * \param bmain: Main pointer
667  * \param name: Name of the datablock
668  * \return Pointer to new data-block
669  */
BKE_gpencil_data_addnew(Main * bmain,const char name[])670 bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
671 {
672   bGPdata *gpd;
673 
674   /* allocate memory for a new block */
675   gpd = BKE_libblock_alloc(bmain, ID_GD, name, 0);
676 
677   /* initial settings */
678   gpd->flag = (GP_DATA_DISPINFO | GP_DATA_EXPAND);
679 
680   /* general flags */
681   gpd->flag |= GP_DATA_VIEWALIGN;
682   /* always enable object onion skin switch */
683   gpd->flag |= GP_DATA_SHOW_ONIONSKINS;
684   /* GP object specific settings */
685   ARRAY_SET_ITEMS(gpd->line_color, 0.6f, 0.6f, 0.6f, 0.5f);
686 
687   gpd->pixfactor = GP_DEFAULT_PIX_FACTOR;
688 
689   gpd->zdepth_offset = 0.150f;
690 
691   /* grid settings */
692   ARRAY_SET_ITEMS(gpd->grid.color, 0.5f, 0.5f, 0.5f); /* Color */
693   ARRAY_SET_ITEMS(gpd->grid.scale, 1.0f, 1.0f);       /* Scale */
694   gpd->grid.lines = GP_DEFAULT_GRID_LINES;            /* Number of lines */
695 
696   /* Onion-skinning settings (data-block level) */
697   gpd->onion_keytype = -1; /* All by default. */
698   gpd->onion_flag |= (GP_ONION_GHOST_PREVCOL | GP_ONION_GHOST_NEXTCOL);
699   gpd->onion_flag |= GP_ONION_FADE;
700   gpd->onion_mode = GP_ONION_MODE_RELATIVE;
701   gpd->onion_factor = 0.5f;
702   ARRAY_SET_ITEMS(gpd->gcolor_prev, 0.145098f, 0.419608f, 0.137255f); /* green */
703   ARRAY_SET_ITEMS(gpd->gcolor_next, 0.125490f, 0.082353f, 0.529412f); /* blue */
704   gpd->gstep = 1;
705   gpd->gstep_next = 1;
706 
707   return gpd;
708 }
709 
710 /* ************************************************** */
711 /* Primitive Creation */
712 /* Utilities for easier bulk-creation of geometry */
713 
714 /**
715  * Populate stroke with point data from data buffers.
716  * \param gps: Grease pencil stroke
717  * \param array: Flat array of point data values. Each entry has #GP_PRIM_DATABUF_SIZE values.
718  * \param totpoints: Total of points
719  * \param mat: 4x4 transform matrix to transform points into the right coordinate space.
720  */
BKE_gpencil_stroke_add_points(bGPDstroke * gps,const float * array,const int totpoints,const float mat[4][4])721 void BKE_gpencil_stroke_add_points(bGPDstroke *gps,
722                                    const float *array,
723                                    const int totpoints,
724                                    const float mat[4][4])
725 {
726   for (int i = 0; i < totpoints; i++) {
727     bGPDspoint *pt = &gps->points[i];
728     const int x = GP_PRIM_DATABUF_SIZE * i;
729 
730     pt->x = array[x];
731     pt->y = array[x + 1];
732     pt->z = array[x + 2];
733     mul_m4_v3(mat, &pt->x);
734 
735     pt->pressure = array[x + 3];
736     pt->strength = array[x + 4];
737   }
738 }
739 
740 /**
741  * Create a new stroke, with pre-allocated data buffers.
742  * \param mat_idx: Index of the material
743  * \param totpoints: Total points
744  * \param thickness: Stroke thickness
745  * \return Pointer to new stroke
746  */
BKE_gpencil_stroke_new(int mat_idx,int totpoints,short thickness)747 bGPDstroke *BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness)
748 {
749   /* allocate memory for a new stroke */
750   bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
751 
752   gps->thickness = thickness;
753   gps->fill_opacity_fac = 1.0f;
754   gps->hardeness = 1.0f;
755   copy_v2_fl(gps->aspect_ratio, 1.0f);
756 
757   gps->uv_scale = 1.0f;
758 
759   gps->inittime = 0;
760 
761   gps->flag = GP_STROKE_3DSPACE;
762 
763   gps->totpoints = totpoints;
764   if (gps->totpoints > 0) {
765     gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
766   }
767   else {
768     gps->points = NULL;
769   }
770 
771   /* initialize triangle memory to dummy data */
772   gps->triangles = NULL;
773   gps->tot_triangles = 0;
774 
775   gps->mat_nr = mat_idx;
776 
777   return gps;
778 }
779 
780 /**
781  * Create a new stroke and add to frame.
782  * \param gpf: Grease pencil frame
783  * \param mat_idx: Material index
784  * \param totpoints: Total points
785  * \param thickness: Stroke thickness
786  * \param insert_at_head: Add to the head of the strokes list
787  * \return Pointer to new stroke
788  */
BKE_gpencil_stroke_add(bGPDframe * gpf,int mat_idx,int totpoints,short thickness,const bool insert_at_head)789 bGPDstroke *BKE_gpencil_stroke_add(
790     bGPDframe *gpf, int mat_idx, int totpoints, short thickness, const bool insert_at_head)
791 {
792   bGPDstroke *gps = BKE_gpencil_stroke_new(mat_idx, totpoints, thickness);
793 
794   /* Add to frame. */
795   if ((gps != NULL) && (gpf != NULL)) {
796     if (!insert_at_head) {
797       BLI_addtail(&gpf->strokes, gps);
798     }
799     else {
800       BLI_addhead(&gpf->strokes, gps);
801     }
802   }
803 
804   return gps;
805 }
806 
807 /**
808  * Add a stroke and copy the temporary drawing color value
809  * from one of the existing stroke.
810  * \param gpf: Grease pencil frame
811  * \param existing: Stroke with the style to copy
812  * \param mat_idx: Material index
813  * \param totpoints: Total points
814  * \param thickness: Stroke thickness
815  * \return Pointer to new stroke
816  */
BKE_gpencil_stroke_add_existing_style(bGPDframe * gpf,bGPDstroke * existing,int mat_idx,int totpoints,short thickness)817 bGPDstroke *BKE_gpencil_stroke_add_existing_style(
818     bGPDframe *gpf, bGPDstroke *existing, int mat_idx, int totpoints, short thickness)
819 {
820   bGPDstroke *gps = BKE_gpencil_stroke_add(gpf, mat_idx, totpoints, thickness, false);
821   /* Copy run-time color data so that strokes added in the modifier has the style.
822    * There are depsgraph reference pointers inside,
823    * change the copy function if interfere with future drawing implementation. */
824   memcpy(&gps->runtime, &existing->runtime, sizeof(bGPDstroke_Runtime));
825   return gps;
826 }
827 
828 /* ************************************************** */
829 /* Data Duplication */
830 
831 /**
832  * Make a copy of a given gpencil weights.
833  * \param gps_src: Source grease pencil stroke
834  * \param gps_dst: Destination grease pencil stroke
835  */
BKE_gpencil_stroke_weights_duplicate(bGPDstroke * gps_src,bGPDstroke * gps_dst)836 void BKE_gpencil_stroke_weights_duplicate(bGPDstroke *gps_src, bGPDstroke *gps_dst)
837 {
838   if (gps_src == NULL) {
839     return;
840   }
841   BLI_assert(gps_src->totpoints == gps_dst->totpoints);
842 
843   BKE_defvert_array_copy(gps_dst->dvert, gps_src->dvert, gps_src->totpoints);
844 }
845 
846 /**
847  * Make a copy of a given grease-pencil stroke.
848  * \param gps_src: Source grease pencil strokes.
849  * \param dup_points: Duplicate points data.
850  * \return Pointer to new stroke.
851  */
BKE_gpencil_stroke_duplicate(bGPDstroke * gps_src,const bool dup_points)852 bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src, const bool dup_points)
853 {
854   bGPDstroke *gps_dst = NULL;
855 
856   gps_dst = MEM_dupallocN(gps_src);
857   gps_dst->prev = gps_dst->next = NULL;
858   gps_dst->triangles = MEM_dupallocN(gps_src->triangles);
859 
860   if (dup_points) {
861     gps_dst->points = MEM_dupallocN(gps_src->points);
862 
863     if (gps_src->dvert != NULL) {
864       gps_dst->dvert = MEM_dupallocN(gps_src->dvert);
865       BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst);
866     }
867     else {
868       gps_dst->dvert = NULL;
869     }
870   }
871 
872   /* return new stroke */
873   return gps_dst;
874 }
875 
876 /**
877  * Make a copy of a given gpencil frame.
878  * \param gpf_src: Source grease pencil frame
879  * \return Pointer to new frame
880  */
BKE_gpencil_frame_duplicate(const bGPDframe * gpf_src)881 bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src)
882 {
883   bGPDstroke *gps_dst = NULL;
884   bGPDframe *gpf_dst;
885 
886   /* error checking */
887   if (gpf_src == NULL) {
888     return NULL;
889   }
890 
891   /* make a copy of the source frame */
892   gpf_dst = MEM_dupallocN(gpf_src);
893   gpf_dst->prev = gpf_dst->next = NULL;
894 
895   /* copy strokes */
896   BLI_listbase_clear(&gpf_dst->strokes);
897   LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
898     /* make copy of source stroke */
899     gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true);
900     BLI_addtail(&gpf_dst->strokes, gps_dst);
901   }
902 
903   /* return new frame */
904   return gpf_dst;
905 }
906 
907 /**
908  * Make a copy of strokes between gpencil frames.
909  * \param gpf_src: Source grease pencil frame
910  * \param gpf_dst: Destination grease pencil frame
911  */
BKE_gpencil_frame_copy_strokes(bGPDframe * gpf_src,struct bGPDframe * gpf_dst)912 void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, struct bGPDframe *gpf_dst)
913 {
914   bGPDstroke *gps_dst = NULL;
915   /* error checking */
916   if ((gpf_src == NULL) || (gpf_dst == NULL)) {
917     return;
918   }
919 
920   /* copy strokes */
921   BLI_listbase_clear(&gpf_dst->strokes);
922   LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
923     /* make copy of source stroke */
924     gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true);
925     BLI_addtail(&gpf_dst->strokes, gps_dst);
926   }
927 }
928 
929 /**
930  * Make a copy of a given gpencil layer.
931  * \param gpl_src: Source grease pencil layer
932  * \return Pointer to new layer
933  */
BKE_gpencil_layer_duplicate(const bGPDlayer * gpl_src)934 bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src)
935 {
936   const bGPDframe *gpf_src;
937   bGPDframe *gpf_dst;
938   bGPDlayer *gpl_dst;
939 
940   /* error checking */
941   if (gpl_src == NULL) {
942     return NULL;
943   }
944 
945   /* make a copy of source layer */
946   gpl_dst = MEM_dupallocN(gpl_src);
947   gpl_dst->prev = gpl_dst->next = NULL;
948 
949   /* Copy masks. */
950   BLI_listbase_clear(&gpl_dst->mask_layers);
951   LISTBASE_FOREACH (bGPDlayer_Mask *, mask_src, &gpl_src->mask_layers) {
952     bGPDlayer_Mask *mask_dst = MEM_dupallocN(mask_src);
953     mask_dst->prev = mask_dst->next = NULL;
954     BLI_addtail(&gpl_dst->mask_layers, mask_dst);
955   }
956 
957   /* copy frames */
958   BLI_listbase_clear(&gpl_dst->frames);
959   for (gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) {
960     /* make a copy of source frame */
961     gpf_dst = BKE_gpencil_frame_duplicate(gpf_src);
962     BLI_addtail(&gpl_dst->frames, gpf_dst);
963 
964     /* if source frame was the current layer's 'active' frame, reassign that too */
965     if (gpf_src == gpl_dst->actframe) {
966       gpl_dst->actframe = gpf_dst;
967     }
968   }
969 
970   /* return new layer */
971   return gpl_dst;
972 }
973 
974 /**
975  * Make a copy of a given gpencil data-block.
976  *
977  * XXX: Should this be deprecated?
978  */
BKE_gpencil_data_duplicate(Main * bmain,const bGPdata * gpd_src,bool internal_copy)979 bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy)
980 {
981   bGPdata *gpd_dst;
982 
983   /* Yuck and super-uber-hyper yuck!!!
984    * Should be replaceable with a no-main copy (LIB_ID_COPY_NO_MAIN etc.), but not sure about it,
985    * so for now keep old code for that one. */
986 
987   /* error checking */
988   if (gpd_src == NULL) {
989     return NULL;
990   }
991 
992   if (internal_copy) {
993     /* make a straight copy for undo buffers used during stroke drawing */
994     gpd_dst = MEM_dupallocN(gpd_src);
995   }
996   else {
997     BLI_assert(bmain != NULL);
998     gpd_dst = (bGPdata *)BKE_id_copy(bmain, &gpd_src->id);
999   }
1000 
1001   /* Copy internal data (layers, etc.) */
1002   greasepencil_copy_data(bmain, &gpd_dst->id, &gpd_src->id, 0);
1003 
1004   /* return new */
1005   return gpd_dst;
1006 }
1007 
1008 /* ************************************************** */
1009 /* GP Stroke API */
1010 
1011 /**
1012  * Ensure selection status of stroke is in sync with its points.
1013  * \param gps: Grease pencil stroke
1014  */
BKE_gpencil_stroke_sync_selection(bGPDstroke * gps)1015 void BKE_gpencil_stroke_sync_selection(bGPDstroke *gps)
1016 {
1017   bGPDspoint *pt;
1018   int i;
1019 
1020   /* error checking */
1021   if (gps == NULL) {
1022     return;
1023   }
1024 
1025   /* we'll stop when we find the first selected point,
1026    * so initially, we must deselect
1027    */
1028   gps->flag &= ~GP_STROKE_SELECT;
1029 
1030   for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1031     if (pt->flag & GP_SPOINT_SELECT) {
1032       gps->flag |= GP_STROKE_SELECT;
1033       break;
1034     }
1035   }
1036 }
1037 
1038 /* ************************************************** */
1039 /* GP Frame API */
1040 
1041 /**
1042  * Delete the last stroke of the given frame.
1043  * \param gpl: Grease pencil layer
1044  * \param gpf: Grease pencil frame
1045  */
BKE_gpencil_frame_delete_laststroke(bGPDlayer * gpl,bGPDframe * gpf)1046 void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
1047 {
1048   bGPDstroke *gps = (gpf) ? gpf->strokes.last : NULL;
1049   int cfra = (gpf) ? gpf->framenum : 0; /* assume that the current frame was not locked */
1050 
1051   /* error checking */
1052   if (ELEM(NULL, gpf, gps)) {
1053     return;
1054   }
1055 
1056   /* free the stroke and its data */
1057   if (gps->points) {
1058     MEM_freeN(gps->points);
1059   }
1060   if (gps->dvert) {
1061     BKE_gpencil_free_stroke_weights(gps);
1062     MEM_freeN(gps->dvert);
1063   }
1064   MEM_freeN(gps->triangles);
1065   BLI_freelinkN(&gpf->strokes, gps);
1066 
1067   /* if frame has no strokes after this, delete it */
1068   if (BLI_listbase_is_empty(&gpf->strokes)) {
1069     BKE_gpencil_layer_frame_delete(gpl, gpf);
1070     BKE_gpencil_layer_frame_get(gpl, cfra, GP_GETFRAME_USE_PREV);
1071   }
1072 }
1073 
1074 /* ************************************************** */
1075 /* GP Layer API */
1076 
1077 /**
1078  * Check if the given layer is able to be edited or not.
1079  * \param gpl: Grease pencil layer
1080  * \return True if layer is editable
1081  */
BKE_gpencil_layer_is_editable(const bGPDlayer * gpl)1082 bool BKE_gpencil_layer_is_editable(const bGPDlayer *gpl)
1083 {
1084   /* Sanity check */
1085   if (gpl == NULL) {
1086     return false;
1087   }
1088 
1089   /* Layer must be: Visible + Editable */
1090   if ((gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) == 0) {
1091     return true;
1092   }
1093 
1094   /* Something failed */
1095   return false;
1096 }
1097 
1098 /**
1099  * Look up the gp-frame on the requested frame number, but don't add a new one.
1100  * \param gpl: Grease pencil layer
1101  * \param cframe: Frame number
1102  * \return Pointer to frame
1103  */
BKE_gpencil_layer_frame_find(bGPDlayer * gpl,int cframe)1104 bGPDframe *BKE_gpencil_layer_frame_find(bGPDlayer *gpl, int cframe)
1105 {
1106   bGPDframe *gpf;
1107 
1108   /* Search in reverse order, since this is often used for playback/adding,
1109    * where it's less likely that we're interested in the earlier frames
1110    */
1111   for (gpf = gpl->frames.last; gpf; gpf = gpf->prev) {
1112     if (gpf->framenum == cframe) {
1113       return gpf;
1114     }
1115   }
1116 
1117   return NULL;
1118 }
1119 
1120 /** Get the appropriate gp-frame from a given layer
1121  * - this sets the layer's actframe var (if allowed to)
1122  * - extension beyond range (if first gp-frame is after all frame in interest and cannot add)
1123  *
1124  * \param gpl: Grease pencil layer
1125  * \param cframe: Frame number
1126  * \param addnew: Add option
1127  * \return Pointer to new frame
1128  */
BKE_gpencil_layer_frame_get(bGPDlayer * gpl,int cframe,eGP_GetFrame_Mode addnew)1129 bGPDframe *BKE_gpencil_layer_frame_get(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
1130 {
1131   bGPDframe *gpf = NULL;
1132   bool found = false;
1133 
1134   /* error checking */
1135   if (gpl == NULL) {
1136     return NULL;
1137   }
1138 
1139   /* check if there is already an active frame */
1140   if (gpl->actframe) {
1141     gpf = gpl->actframe;
1142 
1143     /* do not allow any changes to layer's active frame if layer is locked from changes
1144      * or if the layer has been set to stay on the current frame
1145      */
1146     if (gpl->flag & GP_LAYER_FRAMELOCK) {
1147       return gpf;
1148     }
1149     /* do not allow any changes to actframe if frame has painting tag attached to it */
1150     if (gpf->flag & GP_FRAME_PAINT) {
1151       return gpf;
1152     }
1153 
1154     /* try to find matching frame */
1155     if (gpf->framenum < cframe) {
1156       for (; gpf; gpf = gpf->next) {
1157         if (gpf->framenum == cframe) {
1158           found = true;
1159           break;
1160         }
1161         if ((gpf->next) && (gpf->next->framenum > cframe)) {
1162           found = true;
1163           break;
1164         }
1165       }
1166 
1167       /* set the appropriate frame */
1168       if (addnew) {
1169         if ((found) && (gpf->framenum == cframe)) {
1170           gpl->actframe = gpf;
1171         }
1172         else if (addnew == GP_GETFRAME_ADD_COPY) {
1173           gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe);
1174         }
1175         else {
1176           gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
1177         }
1178       }
1179       else if (found) {
1180         gpl->actframe = gpf;
1181       }
1182       else {
1183         gpl->actframe = gpl->frames.last;
1184       }
1185     }
1186     else {
1187       for (; gpf; gpf = gpf->prev) {
1188         if (gpf->framenum <= cframe) {
1189           found = true;
1190           break;
1191         }
1192       }
1193 
1194       /* set the appropriate frame */
1195       if (addnew) {
1196         if ((found) && (gpf->framenum == cframe)) {
1197           gpl->actframe = gpf;
1198         }
1199         else if (addnew == GP_GETFRAME_ADD_COPY) {
1200           gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe);
1201         }
1202         else {
1203           gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
1204         }
1205       }
1206       else if (found) {
1207         gpl->actframe = gpf;
1208       }
1209       else {
1210         gpl->actframe = gpl->frames.first;
1211       }
1212     }
1213   }
1214   else if (gpl->frames.first) {
1215     /* check which of the ends to start checking from */
1216     const int first = ((bGPDframe *)(gpl->frames.first))->framenum;
1217     const int last = ((bGPDframe *)(gpl->frames.last))->framenum;
1218 
1219     if (abs(cframe - first) > abs(cframe - last)) {
1220       /* find gp-frame which is less than or equal to cframe */
1221       for (gpf = gpl->frames.last; gpf; gpf = gpf->prev) {
1222         if (gpf->framenum <= cframe) {
1223           found = true;
1224           break;
1225         }
1226       }
1227     }
1228     else {
1229       /* find gp-frame which is less than or equal to cframe */
1230       for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1231         if (gpf->framenum <= cframe) {
1232           found = true;
1233           break;
1234         }
1235       }
1236     }
1237 
1238     /* set the appropriate frame */
1239     if (addnew) {
1240       if ((found) && (gpf->framenum == cframe)) {
1241         gpl->actframe = gpf;
1242       }
1243       else {
1244         gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
1245       }
1246     }
1247     else if (found) {
1248       gpl->actframe = gpf;
1249     }
1250     else {
1251       /* If delete first frame, need to find one. */
1252       if (gpl->frames.first != NULL) {
1253         gpl->actframe = gpl->frames.first;
1254       }
1255       else {
1256         /* unresolved errogenous situation! */
1257         CLOG_STR_ERROR(&LOG, "cannot find appropriate gp-frame");
1258         /* gpl->actframe should still be NULL */
1259       }
1260     }
1261   }
1262   else {
1263     /* currently no frames (add if allowed to) */
1264     if (addnew) {
1265       gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
1266     }
1267     else {
1268       /* don't do anything... this may be when no frames yet! */
1269       /* gpl->actframe should still be NULL */
1270     }
1271   }
1272 
1273   /* Don't select first frame if greater than current frame. */
1274   if ((gpl->actframe != NULL) && (gpl->actframe == gpl->frames.first) &&
1275       (gpl->actframe->framenum > cframe)) {
1276     gpl->actframe = NULL;
1277   }
1278 
1279   /* return */
1280   return gpl->actframe;
1281 }
1282 
1283 /**
1284  * Delete the given frame from a layer.
1285  * \param gpl: Grease pencil layer
1286  * \param gpf: Grease pencil frame
1287  * \return True if delete was done
1288  */
BKE_gpencil_layer_frame_delete(bGPDlayer * gpl,bGPDframe * gpf)1289 bool BKE_gpencil_layer_frame_delete(bGPDlayer *gpl, bGPDframe *gpf)
1290 {
1291   bool changed = false;
1292 
1293   /* error checking */
1294   if (ELEM(NULL, gpl, gpf)) {
1295     return false;
1296   }
1297 
1298   /* if this frame was active, make the previous frame active instead
1299    * since it's tricky to set active frame otherwise
1300    */
1301   if (gpl->actframe == gpf) {
1302     gpl->actframe = gpf->prev;
1303   }
1304 
1305   /* free the frame and its data */
1306   changed = BKE_gpencil_free_strokes(gpf);
1307   BLI_freelinkN(&gpl->frames, gpf);
1308 
1309   return changed;
1310 }
1311 
1312 /**
1313  * Get layer by name
1314  * \param gpd: Grease pencil data-block
1315  * \param name: Layer name
1316  * \return Pointer to layer
1317  */
BKE_gpencil_layer_named_get(bGPdata * gpd,const char * name)1318 bGPDlayer *BKE_gpencil_layer_named_get(bGPdata *gpd, const char *name)
1319 {
1320   if (name[0] == '\0') {
1321     return NULL;
1322   }
1323   return BLI_findstring(&gpd->layers, name, offsetof(bGPDlayer, info));
1324 }
1325 
1326 /**
1327  * Get mask layer by name.
1328  * \param gpl: Grease pencil layer
1329  * \param name: Mask name
1330  * \return Pointer to mask layer
1331  */
BKE_gpencil_layer_mask_named_get(bGPDlayer * gpl,const char * name)1332 bGPDlayer_Mask *BKE_gpencil_layer_mask_named_get(bGPDlayer *gpl, const char *name)
1333 {
1334   if (name[0] == '\0') {
1335     return NULL;
1336   }
1337   return BLI_findstring(&gpl->mask_layers, name, offsetof(bGPDlayer_Mask, name));
1338 }
1339 
1340 /**
1341  * Add grease pencil mask layer.
1342  * \param gpl: Grease pencil layer
1343  * \param name: Name of the mask
1344  * \return Pointer to new mask layer
1345  */
BKE_gpencil_layer_mask_add(bGPDlayer * gpl,const char * name)1346 bGPDlayer_Mask *BKE_gpencil_layer_mask_add(bGPDlayer *gpl, const char *name)
1347 {
1348 
1349   bGPDlayer_Mask *mask = MEM_callocN(sizeof(bGPDlayer_Mask), "bGPDlayer_Mask");
1350   BLI_addtail(&gpl->mask_layers, mask);
1351   BLI_strncpy(mask->name, name, sizeof(mask->name));
1352   gpl->act_mask++;
1353 
1354   return mask;
1355 }
1356 
1357 /**
1358  * Remove grease pencil mask layer.
1359  * \param gpl: Grease pencil layer
1360  * \param mask: Grease pencil mask layer
1361  */
BKE_gpencil_layer_mask_remove(bGPDlayer * gpl,bGPDlayer_Mask * mask)1362 void BKE_gpencil_layer_mask_remove(bGPDlayer *gpl, bGPDlayer_Mask *mask)
1363 {
1364   BLI_freelinkN(&gpl->mask_layers, mask);
1365   gpl->act_mask--;
1366   CLAMP_MIN(gpl->act_mask, 0);
1367 }
1368 
1369 /**
1370  * Remove any reference to mask layer.
1371  * \param gpd: Grease pencil data-block
1372  * \param name: Name of the mask layer
1373  */
BKE_gpencil_layer_mask_remove_ref(bGPdata * gpd,const char * name)1374 void BKE_gpencil_layer_mask_remove_ref(bGPdata *gpd, const char *name)
1375 {
1376   bGPDlayer_Mask *mask_next;
1377 
1378   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1379     for (bGPDlayer_Mask *mask = gpl->mask_layers.first; mask; mask = mask_next) {
1380       mask_next = mask->next;
1381       if (STREQ(mask->name, name)) {
1382         BKE_gpencil_layer_mask_remove(gpl, mask);
1383       }
1384     }
1385   }
1386 }
1387 
gpencil_cb_sort_masks(const void * arg1,const void * arg2)1388 static int gpencil_cb_sort_masks(const void *arg1, const void *arg2)
1389 {
1390   /* sort is inverted as layer list. */
1391   const struct bGPDlayer_Mask *mask1 = arg1;
1392   const struct bGPDlayer_Mask *mask2 = arg2;
1393   int val = 0;
1394 
1395   if (mask1->sort_index < mask2->sort_index) {
1396     val = 1;
1397   }
1398   else if (mask1->sort_index > mask2->sort_index) {
1399     val = -1;
1400   }
1401 
1402   return val;
1403 }
1404 
1405 /**
1406  * Sort grease pencil mask layers.
1407  * \param gpd: Grease pencil data-block
1408  * \param gpl: Grease pencil layer
1409  */
BKE_gpencil_layer_mask_sort(bGPdata * gpd,bGPDlayer * gpl)1410 void BKE_gpencil_layer_mask_sort(bGPdata *gpd, bGPDlayer *gpl)
1411 {
1412   /* Update sort index. */
1413   LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl->mask_layers) {
1414     bGPDlayer *gpl_mask = BKE_gpencil_layer_named_get(gpd, mask->name);
1415     if (gpl_mask != NULL) {
1416       mask->sort_index = BLI_findindex(&gpd->layers, gpl_mask);
1417     }
1418     else {
1419       mask->sort_index = 0;
1420     }
1421   }
1422   BLI_listbase_sort(&gpl->mask_layers, gpencil_cb_sort_masks);
1423 }
1424 
1425 /**
1426  * Sort all grease pencil mask layer.
1427  * \param gpd: Grease pencil data-block
1428  */
BKE_gpencil_layer_mask_sort_all(bGPdata * gpd)1429 void BKE_gpencil_layer_mask_sort_all(bGPdata *gpd)
1430 {
1431   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1432     BKE_gpencil_layer_mask_sort(gpd, gpl);
1433   }
1434 }
1435 
gpencil_cb_cmp_frame(void * thunk,const void * a,const void * b)1436 static int gpencil_cb_cmp_frame(void *thunk, const void *a, const void *b)
1437 {
1438   const bGPDframe *frame_a = a;
1439   const bGPDframe *frame_b = b;
1440 
1441   if (frame_a->framenum < frame_b->framenum) {
1442     return -1;
1443   }
1444   if (frame_a->framenum > frame_b->framenum) {
1445     return 1;
1446   }
1447   if (thunk != NULL) {
1448     *((bool *)thunk) = true;
1449   }
1450   /* Sort selected last. */
1451   if ((frame_a->flag & GP_FRAME_SELECT) && ((frame_b->flag & GP_FRAME_SELECT) == 0)) {
1452     return 1;
1453   }
1454   return 0;
1455 }
1456 
1457 /**
1458  * Sort grease pencil frames.
1459  * \param gpl: Grease pencil layer
1460  * \param r_has_duplicate_frames: Duplicated frames flag
1461  */
BKE_gpencil_layer_frames_sort(struct bGPDlayer * gpl,bool * r_has_duplicate_frames)1462 void BKE_gpencil_layer_frames_sort(struct bGPDlayer *gpl, bool *r_has_duplicate_frames)
1463 {
1464   BLI_listbase_sort_r(&gpl->frames, gpencil_cb_cmp_frame, r_has_duplicate_frames);
1465 }
1466 
1467 /**
1468  * Get the active grease pencil layer for editing.
1469  * \param gpd: Grease pencil data-block
1470  * \return Pointer to layer
1471  */
BKE_gpencil_layer_active_get(bGPdata * gpd)1472 bGPDlayer *BKE_gpencil_layer_active_get(bGPdata *gpd)
1473 {
1474   /* error checking */
1475   if (ELEM(NULL, gpd, gpd->layers.first)) {
1476     return NULL;
1477   }
1478 
1479   /* loop over layers until found (assume only one active) */
1480   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1481     if (gpl->flag & GP_LAYER_ACTIVE) {
1482       return gpl;
1483     }
1484   }
1485 
1486   /* no active layer found */
1487   return NULL;
1488 }
1489 
1490 /**
1491  * Set active grease pencil layer.
1492  * \param gpd: Grease pencil data-block
1493  * \param active: Grease pencil layer to set as active
1494  */
BKE_gpencil_layer_active_set(bGPdata * gpd,bGPDlayer * active)1495 void BKE_gpencil_layer_active_set(bGPdata *gpd, bGPDlayer *active)
1496 {
1497   /* error checking */
1498   if (ELEM(NULL, gpd, gpd->layers.first, active)) {
1499     return;
1500   }
1501 
1502   /* loop over layers deactivating all */
1503   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1504     gpl->flag &= ~GP_LAYER_ACTIVE;
1505     if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
1506       gpl->flag |= GP_LAYER_LOCKED;
1507     }
1508   }
1509 
1510   /* set as active one */
1511   active->flag |= GP_LAYER_ACTIVE;
1512   if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
1513     active->flag &= ~GP_LAYER_LOCKED;
1514   }
1515 }
1516 
1517 /**
1518  * Set locked layers for autolock mode.
1519  * \param gpd: Grease pencil data-block
1520  * \param unlock: Unlock flag
1521  */
BKE_gpencil_layer_autolock_set(bGPdata * gpd,const bool unlock)1522 void BKE_gpencil_layer_autolock_set(bGPdata *gpd, const bool unlock)
1523 {
1524   BLI_assert(gpd != NULL);
1525 
1526   if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
1527     bGPDlayer *layer_active = BKE_gpencil_layer_active_get(gpd);
1528 
1529     /* Lock all other layers */
1530     LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1531       /* unlock active layer */
1532       if (gpl == layer_active) {
1533         gpl->flag &= ~GP_LAYER_LOCKED;
1534       }
1535       else {
1536         gpl->flag |= GP_LAYER_LOCKED;
1537       }
1538     }
1539   }
1540   else {
1541     /* If disable is better unlock all layers by default or it looks there is
1542      * a problem in the UI because the user expects all layers will be unlocked
1543      */
1544     if (unlock) {
1545       LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1546         gpl->flag &= ~GP_LAYER_LOCKED;
1547       }
1548     }
1549   }
1550 }
1551 
1552 /**
1553  * Delete grease pencil layer.
1554  * \param gpd: Grease pencil data-block
1555  * \param gpl: Grease pencil layer
1556  */
BKE_gpencil_layer_delete(bGPdata * gpd,bGPDlayer * gpl)1557 void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl)
1558 {
1559   /* error checking */
1560   if (ELEM(NULL, gpd, gpl)) {
1561     return;
1562   }
1563 
1564   /* free layer */
1565   BKE_gpencil_free_frames(gpl);
1566 
1567   /* Free Masks. */
1568   BKE_gpencil_free_layer_masks(gpl);
1569 
1570   /* Remove any reference to that layer in masking lists. */
1571   BKE_gpencil_layer_mask_remove_ref(gpd, gpl->info);
1572 
1573   /* free icon providing preview of icon color */
1574   BKE_icon_delete(gpl->runtime.icon_id);
1575 
1576   BLI_freelinkN(&gpd->layers, gpl);
1577 }
1578 
1579 /**
1580  * Get grease pencil material from brush.
1581  * \param brush: Brush
1582  * \return Pointer to material
1583  */
BKE_gpencil_brush_material_get(Brush * brush)1584 Material *BKE_gpencil_brush_material_get(Brush *brush)
1585 {
1586   Material *ma = NULL;
1587 
1588   if ((brush != NULL) && (brush->gpencil_settings != NULL) &&
1589       (brush->gpencil_settings->material != NULL)) {
1590     ma = brush->gpencil_settings->material;
1591   }
1592 
1593   return ma;
1594 }
1595 
1596 /**
1597  * Set grease pencil brush material.
1598  * \param brush: Brush
1599  * \param ma: Material
1600  */
BKE_gpencil_brush_material_set(Brush * brush,Material * ma)1601 void BKE_gpencil_brush_material_set(Brush *brush, Material *ma)
1602 {
1603   BLI_assert(brush);
1604   BLI_assert(brush->gpencil_settings);
1605   if (brush->gpencil_settings->material != ma) {
1606     if (brush->gpencil_settings->material) {
1607       id_us_min(&brush->gpencil_settings->material->id);
1608     }
1609     if (ma) {
1610       id_us_plus(&ma->id);
1611     }
1612     brush->gpencil_settings->material = ma;
1613   }
1614 }
1615 
1616 /**
1617  * Adds the pinned material to the object if necessary.
1618  * \param bmain: Main pointer
1619  * \param ob: Grease pencil object
1620  * \param brush: Brush
1621  * \return Pointer to material
1622  */
BKE_gpencil_object_material_ensure_from_brush(Main * bmain,Object * ob,Brush * brush)1623 Material *BKE_gpencil_object_material_ensure_from_brush(Main *bmain, Object *ob, Brush *brush)
1624 {
1625   if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) {
1626     Material *ma = BKE_gpencil_brush_material_get(brush);
1627 
1628     /* check if the material is already on object material slots and add it if missing */
1629     if (ma && BKE_gpencil_object_material_index_get(ob, ma) < 0) {
1630       BKE_object_material_slot_add(bmain, ob);
1631       BKE_object_material_assign(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
1632     }
1633 
1634     return ma;
1635   }
1636 
1637   /* using active material instead */
1638   return BKE_object_material_get(ob, ob->actcol);
1639 }
1640 
1641 /**
1642  * Assigns the material to object (if not already present) and returns its index (mat_nr).
1643  * \param bmain: Main pointer
1644  * \param ob: Grease pencil object
1645  * \param material: Material
1646  * \return Index of the material
1647  */
BKE_gpencil_object_material_ensure(Main * bmain,Object * ob,Material * material)1648 int BKE_gpencil_object_material_ensure(Main *bmain, Object *ob, Material *material)
1649 {
1650   if (!material) {
1651     return -1;
1652   }
1653   int index = BKE_gpencil_object_material_index_get(ob, material);
1654   if (index < 0) {
1655     BKE_object_material_slot_add(bmain, ob);
1656     BKE_object_material_assign(bmain, ob, material, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
1657     return ob->totcol - 1;
1658   }
1659   return index;
1660 }
1661 
1662 /**
1663  * Creates a new grease-pencil material and assigns it to object.
1664  * \param bmain: Main pointer
1665  * \param ob: Grease pencil object
1666  * \param name: Material name
1667  * \param r_index: value is set to zero based index of the new material if \a r_index is not NULL.
1668  * \return Material pointer.
1669  */
BKE_gpencil_object_material_new(Main * bmain,Object * ob,const char * name,int * r_index)1670 Material *BKE_gpencil_object_material_new(Main *bmain, Object *ob, const char *name, int *r_index)
1671 {
1672   Material *ma = BKE_gpencil_material_add(bmain, name);
1673   id_us_min(&ma->id); /* no users yet */
1674 
1675   BKE_object_material_slot_add(bmain, ob);
1676   BKE_object_material_assign(bmain, ob, ma, ob->totcol, BKE_MAT_ASSIGN_USERPREF);
1677 
1678   if (r_index) {
1679     *r_index = ob->actcol - 1;
1680   }
1681   return ma;
1682 }
1683 
1684 /**
1685  * Returns the material for a brush with respect to its pinned state.
1686  * \param ob: Grease pencil object
1687  * \param brush: Brush
1688  * \return Material pointer
1689  */
BKE_gpencil_object_material_from_brush_get(Object * ob,Brush * brush)1690 Material *BKE_gpencil_object_material_from_brush_get(Object *ob, Brush *brush)
1691 {
1692   if ((brush) && (brush->gpencil_settings) &&
1693       (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED)) {
1694     Material *ma = BKE_gpencil_brush_material_get(brush);
1695     return ma;
1696   }
1697 
1698   return BKE_object_material_get(ob, ob->actcol);
1699 }
1700 
1701 /**
1702  * Returns the material index for a brush with respect to its pinned state.
1703  * \param ob: Grease pencil object
1704  * \param brush: Brush
1705  * \return Material index.
1706  */
BKE_gpencil_object_material_get_index_from_brush(Object * ob,Brush * brush)1707 int BKE_gpencil_object_material_get_index_from_brush(Object *ob, Brush *brush)
1708 {
1709   if ((brush) && (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED)) {
1710     return BKE_gpencil_object_material_index_get(ob, brush->gpencil_settings->material);
1711   }
1712 
1713   return ob->actcol - 1;
1714 }
1715 
1716 /**
1717  * Guaranteed to return a material assigned to object. Returns never NULL.
1718  * \param bmain: Main pointer
1719  * \param ob: Grease pencil object
1720  * \return Material pointer.
1721  */
BKE_gpencil_object_material_ensure_from_active_input_toolsettings(Main * bmain,Object * ob,ToolSettings * ts)1722 Material *BKE_gpencil_object_material_ensure_from_active_input_toolsettings(Main *bmain,
1723                                                                             Object *ob,
1724                                                                             ToolSettings *ts)
1725 {
1726   if (ts && ts->gp_paint && ts->gp_paint->paint.brush) {
1727     return BKE_gpencil_object_material_ensure_from_active_input_brush(
1728         bmain, ob, ts->gp_paint->paint.brush);
1729   }
1730 
1731   return BKE_gpencil_object_material_ensure_from_active_input_brush(bmain, ob, NULL);
1732 }
1733 
1734 /**
1735  * Guaranteed to return a material assigned to object. Returns never NULL.
1736  * \param bmain: Main pointer
1737  * \param ob: Grease pencil object.
1738  * \param brush: Brush
1739  * \return Material pointer
1740  */
BKE_gpencil_object_material_ensure_from_active_input_brush(Main * bmain,Object * ob,Brush * brush)1741 Material *BKE_gpencil_object_material_ensure_from_active_input_brush(Main *bmain,
1742                                                                      Object *ob,
1743                                                                      Brush *brush)
1744 {
1745   if (brush) {
1746     Material *ma = BKE_gpencil_object_material_ensure_from_brush(bmain, ob, brush);
1747     if (ma) {
1748       return ma;
1749     }
1750     if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) {
1751       /* it is easier to just unpin a NULL material, instead of setting a new one */
1752       brush->gpencil_settings->flag &= ~GP_BRUSH_MATERIAL_PINNED;
1753     }
1754   }
1755   return BKE_gpencil_object_material_ensure_from_active_input_material(ob);
1756 }
1757 
1758 /**
1759  * Guaranteed to return a material assigned to object. Returns never NULL.
1760  * Only use this for materials unrelated to user input.
1761  * \param ob: Grease pencil object
1762  * \return Material pointer
1763  */
BKE_gpencil_object_material_ensure_from_active_input_material(Object * ob)1764 Material *BKE_gpencil_object_material_ensure_from_active_input_material(Object *ob)
1765 {
1766   Material *ma = BKE_object_material_get(ob, ob->actcol);
1767   if (ma) {
1768     return ma;
1769   }
1770 
1771   return BKE_material_default_gpencil();
1772 }
1773 
1774 /**
1775  * Get active color, and add all default settings if we don't find anything.
1776  * \param ob: Grease pencil object
1777  * \return Material pointer
1778  */
BKE_gpencil_object_material_ensure_active(Object * ob)1779 Material *BKE_gpencil_object_material_ensure_active(Object *ob)
1780 {
1781   Material *ma = NULL;
1782 
1783   /* sanity checks */
1784   if (ob == NULL) {
1785     return NULL;
1786   }
1787 
1788   ma = BKE_gpencil_object_material_ensure_from_active_input_material(ob);
1789   if (ma->gp_style == NULL) {
1790     BKE_gpencil_material_attr_init(ma);
1791   }
1792 
1793   return ma;
1794 }
1795 
1796 /* ************************************************** */
1797 /**
1798  * Check if stroke has any point selected
1799  * \param gps: Grease pencil stroke
1800  * \return True if selected
1801  */
BKE_gpencil_stroke_select_check(const bGPDstroke * gps)1802 bool BKE_gpencil_stroke_select_check(const bGPDstroke *gps)
1803 {
1804   const bGPDspoint *pt;
1805   int i;
1806   for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1807     if (pt->flag & GP_SPOINT_SELECT) {
1808       return true;
1809     }
1810   }
1811   return false;
1812 }
1813 
1814 /* ************************************************** */
1815 /* GP Object - Vertex Groups */
1816 
1817 /**
1818  * Remove a vertex group.
1819  * \param ob: Grease pencil object
1820  * \param defgroup: deform group
1821  */
BKE_gpencil_vgroup_remove(Object * ob,bDeformGroup * defgroup)1822 void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup)
1823 {
1824   bGPdata *gpd = ob->data;
1825   MDeformVert *dvert = NULL;
1826   const int def_nr = BLI_findindex(&ob->defbase, defgroup);
1827   const int totgrp = BLI_listbase_count(&ob->defbase);
1828 
1829   /* Remove points data */
1830   if (gpd) {
1831     LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1832       LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
1833         LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
1834           if (gps->dvert != NULL) {
1835             for (int i = 0; i < gps->totpoints; i++) {
1836               dvert = &gps->dvert[i];
1837               MDeformWeight *dw = BKE_defvert_find_index(dvert, def_nr);
1838               if (dw != NULL) {
1839                 BKE_defvert_remove_group(dvert, dw);
1840               }
1841               /* Reorganize weights for other groups after deleted one. */
1842               for (int g = 0; g < totgrp; g++) {
1843                 dw = BKE_defvert_find_index(dvert, g);
1844                 if ((dw != NULL) && (dw->def_nr > def_nr)) {
1845                   dw->def_nr--;
1846                 }
1847               }
1848             }
1849           }
1850         }
1851       }
1852     }
1853   }
1854 
1855   /* Remove the group */
1856   BLI_freelinkN(&ob->defbase, defgroup);
1857   DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1858 }
1859 
1860 /**
1861  * Ensure stroke has vertex group.
1862  * \param gps: Grease pencil stroke
1863  */
BKE_gpencil_dvert_ensure(bGPDstroke * gps)1864 void BKE_gpencil_dvert_ensure(bGPDstroke *gps)
1865 {
1866   if (gps->dvert == NULL) {
1867     gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
1868   }
1869 }
1870 
1871 /* ************************************************** */
1872 
1873 /**
1874  * Get range of selected frames in layer.
1875  * Always the active frame is considered as selected, so if no more selected the range
1876  * will be equal to the current active frame.
1877  * \param gpl: Layer.
1878  * \param r_initframe: Number of first selected frame.
1879  * \param r_endframe: Number of last selected frame.
1880  */
BKE_gpencil_frame_range_selected(bGPDlayer * gpl,int * r_initframe,int * r_endframe)1881 void BKE_gpencil_frame_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_endframe)
1882 {
1883   *r_initframe = gpl->actframe->framenum;
1884   *r_endframe = gpl->actframe->framenum;
1885 
1886   LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
1887     if (gpf->flag & GP_FRAME_SELECT) {
1888       if (gpf->framenum < *r_initframe) {
1889         *r_initframe = gpf->framenum;
1890       }
1891       if (gpf->framenum > *r_endframe) {
1892         *r_endframe = gpf->framenum;
1893       }
1894     }
1895   }
1896 }
1897 
1898 /**
1899  * Get Falloff factor base on frame range
1900  * \param gpf: Frame.
1901  * \param actnum: Number of active frame in layer.
1902  * \param f_init: Number of first selected frame.
1903  * \param f_end: Number of last selected frame.
1904  * \param cur_falloff: Curve with falloff factors.
1905  */
BKE_gpencil_multiframe_falloff_calc(bGPDframe * gpf,int actnum,int f_init,int f_end,CurveMapping * cur_falloff)1906 float BKE_gpencil_multiframe_falloff_calc(
1907     bGPDframe *gpf, int actnum, int f_init, int f_end, CurveMapping *cur_falloff)
1908 {
1909   float fnum = 0.5f; /* default mid curve */
1910   float value;
1911 
1912   /* check curve is available */
1913   if (cur_falloff == NULL) {
1914     return 1.0f;
1915   }
1916 
1917   /* frames to the right of the active frame */
1918   if (gpf->framenum < actnum) {
1919     fnum = (float)(gpf->framenum - f_init) / (actnum - f_init);
1920     fnum *= 0.5f;
1921     value = BKE_curvemapping_evaluateF(cur_falloff, 0, fnum);
1922   }
1923   /* frames to the left of the active frame */
1924   else if (gpf->framenum > actnum) {
1925     fnum = (float)(gpf->framenum - actnum) / (f_end - actnum);
1926     fnum *= 0.5f;
1927     value = BKE_curvemapping_evaluateF(cur_falloff, 0, fnum + 0.5f);
1928   }
1929   else {
1930     /* Center of the curve. */
1931     value = BKE_curvemapping_evaluateF(cur_falloff, 0, 0.5f);
1932   }
1933 
1934   return value;
1935 }
1936 
1937 /**
1938  * Reassign strokes using a material.
1939  * \param gpd: Grease pencil data-block
1940  * \param totcol: Total materials
1941  * \param index: Index of the material
1942  */
BKE_gpencil_material_index_reassign(bGPdata * gpd,int totcol,int index)1943 void BKE_gpencil_material_index_reassign(bGPdata *gpd, int totcol, int index)
1944 {
1945   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1946     LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
1947       LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
1948         /* reassign strokes */
1949         if ((gps->mat_nr > index) || (gps->mat_nr > totcol - 1)) {
1950           gps->mat_nr--;
1951           CLAMP_MIN(gps->mat_nr, 0);
1952         }
1953       }
1954     }
1955   }
1956 }
1957 
1958 /**
1959  * Remove strokes using a material.
1960  * \param gpd: Grease pencil data-block
1961  * \param index: Index of the material
1962  * \return True if removed
1963  */
BKE_gpencil_material_index_used(bGPdata * gpd,int index)1964 bool BKE_gpencil_material_index_used(bGPdata *gpd, int index)
1965 {
1966   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1967     LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
1968       LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
1969         if (gps->mat_nr == index) {
1970           return true;
1971         }
1972       }
1973     }
1974   }
1975 
1976   return false;
1977 }
1978 
1979 /**
1980  * Remap material
1981  * \param gpd: Grease pencil data-block
1982  * \param remap: Remap index
1983  * \param remap_len: Remap length
1984  */
BKE_gpencil_material_remap(struct bGPdata * gpd,const unsigned int * remap,unsigned int remap_len)1985 void BKE_gpencil_material_remap(struct bGPdata *gpd,
1986                                 const unsigned int *remap,
1987                                 unsigned int remap_len)
1988 {
1989   const short remap_len_short = (short)remap_len;
1990 
1991 #define MAT_NR_REMAP(n) \
1992   if (n < remap_len_short) { \
1993     BLI_assert(n >= 0 && remap[n] < remap_len_short); \
1994     n = remap[n]; \
1995   } \
1996   ((void)0)
1997 
1998   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1999     LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2000       LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
2001         /* reassign strokes */
2002         MAT_NR_REMAP(gps->mat_nr);
2003       }
2004     }
2005   }
2006 
2007 #undef MAT_NR_REMAP
2008 }
2009 
2010 /**
2011  * Load a table with material conversion index for merged materials.
2012  * \param ob: Grease pencil object
2013  * \param hue_threshold: Threshold for Hue
2014  * \param sat_threshold: Threshold for Saturation
2015  * \param val_threshold: Threshold for Value
2016  * \param r_mat_table : return material table
2017  * \return True if done
2018  */
BKE_gpencil_merge_materials_table_get(Object * ob,const float hue_threshold,const float sat_threshold,const float val_threshold,GHash * r_mat_table)2019 bool BKE_gpencil_merge_materials_table_get(Object *ob,
2020                                            const float hue_threshold,
2021                                            const float sat_threshold,
2022                                            const float val_threshold,
2023                                            GHash *r_mat_table)
2024 {
2025   bool changed = false;
2026 
2027   Material *ma_primary = NULL;
2028   Material *ma_secondary = NULL;
2029   MaterialGPencilStyle *gp_style_primary = NULL;
2030   MaterialGPencilStyle *gp_style_secondary = NULL;
2031   GHash *mat_used = BLI_ghash_int_new(__func__);
2032 
2033   short *totcol = BKE_object_material_len_p(ob);
2034   if (totcol == 0) {
2035     return changed;
2036   }
2037 
2038   for (int idx_primary = 0; idx_primary < *totcol; idx_primary++) {
2039     /* Read primary material to compare. */
2040     ma_primary = BKE_gpencil_material(ob, idx_primary + 1);
2041     if (ma_primary == NULL) {
2042       continue;
2043     }
2044     for (int idx_secondary = 0; idx_secondary < *totcol; idx_secondary++) {
2045       if ((idx_secondary == idx_primary) ||
2046           BLI_ghash_haskey(r_mat_table, POINTER_FROM_INT(idx_secondary))) {
2047         continue;
2048       }
2049       if (BLI_ghash_haskey(mat_used, POINTER_FROM_INT(idx_secondary))) {
2050         continue;
2051       }
2052 
2053       /* Read secondary material to compare with primary material. */
2054       ma_secondary = BKE_gpencil_material(ob, idx_secondary + 1);
2055       if ((ma_secondary == NULL) ||
2056           (BLI_ghash_haskey(r_mat_table, POINTER_FROM_INT(idx_secondary)))) {
2057         continue;
2058       }
2059       gp_style_primary = ma_primary->gp_style;
2060       gp_style_secondary = ma_secondary->gp_style;
2061 
2062       if ((gp_style_primary == NULL) || (gp_style_secondary == NULL) ||
2063           (gp_style_secondary->flag & GP_MATERIAL_LOCKED)) {
2064         continue;
2065       }
2066 
2067       /* Check materials have the same mode. */
2068       if (gp_style_primary->mode != gp_style_secondary->mode) {
2069         continue;
2070       }
2071 
2072       /* Check materials have same stroke and fill attributes. */
2073       if ((gp_style_primary->flag & GP_MATERIAL_STROKE_SHOW) !=
2074           (gp_style_secondary->flag & GP_MATERIAL_STROKE_SHOW)) {
2075         continue;
2076       }
2077 
2078       if ((gp_style_primary->flag & GP_MATERIAL_FILL_SHOW) !=
2079           (gp_style_secondary->flag & GP_MATERIAL_FILL_SHOW)) {
2080         continue;
2081       }
2082 
2083       /* Check materials have the same type. */
2084       if ((gp_style_primary->stroke_style != gp_style_secondary->stroke_style) ||
2085           (gp_style_primary->fill_style != gp_style_secondary->fill_style)) {
2086         continue;
2087       }
2088 
2089       float s_hsv_a[3], s_hsv_b[3], f_hsv_a[3], f_hsv_b[3], col[3];
2090       zero_v3(s_hsv_a);
2091       zero_v3(s_hsv_b);
2092       zero_v3(f_hsv_a);
2093       zero_v3(f_hsv_b);
2094 
2095       copy_v3_v3(col, gp_style_primary->stroke_rgba);
2096       rgb_to_hsv_compat_v(col, s_hsv_a);
2097       copy_v3_v3(col, gp_style_secondary->stroke_rgba);
2098       rgb_to_hsv_compat_v(col, s_hsv_b);
2099 
2100       copy_v3_v3(col, gp_style_primary->fill_rgba);
2101       rgb_to_hsv_compat_v(col, f_hsv_a);
2102       copy_v3_v3(col, gp_style_secondary->fill_rgba);
2103       rgb_to_hsv_compat_v(col, f_hsv_b);
2104 
2105       /* Check stroke and fill color. */
2106       if ((!compare_ff(s_hsv_a[0], s_hsv_b[0], hue_threshold)) ||
2107           (!compare_ff(s_hsv_a[1], s_hsv_b[1], sat_threshold)) ||
2108           (!compare_ff(s_hsv_a[2], s_hsv_b[2], val_threshold)) ||
2109           (!compare_ff(f_hsv_a[0], f_hsv_b[0], hue_threshold)) ||
2110           (!compare_ff(f_hsv_a[1], f_hsv_b[1], sat_threshold)) ||
2111           (!compare_ff(f_hsv_a[2], f_hsv_b[2], val_threshold)) ||
2112           (!compare_ff(gp_style_primary->stroke_rgba[3],
2113                        gp_style_secondary->stroke_rgba[3],
2114                        val_threshold)) ||
2115           (!compare_ff(
2116               gp_style_primary->fill_rgba[3], gp_style_secondary->fill_rgba[3], val_threshold))) {
2117         continue;
2118       }
2119 
2120       /* Save conversion indexes. */
2121       if (!BLI_ghash_haskey(r_mat_table, POINTER_FROM_INT(idx_secondary))) {
2122         BLI_ghash_insert(
2123             r_mat_table, POINTER_FROM_INT(idx_secondary), POINTER_FROM_INT(idx_primary));
2124         changed = true;
2125 
2126         if (!BLI_ghash_haskey(mat_used, POINTER_FROM_INT(idx_primary))) {
2127           BLI_ghash_insert(mat_used, POINTER_FROM_INT(idx_primary), POINTER_FROM_INT(idx_primary));
2128         }
2129       }
2130     }
2131   }
2132   /* Free hash memory. */
2133   BLI_ghash_free(mat_used, NULL, NULL);
2134 
2135   return changed;
2136 }
2137 
2138 /**
2139  * Merge similar materials
2140  * \param ob: Grease pencil object
2141  * \param hue_threshold: Threshold for Hue
2142  * \param sat_threshold: Threshold for Saturation
2143  * \param val_threshold: Threshold for Value
2144  * \param r_removed: Number of materials removed
2145  * \return True if done
2146  */
BKE_gpencil_merge_materials(Object * ob,const float hue_threshold,const float sat_threshold,const float val_threshold,int * r_removed)2147 bool BKE_gpencil_merge_materials(Object *ob,
2148                                  const float hue_threshold,
2149                                  const float sat_threshold,
2150                                  const float val_threshold,
2151                                  int *r_removed)
2152 {
2153   bGPdata *gpd = ob->data;
2154 
2155   short *totcol = BKE_object_material_len_p(ob);
2156   if (totcol == 0) {
2157     *r_removed = 0;
2158     return 0;
2159   }
2160 
2161   /* Review materials. */
2162   GHash *mat_table = BLI_ghash_int_new(__func__);
2163 
2164   bool changed = BKE_gpencil_merge_materials_table_get(
2165       ob, hue_threshold, sat_threshold, val_threshold, mat_table);
2166 
2167   *r_removed = BLI_ghash_len(mat_table);
2168 
2169   /* Update stroke material index. */
2170   if (changed) {
2171     LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2172       if (gpl->flag & GP_LAYER_HIDE) {
2173         continue;
2174       }
2175 
2176       LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2177         LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
2178           /* Check if the color is editable. */
2179           MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
2180           if (gp_style != NULL) {
2181             if (gp_style->flag & GP_MATERIAL_HIDE) {
2182               continue;
2183             }
2184             if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) &&
2185                 (gp_style->flag & GP_MATERIAL_LOCKED)) {
2186               continue;
2187             }
2188           }
2189 
2190           if (BLI_ghash_haskey(mat_table, POINTER_FROM_INT(gps->mat_nr))) {
2191             int *idx = BLI_ghash_lookup(mat_table, POINTER_FROM_INT(gps->mat_nr));
2192             gps->mat_nr = POINTER_AS_INT(idx);
2193           }
2194         }
2195       }
2196     }
2197   }
2198 
2199   /* Free hash memory. */
2200   BLI_ghash_free(mat_table, NULL, NULL);
2201 
2202   return changed;
2203 }
2204 
2205 /**
2206  * Calc grease pencil statistics functions.
2207  * \param gpd: Grease pencil data-block
2208  */
BKE_gpencil_stats_update(bGPdata * gpd)2209 void BKE_gpencil_stats_update(bGPdata *gpd)
2210 {
2211   gpd->totlayer = 0;
2212   gpd->totframe = 0;
2213   gpd->totstroke = 0;
2214   gpd->totpoint = 0;
2215 
2216   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2217     gpd->totlayer++;
2218     LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2219       gpd->totframe++;
2220       LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
2221         gpd->totstroke++;
2222         gpd->totpoint += gps->totpoints;
2223       }
2224     }
2225   }
2226 }
2227 
2228 /**
2229  * Get material index (0-based like mat_nr not actcol).
2230  * \param ob: Grease pencil object
2231  * \param ma: Material
2232  * \return Index of the material
2233  */
BKE_gpencil_object_material_index_get(Object * ob,Material * ma)2234 int BKE_gpencil_object_material_index_get(Object *ob, Material *ma)
2235 {
2236   short *totcol = BKE_object_material_len_p(ob);
2237   Material *read_ma = NULL;
2238   for (short i = 0; i < *totcol; i++) {
2239     read_ma = BKE_object_material_get(ob, i + 1);
2240     if (ma == read_ma) {
2241       return i;
2242     }
2243   }
2244 
2245   return -1;
2246 }
2247 
2248 /**
2249  * Create a default palette.
2250  * \param bmain: Main pointer
2251  * \param scene: Scene
2252  */
BKE_gpencil_palette_ensure(Main * bmain,Scene * scene)2253 void BKE_gpencil_palette_ensure(Main *bmain, Scene *scene)
2254 {
2255   const char *hexcol[] = {
2256       "FFFFFF", "F2F2F2", "E6E6E6", "D9D9D9", "CCCCCC", "BFBFBF", "B2B2B2", "A6A6A6", "999999",
2257       "8C8C8C", "808080", "737373", "666666", "595959", "4C4C4C", "404040", "333333", "262626",
2258       "1A1A1A", "000000", "F2FC24", "FFEA00", "FEA711", "FE8B68", "FB3B02", "FE3521", "D00000",
2259       "A81F3D", "780422", "2B0000", "F1E2C5", "FEE4B3", "FEDABB", "FEC28E", "D88F57", "BD6340",
2260       "A2402B", "63352D", "6B2833", "34120C", "E7CB8F", "D1B38B", "C1B17F", "D7980B", "FFB100",
2261       "FE8B00", "FF6A00", "B74100", "5F3E1D", "3B2300", "FECADA", "FE65CB", "FE1392", "DD3062",
2262       "C04A6D", "891688", "4D2689", "441521", "2C1139", "241422", "FFFF7D", "FFFF00", "FF7F00",
2263       "FF7D7D", "FF7DFF", "FF00FE", "FF007F", "FF0000", "7F0000", "0A0A00", "F6FDFF", "E9F7FF",
2264       "CFE6FE", "AAC7FE", "77B3FE", "1E74FD", "0046AA", "2F4476", "003052", "0E0E25", "EEF5F0",
2265       "D6E5DE", "ACD8B9", "6CADC6", "42A9AF", "007F7F", "49675C", "2E4E4E", "1D3239", "0F1C21",
2266       "D8FFF4", "B8F4F5", "AECCB5", "76C578", "358757", "409B68", "468768", "1F512B", "2A3C37",
2267       "122E1D", "EFFFC9", "E6F385", "BCF51C", "D4DC18", "82D322", "5C7F00", "59932B", "297F00",
2268       "004320", "1C3322", "00FF7F", "00FF00", "7DFF7D", "7DFFFF", "00FFFF", "7D7DFF", "7F00FF",
2269       "0000FF", "3F007F", "00007F"};
2270 
2271   ToolSettings *ts = scene->toolsettings;
2272   if (ts->gp_paint->paint.palette != NULL) {
2273     return;
2274   }
2275 
2276   /* Try to find the default palette. */
2277   const char *palette_id = "Palette";
2278   struct Palette *palette = BLI_findstring(&bmain->palettes, palette_id, offsetof(ID, name) + 2);
2279 
2280   if (palette == NULL) {
2281     /* Fall back to the first palette. */
2282     palette = bmain->palettes.first;
2283   }
2284 
2285   if (palette == NULL) {
2286     /* Fall back to creating a palette. */
2287     palette = BKE_palette_add(bmain, palette_id);
2288     id_us_min(&palette->id);
2289 
2290     /* Create Colors. */
2291     for (int i = 0; i < ARRAY_SIZE(hexcol); i++) {
2292       PaletteColor *palcol = BKE_palette_color_add(palette);
2293       hex_to_rgb(hexcol[i], palcol->rgb, palcol->rgb + 1, palcol->rgb + 2);
2294     }
2295   }
2296 
2297   BLI_assert(palette != NULL);
2298   BKE_paint_palette_set(&ts->gp_paint->paint, palette);
2299   BKE_paint_palette_set(&ts->gp_vertexpaint->paint, palette);
2300 }
2301 
2302 /**
2303  * Create grease pencil strokes from image
2304  * \param sima: Image
2305  * \param gpf: Grease pencil frame
2306  * \param size: Size
2307  * \param mask: Mask
2308  * \return  True if done
2309  */
BKE_gpencil_from_image(SpaceImage * sima,bGPDframe * gpf,const float size,const bool mask)2310 bool BKE_gpencil_from_image(SpaceImage *sima, bGPDframe *gpf, const float size, const bool mask)
2311 {
2312   Image *image = sima->image;
2313   bool done = false;
2314 
2315   if (image == NULL) {
2316     return false;
2317   }
2318 
2319   ImageUser iuser = sima->iuser;
2320   void *lock;
2321   ImBuf *ibuf;
2322 
2323   ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
2324 
2325   if (ibuf && ibuf->rect) {
2326     int img_x = ibuf->x;
2327     int img_y = ibuf->y;
2328 
2329     float color[4];
2330     bGPDspoint *pt;
2331     for (int row = 0; row < img_y; row++) {
2332       /* Create new stroke */
2333       bGPDstroke *gps = BKE_gpencil_stroke_add(gpf, 0, img_x, size * 1000, false);
2334       done = true;
2335       for (int col = 0; col < img_x; col++) {
2336         IMB_sampleImageAtLocation(ibuf, col, row, true, color);
2337         pt = &gps->points[col];
2338         pt->pressure = 1.0f;
2339         pt->x = col * size;
2340         pt->z = row * size;
2341         if (!mask) {
2342           copy_v3_v3(pt->vert_color, color);
2343           pt->vert_color[3] = 1.0f;
2344           pt->strength = color[3];
2345         }
2346         else {
2347           zero_v3(pt->vert_color);
2348           pt->vert_color[3] = 1.0f;
2349           pt->strength = 1.0f - color[3];
2350         }
2351 
2352         /* Selet Alpha points. */
2353         if (pt->strength < 0.03f) {
2354           gps->flag |= GP_STROKE_SELECT;
2355           pt->flag |= GP_SPOINT_SELECT;
2356         }
2357       }
2358       BKE_gpencil_stroke_geometry_update(gps);
2359     }
2360   }
2361 
2362   /* Free memory. */
2363   BKE_image_release_ibuf(image, ibuf, lock);
2364 
2365   return done;
2366 }
2367 
2368 /**
2369  * Helper to check if a layers is used as mask
2370  * \param view_layer: Actual view layer.
2371  * \param gpd: Grease pencil data-block.
2372  * \param gpl_mask: Actual Layer.
2373  * \return True if the layer is used as mask.
2374  */
gpencil_is_layer_mask(ViewLayer * view_layer,bGPdata * gpd,bGPDlayer * gpl_mask)2375 static bool gpencil_is_layer_mask(ViewLayer *view_layer, bGPdata *gpd, bGPDlayer *gpl_mask)
2376 {
2377   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2378     if ((gpl->viewlayername[0] != '\0') && (!STREQ(view_layer->name, gpl->viewlayername))) {
2379       continue;
2380     }
2381 
2382     LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl->mask_layers) {
2383       if (STREQ(gpl_mask->info, mask->name)) {
2384         return true;
2385       }
2386     }
2387   }
2388 
2389   return false;
2390 }
2391 
2392 /* -------------------------------------------------------------------- */
2393 /** \name Iterators
2394  *
2395  * Iterate over all visible stroke of all visible layers inside a gpObject.
2396  * Also take into account onion-skinning.
2397  * \{ */
2398 
BKE_gpencil_visible_stroke_iter(ViewLayer * view_layer,Object * ob,gpIterCb layer_cb,gpIterCb stroke_cb,void * thunk,bool do_onion,int cfra)2399 void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer,
2400                                      Object *ob,
2401                                      gpIterCb layer_cb,
2402                                      gpIterCb stroke_cb,
2403                                      void *thunk,
2404                                      bool do_onion,
2405                                      int cfra)
2406 {
2407   bGPdata *gpd = (bGPdata *)ob->data;
2408   const bool is_multiedit = GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
2409   const bool is_onion = do_onion && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0);
2410   const bool is_drawing = (gpd->runtime.sbuffer_used > 0);
2411 
2412   /* Onion skinning. */
2413   const bool onion_mode_abs = (gpd->onion_mode == GP_ONION_MODE_ABSOLUTE);
2414   const bool onion_mode_sel = (gpd->onion_mode == GP_ONION_MODE_SELECTED);
2415   const bool onion_loop = (gpd->onion_flag & GP_ONION_LOOP) != 0;
2416   const short onion_keytype = gpd->onion_keytype;
2417 
2418   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2419     /* Reset by layer. */
2420     bool is_before_first = false;
2421 
2422     bGPDframe *act_gpf = gpl->actframe;
2423     bGPDframe *sta_gpf = act_gpf;
2424     bGPDframe *end_gpf = act_gpf ? act_gpf->next : NULL;
2425 
2426     if (gpl->flag & GP_LAYER_HIDE) {
2427       continue;
2428     }
2429 
2430     /* Hide the layer if it's defined a view layer filter. This is used to
2431      * generate renders, putting only selected GP layers for each View Layer.
2432      * This is used only in final render and never in Viewport. */
2433     if ((view_layer != NULL) && (gpl->viewlayername[0] != '\0') &&
2434         (!STREQ(view_layer->name, gpl->viewlayername))) {
2435       /* If the layer is used as mask, cannot be filtered or the masking system
2436        * will crash because needs the mask layer in the draw pipeline. */
2437       if (!gpencil_is_layer_mask(view_layer, gpd, gpl)) {
2438         continue;
2439       }
2440     }
2441 
2442     if (is_multiedit) {
2443       sta_gpf = end_gpf = NULL;
2444       /* Check the whole range and tag the editable frames. */
2445       LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2446         if (gpf == act_gpf || (gpf->flag & GP_FRAME_SELECT)) {
2447           gpf->runtime.onion_id = 0;
2448           if (sta_gpf == NULL) {
2449             sta_gpf = gpf;
2450           }
2451           end_gpf = gpf->next;
2452         }
2453         else {
2454           gpf->runtime.onion_id = INT_MAX;
2455         }
2456       }
2457     }
2458     else if (is_onion && (gpl->onion_flag & GP_LAYER_ONIONSKIN)) {
2459       /* Special cases when cframe is before first frame. */
2460       bGPDframe *gpf_first = gpl->frames.first;
2461       if ((gpf_first != NULL) && (act_gpf != NULL) && (gpf_first->framenum > act_gpf->framenum)) {
2462         is_before_first = true;
2463       }
2464       if ((gpf_first != NULL) && (act_gpf == NULL)) {
2465         act_gpf = gpf_first;
2466         is_before_first = true;
2467       }
2468 
2469       if (act_gpf) {
2470         bGPDframe *last_gpf = gpl->frames.last;
2471 
2472         int frame_len = 0;
2473         LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2474           gpf->runtime.frameid = frame_len++;
2475         }
2476 
2477         LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2478           bool is_wrong_keytype = (onion_keytype > -1) && (gpf->key_type != onion_keytype);
2479           bool is_in_range;
2480           int delta = (onion_mode_abs) ? (gpf->framenum - cfra) :
2481                                          (gpf->runtime.frameid - act_gpf->runtime.frameid);
2482 
2483           if (is_before_first) {
2484             delta++;
2485           }
2486 
2487           if (onion_mode_sel) {
2488             is_in_range = (gpf->flag & GP_FRAME_SELECT) != 0;
2489           }
2490           else {
2491             is_in_range = (-delta <= gpd->gstep) && (delta <= gpd->gstep_next);
2492 
2493             if (onion_loop && !is_in_range) {
2494               /* We wrap the value using the last frame and 0 as reference. */
2495               /* FIXME: This might not be good for animations not starting at 0. */
2496               int shift = (onion_mode_abs) ? last_gpf->framenum : last_gpf->runtime.frameid;
2497               delta += (delta < 0) ? (shift + 1) : -(shift + 1);
2498               /* Test again with wrapped value. */
2499               is_in_range = (-delta <= gpd->gstep) && (delta <= gpd->gstep_next);
2500             }
2501           }
2502           /* Mask frames that have wrong keytype of are not in range. */
2503           gpf->runtime.onion_id = (is_wrong_keytype || !is_in_range) ? INT_MAX : delta;
2504         }
2505         /* Active frame is always shown. */
2506         if (!is_before_first || is_drawing) {
2507           act_gpf->runtime.onion_id = 0;
2508         }
2509       }
2510 
2511       sta_gpf = gpl->frames.first;
2512       end_gpf = NULL;
2513     }
2514     else {
2515       /* Bypass multiedit/onion skinning. */
2516       end_gpf = sta_gpf = NULL;
2517     }
2518 
2519     if (sta_gpf == NULL && act_gpf == NULL) {
2520       if (layer_cb) {
2521         layer_cb(gpl, act_gpf, NULL, thunk);
2522       }
2523       continue;
2524     }
2525 
2526     /* Draw multiedit/onion skinning first */
2527     for (bGPDframe *gpf = sta_gpf; gpf && gpf != end_gpf; gpf = gpf->next) {
2528       if ((gpf->runtime.onion_id == INT_MAX || gpf == act_gpf) && (!is_before_first)) {
2529         continue;
2530       }
2531 
2532       /* Only do once for frame before first. */
2533       if (is_before_first && gpf == act_gpf) {
2534         is_before_first = false;
2535       }
2536 
2537       if (layer_cb) {
2538         layer_cb(gpl, gpf, NULL, thunk);
2539       }
2540 
2541       LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
2542         if (gps->totpoints == 0) {
2543           continue;
2544         }
2545         stroke_cb(gpl, gpf, gps, thunk);
2546       }
2547     }
2548     /* Draw Active frame on top. */
2549     /* Use evaluated frame (with modifiers for active stroke)/ */
2550     act_gpf = gpl->actframe;
2551     if (act_gpf) {
2552       act_gpf->runtime.onion_id = 0;
2553       if (layer_cb) {
2554         layer_cb(gpl, act_gpf, NULL, thunk);
2555       }
2556 
2557       /* If layer solo mode and Paint mode, only keyframes with data are displayed. */
2558       if (GPENCIL_PAINT_MODE(gpd) && (gpl->flag & GP_LAYER_SOLO_MODE) &&
2559           (act_gpf->framenum != cfra)) {
2560         continue;
2561       }
2562 
2563       LISTBASE_FOREACH (bGPDstroke *, gps, &act_gpf->strokes) {
2564         if (gps->totpoints == 0) {
2565           continue;
2566         }
2567         stroke_cb(gpl, act_gpf, gps, thunk);
2568       }
2569     }
2570   }
2571 }
2572 
2573 /**
2574  * Update original pointers in evaluated frame.
2575  * \param gpf_orig: Original grease-pencil frame.
2576  * \param gpf_eval: Evaluated grease pencil frame.
2577  */
BKE_gpencil_frame_original_pointers_update(const struct bGPDframe * gpf_orig,const struct bGPDframe * gpf_eval)2578 void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig,
2579                                                 const struct bGPDframe *gpf_eval)
2580 {
2581   bGPDstroke *gps_eval = gpf_eval->strokes.first;
2582   LISTBASE_FOREACH (bGPDstroke *, gps_orig, &gpf_orig->strokes) {
2583 
2584     /* Assign original stroke pointer. */
2585     if (gps_eval != NULL) {
2586       gps_eval->runtime.gps_orig = gps_orig;
2587 
2588       /* Assign original point pointer. */
2589       for (int i = 0; i < gps_orig->totpoints; i++) {
2590         if (i > gps_eval->totpoints - 1) {
2591           break;
2592         }
2593         bGPDspoint *pt_orig = &gps_orig->points[i];
2594         bGPDspoint *pt_eval = &gps_eval->points[i];
2595         pt_orig->runtime.pt_orig = NULL;
2596         pt_orig->runtime.idx_orig = i;
2597         pt_eval->runtime.pt_orig = pt_orig;
2598         pt_eval->runtime.idx_orig = i;
2599       }
2600       /* Increase pointer. */
2601       gps_eval = gps_eval->next;
2602     }
2603   }
2604 }
2605 
2606 /**
2607  * Update pointers of eval data to original data to keep references.
2608  * \param ob_orig: Original grease pencil object
2609  * \param ob_eval: Evaluated grease pencil object
2610  */
BKE_gpencil_update_orig_pointers(const Object * ob_orig,const Object * ob_eval)2611 void BKE_gpencil_update_orig_pointers(const Object *ob_orig, const Object *ob_eval)
2612 {
2613   bGPdata *gpd_eval = (bGPdata *)ob_eval->data;
2614   bGPdata *gpd_orig = (bGPdata *)ob_orig->data;
2615 
2616   /* Assign pointers to the original stroke and points to the evaluated data. This must
2617    * be done before applying any modifier because at this moment the structure is equals,
2618    * so we can assume the layer index is the same in both data-blocks.
2619    * This data will be used by operators. */
2620 
2621   bGPDlayer *gpl_eval = gpd_eval->layers.first;
2622   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_orig->layers) {
2623     if (gpl_eval != NULL) {
2624       /* Update layer reference pointers. */
2625       gpl_eval->runtime.gpl_orig = (bGPDlayer *)gpl;
2626 
2627       bGPDframe *gpf_eval = gpl_eval->frames.first;
2628       LISTBASE_FOREACH (bGPDframe *, gpf_orig, &gpl->frames) {
2629         if (gpf_eval != NULL) {
2630           /* Update frame reference pointers. */
2631           gpf_eval->runtime.gpf_orig = (bGPDframe *)gpf_orig;
2632           BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf_eval);
2633           gpf_eval = gpf_eval->next;
2634         }
2635       }
2636       gpl_eval = gpl_eval->next;
2637     }
2638   }
2639 }
2640 
2641 /**
2642  * Get parent matrix, including layer parenting.
2643  * \param depsgraph: Depsgraph
2644  * \param obact: Grease pencil object
2645  * \param gpl: Grease pencil layer
2646  * \param diff_mat: Result parent matrix
2647  */
BKE_gpencil_parent_matrix_get(const Depsgraph * depsgraph,Object * obact,bGPDlayer * gpl,float diff_mat[4][4])2648 void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph,
2649                                    Object *obact,
2650                                    bGPDlayer *gpl,
2651                                    float diff_mat[4][4])
2652 {
2653   Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact;
2654   Object *obparent = gpl->parent;
2655   Object *obparent_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obparent) :
2656                                               obparent;
2657 
2658   /* if not layer parented, try with object parented */
2659   if (obparent_eval == NULL) {
2660     if (ob_eval != NULL) {
2661       if (ob_eval->type == OB_GPENCIL) {
2662         copy_m4_m4(diff_mat, ob_eval->obmat);
2663         return;
2664       }
2665     }
2666     /* not gpencil object */
2667     unit_m4(diff_mat);
2668     return;
2669   }
2670 
2671   if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
2672     mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
2673     add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
2674     return;
2675   }
2676   if (gpl->partype == PARBONE) {
2677     bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr);
2678     if (pchan) {
2679       float tmp_mat[4][4];
2680       mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat);
2681       mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse);
2682       add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
2683     }
2684     else {
2685       /* if bone not found use object (armature) */
2686       mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
2687       add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
2688     }
2689     return;
2690   }
2691 
2692   unit_m4(diff_mat); /* not defined type */
2693 }
2694 
2695 /**
2696  * Update parent matrix.
2697  * \param depsgraph: Depsgraph
2698  * \param ob: Grease pencil object
2699  */
BKE_gpencil_update_layer_parent(const Depsgraph * depsgraph,Object * ob)2700 void BKE_gpencil_update_layer_parent(const Depsgraph *depsgraph, Object *ob)
2701 {
2702   if (ob->type != OB_GPENCIL) {
2703     return;
2704   }
2705 
2706   bGPdata *gpd = (bGPdata *)ob->data;
2707   float cur_mat[4][4];
2708 
2709   LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2710     if ((gpl->parent != NULL) && (gpl->actframe != NULL)) {
2711       Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent);
2712       /* calculate new matrix */
2713       if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
2714         copy_m4_m4(cur_mat, ob_parent->obmat);
2715       }
2716       else if (gpl->partype == PARBONE) {
2717         bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr);
2718         if (pchan != NULL) {
2719           copy_m4_m4(cur_mat, ob->imat);
2720           mul_m4_m4m4(cur_mat, ob_parent->obmat, pchan->pose_mat);
2721         }
2722         else {
2723           unit_m4(cur_mat);
2724         }
2725       }
2726       /* only redo if any change */
2727       if (!equals_m4m4(gpl->inverse, cur_mat)) {
2728         LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) {
2729           bGPDspoint *pt;
2730           int i;
2731           for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
2732             mul_m4_v3(gpl->inverse, &pt->x);
2733             mul_m4_v3(cur_mat, &pt->x);
2734           }
2735         }
2736       }
2737     }
2738   }
2739 }
2740 
2741 /**
2742  * Find material by name prefix.
2743  * \param ob: Object pointer
2744  * \param name_prefix: Prefix name of the material
2745  * \return  Index
2746  */
BKE_gpencil_material_find_index_by_name_prefix(Object * ob,const char * name_prefix)2747 int BKE_gpencil_material_find_index_by_name_prefix(Object *ob, const char *name_prefix)
2748 {
2749   const int name_prefix_len = strlen(name_prefix);
2750   for (int i = 0; i < ob->totcol; i++) {
2751     Material *ma = BKE_object_material_get(ob, i + 1);
2752     if ((ma != NULL) && (ma->gp_style != NULL) &&
2753         (STREQLEN(ma->id.name + 2, name_prefix, name_prefix_len))) {
2754       return i;
2755     }
2756   }
2757 
2758   return -1;
2759 }
2760 
2761 /** \} */
2762