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