Blender V4.3
gpencil_legacy.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cmath>
10#include <cstddef>
11#include <cstdio>
12#include <cstdlib>
13#include <cstring>
14#include <optional>
15
16#include "CLG_log.h"
17
18#include "MEM_guardedalloc.h"
19
20#include "BLI_blenlib.h"
21#include "BLI_math_matrix.h"
22#include "BLI_math_vector.h"
23#include "BLI_string_utils.hh"
24
25#include "BLT_translation.hh"
26
27#include "IMB_interp.hh"
28
29/* Allow using deprecated functionality for .blend file I/O. */
30#define DNA_DEPRECATED_ALLOW
31
33#include "DNA_material_types.h"
34#include "DNA_meshdata_types.h"
35#include "DNA_space_types.h"
36
37#include "BKE_action.hh"
38#include "BKE_anim_data.hh"
39#include "BKE_brush.hh"
40#include "BKE_collection.hh"
41#include "BKE_colortools.hh"
42#include "BKE_deform.hh"
44#include "BKE_gpencil_legacy.h"
46#include "BKE_icons.h"
47#include "BKE_idtype.hh"
48#include "BKE_image.hh"
49#include "BKE_lib_id.hh"
50#include "BKE_lib_query.hh"
51#include "BKE_main.hh"
52#include "BKE_material.h"
53#include "BKE_paint.hh"
54
55#include "BLI_math_color.h"
56
58
59#include "BLO_read_write.hh"
60
61static CLG_LogRef LOG = {"bke.gpencil"};
62
63static void greasepencil_copy_data(Main * /*bmain*/,
64 std::optional<Library *> /*owner_library*/,
65 ID *id_dst,
66 const ID *id_src,
67 const int /*flag*/)
68{
69 bGPdata *gpd_dst = (bGPdata *)id_dst;
70 const bGPdata *gpd_src = (const bGPdata *)id_src;
71
72 /* duplicate material array */
73 if (gpd_src->mat) {
74 gpd_dst->mat = static_cast<Material **>(MEM_dupallocN(gpd_src->mat));
75 }
76
78
79 /* copy layers */
80 BLI_listbase_clear(&gpd_dst->layers);
81 LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) {
82 /* make a copy of source layer and its data */
83
84 /* TODO: here too could add unused flags... */
85 bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src, true, true);
86
87 /* Apply local layer transform to all frames. Calc the active frame is not enough
88 * because onion skin can use more frames. This is more slow but required here. */
89 if (gpl_dst->actframe != nullptr) {
90 bool transformed = (!is_zero_v3(gpl_dst->location) || !is_zero_v3(gpl_dst->rotation) ||
91 !is_one_v3(gpl_dst->scale));
92 if (transformed) {
94 gpl_dst->layer_mat, gpl_dst->location, gpl_dst->rotation, gpl_dst->scale);
95 bool do_onion = ((gpl_dst->onion_flag & GP_LAYER_ONIONSKIN) != 0);
96 bGPDframe *init_gpf = static_cast<bGPDframe *>((do_onion) ? gpl_dst->frames.first :
97 gpl_dst->actframe);
98 for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
99 LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
100 bGPDspoint *pt;
101 int i;
102 for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
103 mul_m4_v3(gpl_dst->layer_mat, &pt->x);
104 }
105 }
106 /* if not onion, exit loop. */
107 if (!do_onion) {
108 break;
109 }
110 }
111 }
112 }
113
114 BLI_addtail(&gpd_dst->layers, gpl_dst);
115 }
116}
117
119{
120 /* Really not ideal, but for now will do... In theory custom behaviors like not freeing cache
121 * should be handled through specific API, and not be part of the generic one. */
122 BKE_gpencil_free_data((bGPdata *)id, true);
123}
124
126{
127 bGPdata *gpencil = (bGPdata *)id;
128 /* materials */
129 for (int i = 0; i < gpencil->totcol; i++) {
131 }
132
133 LISTBASE_FOREACH (bGPDlayer *, gplayer, &gpencil->layers) {
134 BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, gplayer->parent, IDWALK_CB_NOP);
135 }
136}
137
138static void greasepencil_blend_write(BlendWriter *writer, ID *id, const void *id_address)
139{
140 bGPdata *gpd = (bGPdata *)id;
141
142 /* Clean up, important in undo case to reduce false detection of changed data-blocks. */
143 /* XXX not sure why the whole run-time data is not cleared in reading code,
144 * for now mimicking it here. */
145 gpd->runtime.sbuffer = nullptr;
146 gpd->runtime.sbuffer_used = 0;
147 gpd->runtime.sbuffer_size = 0;
148 gpd->runtime.tot_cp_points = 0;
149 gpd->runtime.update_cache = nullptr;
150
151 /* write gpd data block to file */
152 BLO_write_id_struct(writer, bGPdata, id_address, &gpd->id);
153 BKE_id_blend_write(writer, &gpd->id);
154
156
157 BLO_write_pointer_array(writer, gpd->totcol, gpd->mat);
158
159 /* write grease-pencil layers to file */
160 BLO_write_struct_list(writer, bGPDlayer, &gpd->layers);
161 LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
162 /* Write mask list. */
163 BLO_write_struct_list(writer, bGPDlayer_Mask, &gpl->mask_layers);
164 /* write this layer's frames to file */
165 BLO_write_struct_list(writer, bGPDframe, &gpl->frames);
166 LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
167 /* write strokes */
168 BLO_write_struct_list(writer, bGPDstroke, &gpf->strokes);
169 LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
170 BLO_write_struct_array(writer, bGPDspoint, gps->totpoints, gps->points);
171 BLO_write_struct_array(writer, bGPDtriangle, gps->tot_triangles, gps->triangles);
172 BKE_defvert_blend_write(writer, gps->totpoints, gps->dvert);
173 if (gps->editcurve != nullptr) {
174 bGPDcurve *gpc = gps->editcurve;
175 BLO_write_struct(writer, bGPDcurve, gpc);
177 writer, bGPDcurve_point, gpc->tot_curve_points, gpc->curve_points);
178 }
179 }
180 }
181 }
182}
183
185{
186 /* We must firstly have some grease-pencil data to link! */
187 if (gpd == nullptr) {
188 return;
189 }
190
191 /* Ensure full object-mode for linked grease pencil. */
192 if (ID_IS_LINKED(gpd)) {
193 gpd->flag &= ~GP_DATA_STROKE_PAINTMODE;
194 gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
195 gpd->flag &= ~GP_DATA_STROKE_SCULPTMODE;
196 gpd->flag &= ~GP_DATA_STROKE_WEIGHTMODE;
197 gpd->flag &= ~GP_DATA_STROKE_VERTEXMODE;
198 }
199
200 /* init stroke buffer */
201 gpd->runtime.sbuffer = nullptr;
202 gpd->runtime.sbuffer_used = 0;
203 gpd->runtime.sbuffer_size = 0;
204 gpd->runtime.tot_cp_points = 0;
205 gpd->runtime.update_cache = nullptr;
206
207 /* Relink palettes (old palettes deprecated, only to convert old files). */
208 BLO_read_struct_list(reader, bGPDpalette, &gpd->palettes);
209 if (gpd->palettes.first != nullptr) {
210 LISTBASE_FOREACH (bGPDpalette *, palette, &gpd->palettes) {
211 BLO_read_struct_list(reader, PaletteColor, &palette->colors);
212 }
213 }
214
216
217 /* Materials. */
218 BLO_read_pointer_array(reader, gpd->totcol, (void **)&gpd->mat);
219
220 /* Relink layers. */
221 BLO_read_struct_list(reader, bGPDlayer, &gpd->layers);
222
223 LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
224 /* Relink frames. */
225 BLO_read_struct_list(reader, bGPDframe, &gpl->frames);
226
227 BLO_read_struct(reader, bGPDframe, &gpl->actframe);
228
229 gpl->runtime.icon_id = 0;
230
231 /* Relink masks. */
232 BLO_read_struct_list(reader, bGPDlayer_Mask, &gpl->mask_layers);
233
234 LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
235 /* Relink strokes (and their points). */
236 BLO_read_struct_list(reader, bGPDstroke, &gpf->strokes);
237
238 LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
239 /* Relink stroke points array. */
240 BLO_read_struct_array(reader, bGPDspoint, gps->totpoints, &gps->points);
241 /* Relink geometry. */
242 BLO_read_struct_array(reader, bGPDtriangle, gps->tot_triangles, &gps->triangles);
243
244 /* Relink stroke edit curve. */
245 BLO_read_struct(reader, bGPDcurve, &gps->editcurve);
246 if (gps->editcurve != nullptr) {
247 /* Relink curve point array. */
248 bGPDcurve *gpc = gps->editcurve;
250 reader, bGPDcurve_point, gpc->tot_curve_points, &gps->editcurve->curve_points);
251 }
252
253 /* Relink weight data. */
254 if (gps->dvert) {
255 BLO_read_struct_array(reader, MDeformVert, gps->totpoints, &gps->dvert);
256 BKE_defvert_blend_read(reader, gps->totpoints, gps->dvert);
257 }
258 }
259 }
260 }
261}
262
264{
265 bGPdata *gpd = (bGPdata *)id;
266 BKE_gpencil_blend_read_data(reader, gpd);
267}
268
270 /*id_code*/ ID_GD_LEGACY,
271 /*id_filter*/ FILTER_ID_GD_LEGACY,
272 /*dependencies_id_types*/ FILTER_ID_MA,
273 /*main_listbase_index*/ INDEX_ID_GD_LEGACY,
274 /*struct_size*/ sizeof(bGPdata),
275 /*name*/ "GPencil",
276 /*name_plural*/ N_("grease_pencils"),
277 /*translation_context*/ BLT_I18NCONTEXT_ID_GPENCIL,
279 /*asset_type_info*/ nullptr,
280
281 /*init_data*/ nullptr,
282 /*copy_data*/ greasepencil_copy_data,
283 /*free_data*/ greasepencil_free_data,
284 /*make_local*/ nullptr,
285 /*foreach_id*/ greasepencil_foreach_id,
286 /*foreach_cache*/ nullptr,
287 /*foreach_path*/ nullptr,
288 /*owner_pointer_get*/ nullptr,
289
290 /*blend_write*/ greasepencil_blend_write,
291 /*blend_read_data*/ greasepencil_blend_read_data,
292 /*blend_read_after_liblink*/ nullptr,
293
294 /*blend_read_undo_preserve*/ nullptr,
295
296 /*lib_override_apply_post*/ nullptr,
297};
298
299/* ************************************************** */
300/* Draw Engine */
301
304
312
314{
315 if (gpd) {
317 }
318}
319
320/* ************************************************** */
321/* Memory Management */
322
324{
325 if (dvert == nullptr) {
326 return;
327 }
328 MEM_SAFE_FREE(dvert->dw);
329}
330
332{
333 if (gps == nullptr) {
334 return;
335 }
336
337 if (gps->dvert == nullptr) {
338 return;
339 }
340
341 for (int i = 0; i < gps->totpoints; i++) {
342 MDeformVert *dvert = &gps->dvert[i];
344 }
345}
346
348{
349 if (gps == nullptr) {
350 return;
351 }
352 bGPDcurve *editcurve = gps->editcurve;
353 if (editcurve == nullptr) {
354 return;
355 }
356 MEM_freeN(editcurve->curve_points);
357 MEM_freeN(editcurve);
358 gps->editcurve = nullptr;
359}
360
362{
363 if (gps == nullptr) {
364 return;
365 }
366 /* free stroke memory arrays, then stroke itself */
367 if (gps->points) {
368 MEM_freeN(gps->points);
369 }
370 if (gps->dvert) {
372 MEM_freeN(gps->dvert);
373 }
374 if (gps->triangles) {
375 MEM_freeN(gps->triangles);
376 }
377 if (gps->editcurve != nullptr) {
379 }
380
381 MEM_freeN(gps);
382}
383
385{
386 bool changed = (BLI_listbase_is_empty(&gpf->strokes) == false);
387
388 /* free strokes */
391 }
393
394 return changed;
395}
396
398{
399 bGPDframe *gpf_next;
400
401 /* error checking */
402 if (gpl == nullptr) {
403 return;
404 }
405
406 /* free frames */
407 for (bGPDframe *gpf = static_cast<bGPDframe *>(gpl->frames.first); gpf; gpf = gpf_next) {
408 gpf_next = gpf->next;
409
410 /* free strokes and their associated memory */
412 BLI_freelinkN(&gpl->frames, gpf);
413 }
414 gpl->actframe = nullptr;
415}
416
418{
419 /* Free masks. */
420 bGPDlayer_Mask *mask_next = nullptr;
421 for (bGPDlayer_Mask *mask = static_cast<bGPDlayer_Mask *>(gpl->mask_layers.first); mask;
422 mask = mask_next)
423 {
424 mask_next = mask->next;
425 BLI_freelinkN(&gpl->mask_layers, mask);
426 }
427}
429{
430 bGPDlayer *gpl_next;
431
432 /* error checking */
433 if (list == nullptr) {
434 return;
435 }
436
437 /* delete layers */
438 for (bGPDlayer *gpl = static_cast<bGPDlayer *>(list->first); gpl; gpl = gpl_next) {
439 gpl_next = gpl->next;
440
441 /* free layers and their data */
443
444 /* Free masks. */
446
447 BLI_freelinkN(list, gpl);
448 }
449}
450
452{
453 LISTBASE_FOREACH_MUTABLE (bGPDpalette *, palette, list) {
454 BLI_freelistN(&palette->colors);
455 MEM_freeN(palette);
456 }
457 BLI_listbase_clear(list);
458}
459
460void BKE_gpencil_free_data(bGPdata *gpd, bool free_all)
461{
462 /* free layers */
465
466 /* materials */
467 MEM_SAFE_FREE(gpd->mat);
468
470
472
473 /* free all data */
474 if (free_all) {
475 /* clear cache */
477 }
478}
479
484
485/* ************************************************** */
486/* Container Creation */
487
489{
490 bGPDframe *gpf = nullptr, *gf = nullptr;
491 short state = 0;
492
493 /* error checking */
494 if (gpl == nullptr) {
495 return nullptr;
496 }
497
498 /* allocate memory for this frame */
499 gpf = static_cast<bGPDframe *>(MEM_callocN(sizeof(bGPDframe), "bGPDframe"));
500 gpf->framenum = cframe;
501
502 /* find appropriate place to add frame */
503 if (gpl->frames.first) {
504 for (gf = static_cast<bGPDframe *>(gpl->frames.first); gf; gf = gf->next) {
505 /* check if frame matches one that is supposed to be added */
506 if (gf->framenum == cframe) {
507 state = -1;
508 break;
509 }
510
511 /* if current frame has already exceeded the frame to add, add before */
512 if (gf->framenum > cframe) {
513 BLI_insertlinkbefore(&gpl->frames, gf, gpf);
514 state = 1;
515 break;
516 }
517 }
518 }
519
520 /* check whether frame was added successfully */
521 if (state == -1) {
523 &LOG, "Frame (%d) existed already for this layer_active. Using existing frame", cframe);
524
525 /* free the newly created one, and use the old one instead */
526 MEM_freeN(gpf);
527
528 /* return existing frame instead... */
529 BLI_assert(gf != nullptr);
530 gpf = gf;
531 }
532 else if (state == 0) {
533 /* add to end then! */
534 BLI_addtail(&gpl->frames, gpf);
535 }
536
537 /* return frame */
538 return gpf;
539}
540
542{
543 bGPDframe *new_frame;
544 bool found = false;
545
546 /* Error checking/handling */
547 if (gpl == nullptr) {
548 /* no layer */
549 return nullptr;
550 }
551 if (gpl->actframe == nullptr) {
552 /* no active frame, so just create a new one from scratch */
553 return BKE_gpencil_frame_addnew(gpl, cframe);
554 }
555
556 /* Create a copy of the frame */
557 new_frame = BKE_gpencil_frame_duplicate(gpl->actframe, true);
558
559 /* Find frame to insert it before */
560 LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
561 if (gpf->framenum > cframe) {
562 /* Add it here */
563 BLI_insertlinkbefore(&gpl->frames, gpf, new_frame);
564
565 found = true;
566 break;
567 }
568 if (gpf->framenum == cframe) {
569 /* This only happens when we're editing with frame-lock on.
570 * - Delete the new frame and don't do anything else here.
571 */
572 BKE_gpencil_free_strokes(new_frame);
573 MEM_freeN(new_frame);
574 new_frame = nullptr;
575
576 found = true;
577 break;
578 }
579 }
580
581 if (found == false) {
582 /* Add new frame to the end */
583 BLI_addtail(&gpl->frames, new_frame);
584 }
585
586 /* Ensure that frame is set up correctly, and return it */
587 if (new_frame) {
588 new_frame->framenum = cframe;
589 gpl->actframe = new_frame;
590 }
591
592 return new_frame;
593}
594
596 const char *name,
597 const bool setactive,
598 const bool add_to_header)
599{
600 bGPDlayer *gpl = nullptr;
601 bGPDlayer *gpl_active = nullptr;
602
603 /* check that list is ok */
604 if (gpd == nullptr) {
605 return nullptr;
606 }
607
608 /* allocate memory for frame and add to end of list */
609 gpl = static_cast<bGPDlayer *>(MEM_callocN(sizeof(bGPDlayer), "bGPDlayer"));
610
611 gpl_active = BKE_gpencil_layer_active_get(gpd);
612
613 /* Add to data-block. */
614 if (add_to_header) {
615 BLI_addhead(&gpd->layers, gpl);
616 }
617 else {
618 if (gpl_active == nullptr) {
619 BLI_addtail(&gpd->layers, gpl);
620 }
621 else {
622 /* if active layer, add after that layer */
623 BLI_insertlinkafter(&gpd->layers, gpl_active, gpl);
624 }
625 }
626 /* annotation vs GP Object behavior is slightly different */
627 if (gpd->flag & GP_DATA_ANNOTATIONS) {
628 /* set default color of new strokes for this layer */
629 copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
630 gpl->opacity = 1.0f;
631
632 /* set default thickness of new strokes for this layer */
633 gpl->thickness = 3;
634
635 /* Onion colors */
636 ARRAY_SET_ITEMS(gpl->gcolor_prev, 0.302f, 0.851f, 0.302f);
637 ARRAY_SET_ITEMS(gpl->gcolor_next, 0.250f, 0.1f, 1.0f);
638 }
639 else {
640 /* thickness parameter represents "thickness change", not absolute thickness */
641 gpl->thickness = 0;
642 gpl->opacity = 1.0f;
643 /* default channel color */
644 ARRAY_SET_ITEMS(gpl->color, 0.2f, 0.2f, 0.2f);
645 /* Default vertex mix. */
646 gpl->vertex_paint_opacity = 1.0f;
647 /* Enable onion skin. */
649 }
650
651 /* auto-name */
652 STRNCPY_UTF8(gpl->info, DATA_(name));
654 gpl,
655 (gpd->flag & GP_DATA_ANNOTATIONS) ? DATA_("Note") : DATA_("GP_Layer"),
656 '.',
657 offsetof(bGPDlayer, info),
658 sizeof(gpl->info));
659
660 /* Enable always affected by scene lights. */
662
663 /* Init transform. */
664 zero_v3(gpl->location);
665 zero_v3(gpl->rotation);
666 copy_v3_fl(gpl->scale, 1.0f);
667 loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale);
669
670 /* make this one the active one */
671 if (setactive) {
673 }
674
675 /* return layer */
676 return gpl;
677}
678
679bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
680{
681 bGPdata *gpd;
682
683 /* allocate memory for a new block */
684 gpd = static_cast<bGPdata *>(BKE_libblock_alloc(bmain, ID_GD_LEGACY, name, 0));
685
686 /* initial settings */
688
689 /* general flags */
690 gpd->flag |= GP_DATA_VIEWALIGN;
691 /* always enable object onion skin switch */
693 /* GP object specific settings */
694 ARRAY_SET_ITEMS(gpd->line_color, 0.6f, 0.6f, 0.6f, 0.5f);
695
697
701
702 /* use adaptive curve resolution by default */
704
705 gpd->zdepth_offset = 0.150f;
706
707 /* grid settings */
708 ARRAY_SET_ITEMS(gpd->grid.color, 0.5f, 0.5f, 0.5f); /* Color */
709 ARRAY_SET_ITEMS(gpd->grid.scale, 1.0f, 1.0f); /* Scale */
710 gpd->grid.lines = GP_DEFAULT_GRID_LINES; /* Number of lines */
711
712 /* Onion-skinning settings (data-block level) */
713 gpd->onion_keytype = -1; /* All by default. */
717 gpd->onion_factor = 0.5f;
718 ARRAY_SET_ITEMS(gpd->gcolor_prev, 0.145098f, 0.419608f, 0.137255f); /* green */
719 ARRAY_SET_ITEMS(gpd->gcolor_next, 0.125490f, 0.082353f, 0.529412f); /* blue */
720 gpd->gstep = 1;
721 gpd->gstep_next = 1;
722
723 return gpd;
724}
725
726/* ************************************************** */
727/* Primitive Creation */
728/* Utilities for easier bulk-creation of geometry */
729
730bGPDstroke *BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness)
731{
732 /* allocate memory for a new stroke */
733 bGPDstroke *gps = static_cast<bGPDstroke *>(MEM_callocN(sizeof(bGPDstroke), "gp_stroke"));
734
735 gps->thickness = thickness;
736 gps->fill_opacity_fac = 1.0f;
737 gps->hardness = 1.0f;
738 copy_v2_fl(gps->aspect_ratio, 1.0f);
739
740 gps->uv_scale = 1.0f;
741
742 gps->inittime = 0;
743
744 gps->flag = GP_STROKE_3DSPACE;
745
746 gps->totpoints = totpoints;
747 if (gps->totpoints > 0) {
748 gps->points = static_cast<bGPDspoint *>(
749 MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"));
750 }
751 else {
752 gps->points = nullptr;
753 }
754
755 /* initialize triangle memory to dummy data */
756 gps->triangles = nullptr;
757 gps->tot_triangles = 0;
758
759 gps->mat_nr = mat_idx;
760
761 gps->dvert = nullptr;
762 gps->editcurve = nullptr;
763
764 return gps;
765}
766
768 bGPDframe *gpf, int mat_idx, int totpoints, short thickness, const bool insert_at_head)
769{
770 bGPDstroke *gps = BKE_gpencil_stroke_new(mat_idx, totpoints, thickness);
771
772 /* Add to frame. */
773 if ((gps != nullptr) && (gpf != nullptr)) {
774 if (!insert_at_head) {
775 BLI_addtail(&gpf->strokes, gps);
776 }
777 else {
778 BLI_addhead(&gpf->strokes, gps);
779 }
780 }
781
782 return gps;
783}
784
785bGPDcurve *BKE_gpencil_stroke_editcurve_new(const int tot_curve_points)
786{
787 bGPDcurve *new_gp_curve = (bGPDcurve *)MEM_callocN(sizeof(bGPDcurve), __func__);
788 new_gp_curve->tot_curve_points = tot_curve_points;
789 new_gp_curve->curve_points = (bGPDcurve_point *)MEM_callocN(
790 sizeof(bGPDcurve_point) * tot_curve_points, __func__);
791
792 return new_gp_curve;
793}
794
795/* ************************************************** */
796/* Data Duplication */
797
799{
800 if (gps_src == nullptr) {
801 return;
802 }
803 BLI_assert(gps_src->totpoints == gps_dst->totpoints);
804
805 BKE_defvert_array_copy(gps_dst->dvert, gps_src->dvert, gps_src->totpoints);
806}
807
809 const bool dup_points,
810 const bool /*dup_curve*/)
811{
812 bGPDstroke *gps_dst = nullptr;
813
814 gps_dst = static_cast<bGPDstroke *>(MEM_dupallocN(gps_src));
815 gps_dst->prev = gps_dst->next = nullptr;
816 gps_dst->triangles = static_cast<bGPDtriangle *>(MEM_dupallocN(gps_src->triangles));
817
818 if (dup_points) {
819 gps_dst->points = static_cast<bGPDspoint *>(MEM_dupallocN(gps_src->points));
820
821 if (gps_src->dvert != nullptr) {
822 gps_dst->dvert = static_cast<MDeformVert *>(MEM_dupallocN(gps_src->dvert));
823 BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst);
824 }
825 else {
826 gps_dst->dvert = nullptr;
827 }
828 }
829 else {
830 gps_dst->points = nullptr;
831 gps_dst->dvert = nullptr;
832 }
833
834 gps_dst->editcurve = nullptr;
835
836 /* return new stroke */
837 return gps_dst;
838}
839
840bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src, const bool dup_strokes)
841{
842 bGPDstroke *gps_dst = nullptr;
843 bGPDframe *gpf_dst;
844
845 /* error checking */
846 if (gpf_src == nullptr) {
847 return nullptr;
848 }
849
850 /* make a copy of the source frame */
851 gpf_dst = static_cast<bGPDframe *>(MEM_dupallocN(gpf_src));
852 gpf_dst->prev = gpf_dst->next = nullptr;
853
854 /* Copy strokes. */
855 BLI_listbase_clear(&gpf_dst->strokes);
856 if (dup_strokes) {
857 LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
858 /* make copy of source stroke */
859 gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true);
860 BLI_addtail(&gpf_dst->strokes, gps_dst);
861 }
862 }
863
864 /* return new frame */
865 return gpf_dst;
866}
867
869 const bool dup_frames,
870 const bool dup_strokes)
871{
872 bGPDframe *gpf_dst;
873 bGPDlayer *gpl_dst;
874
875 /* error checking */
876 if (gpl_src == nullptr) {
877 return nullptr;
878 }
879
880 /* make a copy of source layer */
881 gpl_dst = static_cast<bGPDlayer *>(MEM_dupallocN(gpl_src));
882 gpl_dst->prev = gpl_dst->next = nullptr;
883
884 /* Copy masks. */
885 BKE_gpencil_layer_mask_copy(gpl_src, gpl_dst);
886
887 /* copy frames */
888 BLI_listbase_clear(&gpl_dst->frames);
889 if (dup_frames) {
890 LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) {
891 /* make a copy of source frame */
892 gpf_dst = BKE_gpencil_frame_duplicate(gpf_src, dup_strokes);
893 BLI_addtail(&gpl_dst->frames, gpf_dst);
894
895 /* if source frame was the current layer's 'active' frame, reassign that too */
896 if (gpf_src == gpl_dst->actframe) {
897 gpl_dst->actframe = gpf_dst;
898 }
899 }
900 }
901
902 /* return new layer */
903 return gpl_dst;
904}
905
906bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy)
907{
908 bGPdata *gpd_dst;
909
910 /* Yuck and super-uber-hyper yuck!!!
911 * Should be replaceable with a no-main copy (LIB_ID_COPY_NO_MAIN etc.), but not sure about it,
912 * so for now keep old code for that one. */
913
914 /* error checking */
915 if (gpd_src == nullptr) {
916 return nullptr;
917 }
918
919 if (internal_copy) {
920 /* make a straight copy for undo buffers used during stroke drawing */
921 gpd_dst = static_cast<bGPdata *>(MEM_dupallocN(gpd_src));
922 }
923 else {
924 BLI_assert(bmain != nullptr);
925 gpd_dst = (bGPdata *)BKE_id_copy(bmain, &gpd_src->id);
926 }
927
928 /* Copy internal data (layers, etc.) */
929 greasepencil_copy_data(bmain, std::nullopt, &gpd_dst->id, &gpd_src->id, 0);
930
931 /* return new */
932 return gpd_dst;
933}
934
935/* ************************************************** */
936/* GP Layer API */
937
939{
940 /* Sanity check */
941 if (gpl == nullptr) {
942 return false;
943 }
944
945 /* Layer must be: Visible + Editable */
946 if ((gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) == 0) {
947 return true;
948 }
949
950 /* Something failed */
951 return false;
952}
953
955{
956 /* Search in reverse order, since this is often used for playback/adding,
957 * where it's less likely that we're interested in the earlier frames
958 */
960 if (gpf->framenum == cframe) {
961 return gpf;
962 }
963 }
964
965 return nullptr;
966}
967
969{
970 bGPDframe *gpf = nullptr;
971 bool found = false;
972
973 /* error checking */
974 if (gpl == nullptr) {
975 return nullptr;
976 }
977
978 /* check if there is already an active frame */
979 if (gpl->actframe) {
980 gpf = gpl->actframe;
981
982 /* do not allow any changes to layer's active frame if layer is locked from changes
983 * or if the layer has been set to stay on the current frame
984 */
985 if (gpl->flag & GP_LAYER_FRAMELOCK) {
986 return gpf;
987 }
988 /* do not allow any changes to actframe if frame has painting tag attached to it */
989 if (gpf->flag & GP_FRAME_PAINT) {
990 return gpf;
991 }
992
993 /* try to find matching frame */
994 if (gpf->framenum < cframe) {
995 for (; gpf; gpf = gpf->next) {
996 if (gpf->framenum == cframe) {
997 found = true;
998 break;
999 }
1000 /* If this is the last frame or the next frame is at a later time, we found the right
1001 * frame. */
1002 if (!(gpf->next) || (gpf->next->framenum > cframe)) {
1003 found = true;
1004 break;
1005 }
1006 }
1007
1008 /* set the appropriate frame */
1009 if (addnew) {
1010 if ((found) && (gpf->framenum == cframe)) {
1011 gpl->actframe = gpf;
1012 }
1013 else if (addnew == GP_GETFRAME_ADD_COPY) {
1014 /* The #BKE_gpencil_frame_addcopy function copies the active frame of gpl,
1015 * so we need to set the active frame before copying. */
1016 gpl->actframe = gpf;
1017 gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe);
1018 }
1019 else {
1020 gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
1021 }
1022 }
1023 else if (found) {
1024 gpl->actframe = gpf;
1025 }
1026 else {
1027 gpl->actframe = static_cast<bGPDframe *>(gpl->frames.last);
1028 }
1029 }
1030 else {
1031 for (; gpf; gpf = gpf->prev) {
1032 if (gpf->framenum <= cframe) {
1033 found = true;
1034 break;
1035 }
1036 }
1037
1038 /* set the appropriate frame */
1039 if (addnew) {
1040 if ((found) && (gpf->framenum == cframe)) {
1041 gpl->actframe = gpf;
1042 }
1043 else if (addnew == GP_GETFRAME_ADD_COPY) {
1044 /* The #BKE_gpencil_frame_addcopy function copies the active frame of gpl;
1045 * so we need to set the active frame before copying. */
1046 gpl->actframe = gpf;
1047 gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe);
1048 }
1049 else {
1050 gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
1051 }
1052 }
1053 else if (found) {
1054 gpl->actframe = gpf;
1055 }
1056 else {
1057 gpl->actframe = static_cast<bGPDframe *>(gpl->frames.first);
1058 }
1059 }
1060 }
1061 else if (gpl->frames.first) {
1062 /* check which of the ends to start checking from */
1063 const int first = ((bGPDframe *)(gpl->frames.first))->framenum;
1064 const int last = ((bGPDframe *)(gpl->frames.last))->framenum;
1065
1066 if (abs(cframe - first) > abs(cframe - last)) {
1067 /* find gp-frame which is less than or equal to cframe */
1068 for (gpf = static_cast<bGPDframe *>(gpl->frames.last); gpf; gpf = gpf->prev) {
1069 if (gpf->framenum <= cframe) {
1070 found = true;
1071 break;
1072 }
1073 }
1074 }
1075 else {
1076 /* find gp-frame which is less than or equal to cframe */
1077 for (gpf = static_cast<bGPDframe *>(gpl->frames.first); gpf; gpf = gpf->next) {
1078 if (gpf->framenum <= cframe) {
1079 found = true;
1080 break;
1081 }
1082 }
1083 }
1084
1085 /* set the appropriate frame */
1086 if (addnew) {
1087 if ((found) && (gpf->framenum == cframe)) {
1088 gpl->actframe = gpf;
1089 }
1090 else {
1091 gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
1092 }
1093 }
1094 else if (found) {
1095 gpl->actframe = gpf;
1096 }
1097 else {
1098 /* If delete first frame, need to find one. */
1099 if (gpl->frames.first != nullptr) {
1100 gpl->actframe = static_cast<bGPDframe *>(gpl->frames.first);
1101 }
1102 else {
1103 /* Unresolved erogenous situation! */
1104 CLOG_STR_ERROR(&LOG, "cannot find appropriate gp-frame");
1105 /* `gpl->actframe` should still be nullptr. */
1106 }
1107 }
1108 }
1109 else {
1110 /* currently no frames (add if allowed to) */
1111 if (addnew) {
1112 gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
1113 }
1114 else {
1115 /* don't do anything... this may be when no frames yet! */
1116 /* gpl->actframe should still be nullptr */
1117 }
1118 }
1119
1120 /* Don't select first frame if greater than current frame. */
1121 if ((gpl->actframe != nullptr) && (gpl->actframe == gpl->frames.first) &&
1122 (gpl->actframe->framenum > cframe))
1123 {
1124 gpl->actframe = nullptr;
1125 }
1126
1127 /* return */
1128 return gpl->actframe;
1129}
1130
1132{
1133 bool changed = false;
1134
1135 /* error checking */
1136 if (ELEM(nullptr, gpl, gpf)) {
1137 return false;
1138 }
1139
1140 /* if this frame was active, make the previous frame active instead
1141 * since it's tricky to set active frame otherwise
1142 */
1143 if (gpl->actframe == gpf) {
1144 gpl->actframe = gpf->prev;
1145 }
1146
1147 /* free the frame and its data */
1148 changed = BKE_gpencil_free_strokes(gpf);
1149 BLI_freelinkN(&gpl->frames, gpf);
1150
1151 return changed;
1152}
1153
1155{
1156 if (name[0] == '\0') {
1157 return nullptr;
1158 }
1159 return static_cast<bGPDlayer *>(BLI_findstring(&gpd->layers, name, offsetof(bGPDlayer, info)));
1160}
1161
1163{
1164 BLI_freelinkN(&gpl->mask_layers, mask);
1165 gpl->act_mask--;
1166 CLAMP_MIN(gpl->act_mask, 0);
1167}
1168
1169void BKE_gpencil_layer_mask_remove_ref(bGPdata *gpd, const char *name)
1170{
1171 bGPDlayer_Mask *mask_next;
1172
1173 LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1174 for (bGPDlayer_Mask *mask = static_cast<bGPDlayer_Mask *>(gpl->mask_layers.first); mask;
1175 mask = mask_next)
1176 {
1177 mask_next = mask->next;
1178 if (STREQ(mask->name, name)) {
1180 }
1181 }
1182 }
1183}
1184
1185static int gpencil_cb_sort_masks(const void *arg1, const void *arg2)
1186{
1187 /* sort is inverted as layer list. */
1188 const bGPDlayer_Mask *mask1 = static_cast<const bGPDlayer_Mask *>(arg1);
1189 const bGPDlayer_Mask *mask2 = static_cast<const bGPDlayer_Mask *>(arg2);
1190 int val = 0;
1191
1192 if (mask1->sort_index < mask2->sort_index) {
1193 val = 1;
1194 }
1195 else if (mask1->sort_index > mask2->sort_index) {
1196 val = -1;
1197 }
1198
1199 return val;
1200}
1201
1203{
1204 /* Update sort index. */
1206 bGPDlayer *gpl_mask = BKE_gpencil_layer_named_get(gpd, mask->name);
1207 if (gpl_mask != nullptr) {
1208 mask->sort_index = BLI_findindex(&gpd->layers, gpl_mask);
1209 }
1210 else {
1211 mask->sort_index = 0;
1212 }
1213 }
1215}
1216
1218{
1219 LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1221 }
1222}
1223
1225{
1227 LISTBASE_FOREACH (bGPDlayer_Mask *, mask_src, &gpl_src->mask_layers) {
1228 bGPDlayer_Mask *mask_dst = static_cast<bGPDlayer_Mask *>(MEM_dupallocN(mask_src));
1229 mask_dst->prev = mask_dst->next = nullptr;
1230 BLI_addtail(&gpl_dst->mask_layers, mask_dst);
1231 }
1232}
1233
1235{
1237 if (BKE_gpencil_layer_named_get(gpd, mask->name) == nullptr) {
1239 }
1240 }
1241}
1242
1243static int gpencil_cb_cmp_frame(void *thunk, const void *a, const void *b)
1244{
1245 const bGPDframe *frame_a = static_cast<const bGPDframe *>(a);
1246 const bGPDframe *frame_b = static_cast<const bGPDframe *>(b);
1247
1248 if (frame_a->framenum < frame_b->framenum) {
1249 return -1;
1250 }
1251 if (frame_a->framenum > frame_b->framenum) {
1252 return 1;
1253 }
1254 if (thunk != nullptr) {
1255 *((bool *)thunk) = true;
1256 }
1257 /* Sort selected last. */
1258 if ((frame_a->flag & GP_FRAME_SELECT) && ((frame_b->flag & GP_FRAME_SELECT) == 0)) {
1259 return 1;
1260 }
1261 return 0;
1262}
1263
1264void BKE_gpencil_layer_frames_sort(bGPDlayer *gpl, bool *r_has_duplicate_frames)
1265{
1266 BLI_listbase_sort_r(&gpl->frames, gpencil_cb_cmp_frame, r_has_duplicate_frames);
1267}
1268
1270{
1271 /* error checking */
1272 if (ELEM(nullptr, gpd, gpd->layers.first)) {
1273 return nullptr;
1274 }
1275
1276 /* loop over layers until found (assume only one active) */
1277 LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1278 if (gpl->flag & GP_LAYER_ACTIVE) {
1279 return gpl;
1280 }
1281 }
1282
1283 /* no active layer found */
1284 return nullptr;
1285}
1286
1288{
1289 /* error checking */
1290 if (ELEM(nullptr, gpd, gpd->layers.first, active)) {
1291 return;
1292 }
1293
1294 /* loop over layers deactivating all */
1295 LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1296 gpl->flag &= ~GP_LAYER_ACTIVE;
1297 if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
1298 gpl->flag |= GP_LAYER_LOCKED;
1299 }
1300 }
1301
1302 /* set as active one */
1303 active->flag |= GP_LAYER_ACTIVE;
1304 if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
1305 active->flag &= ~GP_LAYER_LOCKED;
1306 }
1307}
1308
1309void BKE_gpencil_layer_autolock_set(bGPdata *gpd, const bool unlock)
1310{
1311 BLI_assert(gpd != nullptr);
1312
1313 if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
1314 bGPDlayer *layer_active = BKE_gpencil_layer_active_get(gpd);
1315
1316 /* Lock all other layers */
1317 LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1318 /* unlock active layer */
1319 if (gpl == layer_active) {
1320 gpl->flag &= ~GP_LAYER_LOCKED;
1321 }
1322 else {
1323 gpl->flag |= GP_LAYER_LOCKED;
1324 }
1325 }
1326 }
1327 else {
1328 /* If disable is better unlock all layers by default or it looks there is
1329 * a problem in the UI because the user expects all layers will be unlocked
1330 */
1331 if (unlock) {
1332 LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1333 gpl->flag &= ~GP_LAYER_LOCKED;
1334 }
1335 }
1336 }
1337}
1338
1340{
1341 /* error checking */
1342 if (ELEM(nullptr, gpd, gpl)) {
1343 return;
1344 }
1345
1346 /* free layer */
1348
1349 /* Free Masks. */
1351
1352 /* Remove any reference to that layer in masking lists. */
1354
1355 /* free icon providing preview of icon color */
1357
1358 BLI_freelinkN(&gpd->layers, gpl);
1359}
1360
1362{
1363 BLI_assert(brush);
1365 if (brush->gpencil_settings->material != ma) {
1366 if (brush->gpencil_settings->material) {
1368 }
1369 if (ma) {
1370 id_us_plus(&ma->id);
1371 }
1372 brush->gpencil_settings->material = ma;
1374 }
1375}
1376
1377void BKE_gpencil_frame_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_endframe)
1378{
1379 *r_initframe = gpl->actframe->framenum;
1380 *r_endframe = gpl->actframe->framenum;
1381
1382 LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
1383 if (gpf->flag & GP_FRAME_SELECT) {
1384 if (gpf->framenum < *r_initframe) {
1385 *r_initframe = gpf->framenum;
1386 }
1387 if (gpf->framenum > *r_endframe) {
1388 *r_endframe = gpf->framenum;
1389 }
1390 }
1391 }
1392}
1393
1395 bGPDframe *gpf, int actnum, int f_init, int f_end, CurveMapping *cur_falloff)
1396{
1397 float fnum = 0.5f; /* default mid curve */
1398 float value;
1399
1400 /* check curve is available */
1401 if (cur_falloff == nullptr) {
1402 return 1.0f;
1403 }
1404
1405 /* frames to the right of the active frame */
1406 if (gpf->framenum < actnum) {
1407 fnum = float(gpf->framenum - f_init) / (actnum - f_init);
1408 fnum *= 0.5f;
1409 value = BKE_curvemapping_evaluateF(cur_falloff, 0, fnum);
1410 }
1411 /* frames to the left of the active frame */
1412 else if (gpf->framenum > actnum) {
1413 fnum = float(gpf->framenum - actnum) / (f_end - actnum);
1414 fnum *= 0.5f;
1415 value = BKE_curvemapping_evaluateF(cur_falloff, 0, fnum + 0.5f);
1416 }
1417 else {
1418 /* Center of the curve. */
1419 value = BKE_curvemapping_evaluateF(cur_falloff, 0, 0.5f);
1420 }
1421
1422 return value;
1423}
1424
1426{
1427 const char *hexcol[] = {
1428 "FFFFFF", "F2F2F2", "E6E6E6", "D9D9D9", "CCCCCC", "BFBFBF", "B2B2B2", "A6A6A6", "999999",
1429 "8C8C8C", "808080", "737373", "666666", "595959", "4C4C4C", "404040", "333333", "262626",
1430 "1A1A1A", "000000", "F2FC24", "FFEA00", "FEA711", "FE8B68", "FB3B02", "FE3521", "D00000",
1431 "A81F3D", "780422", "2B0000", "F1E2C5", "FEE4B3", "FEDABB", "FEC28E", "D88F57", "BD6340",
1432 "A2402B", "63352D", "6B2833", "34120C", "E7CB8F", "D1B38B", "C1B17F", "D7980B", "FFB100",
1433 "FE8B00", "FF6A00", "B74100", "5F3E1D", "3B2300", "FECADA", "FE65CB", "FE1392", "DD3062",
1434 "C04A6D", "891688", "4D2689", "441521", "2C1139", "241422", "FFFF7D", "FFFF00", "FF7F00",
1435 "FF7D7D", "FF7DFF", "FF00FE", "FF007F", "FF0000", "7F0000", "0A0A00", "F6FDFF", "E9F7FF",
1436 "CFE6FE", "AAC7FE", "77B3FE", "1E74FD", "0046AA", "2F4476", "003052", "0E0E25", "EEF5F0",
1437 "D6E5DE", "ACD8B9", "6CADC6", "42A9AF", "007F7F", "49675C", "2E4E4E", "1D3239", "0F1C21",
1438 "D8FFF4", "B8F4F5", "AECCB5", "76C578", "358757", "409B68", "468768", "1F512B", "2A3C37",
1439 "122E1D", "EFFFC9", "E6F385", "BCF51C", "D4DC18", "82D322", "5C7F00", "59932B", "297F00",
1440 "004320", "1C3322", "00FF7F", "00FF00", "7DFF7D", "7DFFFF", "00FFFF", "7D7DFF", "7F00FF",
1441 "0000FF", "3F007F", "00007F"};
1442
1443 ToolSettings *ts = scene->toolsettings;
1444 if (ts->gp_paint->paint.palette != nullptr) {
1445 return;
1446 }
1447
1448 /* Try to find the default palette. */
1449 const char *palette_id = "Palette";
1450 Palette *palette = static_cast<Palette *>(
1451 BLI_findstring(&bmain->palettes, palette_id, offsetof(ID, name) + 2));
1452
1453 if (palette == nullptr) {
1454 /* Fall back to the first palette. */
1455 palette = static_cast<Palette *>(bmain->palettes.first);
1456 }
1457
1458 if (palette == nullptr) {
1459 /* Fall back to creating a palette. */
1460 palette = BKE_palette_add(bmain, palette_id);
1461 id_us_min(&palette->id);
1462
1463 /* Create Colors. */
1464 for (int i = 0; i < ARRAY_SIZE(hexcol); i++) {
1465 PaletteColor *palcol = BKE_palette_color_add(palette);
1466 hex_to_rgb(hexcol[i], palcol->rgb, palcol->rgb + 1, palcol->rgb + 2);
1467 }
1468 }
1469
1470 BLI_assert(palette != nullptr);
1471 BKE_paint_palette_set(&ts->gp_paint->paint, palette);
1473}
1481static bool gpencil_is_layer_mask(ViewLayer *view_layer, bGPdata *gpd, bGPDlayer *gpl_mask)
1482{
1483 LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1484 if ((gpl->viewlayername[0] != '\0') && !STREQ(view_layer->name, gpl->viewlayername)) {
1485 continue;
1486 }
1487
1488 /* Skip if masks are disabled for this view layer. */
1489 if (gpl->flag & GP_LAYER_DISABLE_MASKS_IN_VIEWLAYER) {
1490 continue;
1491 }
1492
1493 LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl->mask_layers) {
1494 if (STREQ(gpl_mask->info, mask->name)) {
1495 return true;
1496 }
1497 }
1498 }
1499
1500 return false;
1501}
1502
1503/* -------------------------------------------------------------------- */
1511 Object *ob,
1512 gpIterCb layer_cb,
1513 gpIterCb stroke_cb,
1514 void *thunk,
1515 bool do_onion,
1516 int cfra)
1517{
1518 bGPdata *gpd = (bGPdata *)ob->data;
1519 const bool is_multiedit = (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd) && !GPENCIL_PLAY_ON(gpd));
1520 const bool is_onion = do_onion && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0);
1521 const bool is_drawing = (gpd->runtime.sbuffer_used > 0);
1522
1523 /* Onion skinning. */
1524 const bool onion_mode_abs = (gpd->onion_mode == GP_ONION_MODE_ABSOLUTE);
1525 const bool onion_mode_sel = (gpd->onion_mode == GP_ONION_MODE_SELECTED);
1526 const bool onion_loop = (gpd->onion_flag & GP_ONION_LOOP) != 0;
1527 const short onion_keytype = gpd->onion_keytype;
1528
1529 LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1530 /* Reset by layer. */
1531 bool is_before_first = false;
1532
1533 bGPDframe *act_gpf = gpl->actframe;
1534 bGPDframe *sta_gpf = act_gpf;
1535 bGPDframe *end_gpf = act_gpf ? act_gpf->next : nullptr;
1536 float prev_opacity = gpl->opacity;
1537
1538 if (gpl->flag & GP_LAYER_HIDE) {
1539 continue;
1540 }
1541
1542 /* If scale to 0 the layer must be invisible. */
1543 if (is_zero_v3(gpl->scale)) {
1544 continue;
1545 }
1546
1547 /* Hide the layer if it's defined a view layer filter. This is used to
1548 * generate renders, putting only selected GP layers for each View Layer.
1549 * This is used only in final render and never in Viewport. */
1550 if ((view_layer != nullptr) && (gpl->viewlayername[0] != '\0') &&
1551 !STREQ(view_layer->name, gpl->viewlayername))
1552 {
1553 /* Do not skip masks when rendering the view-layer so that it can still be used to clip
1554 * other layers. Instead set their opacity to zero. */
1555 if (gpencil_is_layer_mask(view_layer, gpd, gpl)) {
1556 gpl->opacity = 0.0f;
1557 }
1558 else {
1559 continue;
1560 }
1561 }
1562
1563 if (is_multiedit) {
1564 sta_gpf = end_gpf = nullptr;
1565 /* Check the whole range and tag the editable frames. */
1566 LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
1567 if (act_gpf != nullptr && (gpf == act_gpf || (gpf->flag & GP_FRAME_SELECT))) {
1568 gpf->runtime.onion_id = 0;
1569 if (do_onion) {
1570 if (gpf->framenum < act_gpf->framenum) {
1571 gpf->runtime.onion_id = -1;
1572 }
1573 else {
1574 gpf->runtime.onion_id = 1;
1575 }
1576 }
1577
1578 if (sta_gpf == nullptr) {
1579 sta_gpf = gpf;
1580 }
1581 end_gpf = gpf->next;
1582 }
1583 else {
1584 gpf->runtime.onion_id = INT_MAX;
1585 }
1586 }
1587 }
1588 else if (is_onion && (gpl->onion_flag & GP_LAYER_ONIONSKIN)) {
1589 /* Special cases when cframe is before first frame. */
1590 bGPDframe *gpf_first = static_cast<bGPDframe *>(gpl->frames.first);
1591 if ((gpf_first != nullptr) && (act_gpf != nullptr) &&
1592 (gpf_first->framenum > act_gpf->framenum))
1593 {
1594 is_before_first = true;
1595 }
1596 if ((gpf_first != nullptr) && (act_gpf == nullptr)) {
1597 act_gpf = gpf_first;
1598 is_before_first = true;
1599 }
1600
1601 if (act_gpf) {
1602 bGPDframe *last_gpf = static_cast<bGPDframe *>(gpl->frames.last);
1603
1604 int frame_len = 0;
1605 LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
1606 gpf->runtime.frameid = frame_len++;
1607 }
1608
1609 LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
1610 bool is_wrong_keytype = (onion_keytype > -1) && (gpf->key_type != onion_keytype);
1611 bool is_in_range;
1612 int delta = (onion_mode_abs) ? (gpf->framenum - cfra) :
1613 (gpf->runtime.frameid - act_gpf->runtime.frameid);
1614
1615 if (is_before_first) {
1616 delta++;
1617 }
1618
1619 if (onion_mode_sel) {
1620 is_in_range = (gpf->flag & GP_FRAME_SELECT) != 0;
1621 }
1622 else {
1623 is_in_range = (-delta <= gpd->gstep) && (delta <= gpd->gstep_next);
1624
1625 if (onion_loop && !is_in_range) {
1626 /* We wrap the value using the last frame and 0 as reference. */
1627 /* FIXME: This might not be good for animations not starting at 0. */
1628 int shift = (onion_mode_abs) ? last_gpf->framenum : last_gpf->runtime.frameid;
1629 delta += (delta < 0) ? (shift + 1) : -(shift + 1);
1630 /* Test again with wrapped value. */
1631 is_in_range = (-delta <= gpd->gstep) && (delta <= gpd->gstep_next);
1632 }
1633 }
1634 /* Mask frames that have wrong keytype of are not in range. */
1635 gpf->runtime.onion_id = (is_wrong_keytype || !is_in_range) ? INT_MAX : delta;
1636 }
1637 /* Active frame is always shown. */
1638 if (!is_before_first || is_drawing) {
1639 act_gpf->runtime.onion_id = 0;
1640 }
1641 }
1642
1643 sta_gpf = static_cast<bGPDframe *>(gpl->frames.first);
1644 end_gpf = nullptr;
1645 }
1646 else {
1647 /* Bypass multiedit/onion skinning. */
1648 end_gpf = sta_gpf = nullptr;
1649 }
1650
1651 if (sta_gpf == nullptr && act_gpf == nullptr) {
1652 if (layer_cb) {
1653 layer_cb(gpl, act_gpf, nullptr, thunk);
1654 }
1655 gpl->opacity = prev_opacity;
1656 continue;
1657 }
1658
1659 /* Draw multiedit/onion skinning first */
1660 for (bGPDframe *gpf = sta_gpf; gpf && gpf != end_gpf; gpf = gpf->next) {
1661 if ((gpf->runtime.onion_id == INT_MAX || gpf == act_gpf) && (!is_before_first)) {
1662 continue;
1663 }
1664
1665 /* Only do once for frame before first. */
1666 if (is_before_first && gpf == act_gpf) {
1667 is_before_first = false;
1668 }
1669
1670 if (layer_cb) {
1671 layer_cb(gpl, gpf, nullptr, thunk);
1672 }
1673
1674 if (stroke_cb) {
1675 LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
1676 if (gps->totpoints == 0) {
1677 continue;
1678 }
1679 stroke_cb(gpl, gpf, gps, thunk);
1680 }
1681 }
1682 }
1683 /* Draw Active frame on top. */
1684 /* Use evaluated frame (with modifiers for active stroke)/ */
1685 act_gpf = gpl->actframe;
1686 if (act_gpf) {
1687 act_gpf->runtime.onion_id = 0;
1688 if (layer_cb) {
1689 layer_cb(gpl, act_gpf, nullptr, thunk);
1690 }
1691
1692 /* If layer solo mode and Paint mode, only keyframes with data are displayed. */
1693 if (GPENCIL_PAINT_MODE(gpd) && (gpl->flag & GP_LAYER_SOLO_MODE) &&
1694 (act_gpf->framenum != cfra))
1695 {
1696 gpl->opacity = prev_opacity;
1697 continue;
1698 }
1699 if (stroke_cb) {
1700 LISTBASE_FOREACH (bGPDstroke *, gps, &act_gpf->strokes) {
1701 if (gps->totpoints == 0) {
1702 continue;
1703 }
1704 stroke_cb(gpl, act_gpf, gps, thunk);
1705 }
1706 }
1707 }
1708
1709 /* Restore the opacity in case it was overwritten (used to hide masks in render). */
1710 gpl->opacity = prev_opacity;
1711 }
1712}
1713
1715 const bGPDframe *gpf_eval)
1716{
1717 bGPDstroke *gps_eval = static_cast<bGPDstroke *>(gpf_eval->strokes.first);
1718 LISTBASE_FOREACH (bGPDstroke *, gps_orig, &gpf_orig->strokes) {
1719
1720 /* Assign original stroke pointer. */
1721 if (gps_eval != nullptr) {
1722 gps_eval->runtime.gps_orig = gps_orig;
1723
1724 /* Assign original point pointer. */
1725 for (int i = 0; i < gps_orig->totpoints; i++) {
1726 if (i > gps_eval->totpoints - 1) {
1727 break;
1728 }
1729 bGPDspoint *pt_orig = &gps_orig->points[i];
1730 bGPDspoint *pt_eval = &gps_eval->points[i];
1731 pt_orig->runtime.pt_orig = nullptr;
1732 pt_orig->runtime.idx_orig = i;
1733 pt_eval->runtime.pt_orig = pt_orig;
1734 pt_eval->runtime.idx_orig = i;
1735 }
1736 /* Increase pointer. */
1737 gps_eval = gps_eval->next;
1738 }
1739 }
1740}
1741
1743 const bGPDlayer *gpl_eval)
1744{
1745 bGPDframe *gpf_eval = static_cast<bGPDframe *>(gpl_eval->frames.first);
1746 LISTBASE_FOREACH (bGPDframe *, gpf_orig, &gpl_orig->frames) {
1747 if (gpf_eval != nullptr) {
1748 /* Update frame reference pointers. */
1749 gpf_eval->runtime.gpf_orig = (bGPDframe *)gpf_orig;
1751 gpf_eval = gpf_eval->next;
1752 }
1753 }
1754}
1755
1756void BKE_gpencil_data_update_orig_pointers(const bGPdata *gpd_orig, const bGPdata *gpd_eval)
1757{
1758 /* Assign pointers to the original stroke and points to the evaluated data. This must
1759 * be done before applying any modifier because at this moment the structure is equals,
1760 * so we can assume the layer index is the same in both data-blocks.
1761 * This data will be used by operators. */
1762
1763 bGPDlayer *gpl_eval = static_cast<bGPDlayer *>(gpd_eval->layers.first);
1764 LISTBASE_FOREACH (bGPDlayer *, gpl_orig, &gpd_orig->layers) {
1765 if (gpl_eval != nullptr) {
1766 /* Update layer reference pointers. */
1767 gpl_eval->runtime.gpl_orig = gpl_orig;
1769 gpl_eval = gpl_eval->next;
1770 }
1771 }
1772}
1773
1774void BKE_gpencil_update_orig_pointers(const Object *ob_orig, const Object *ob_eval)
1775{
1777}
1778
1780 Object *obact,
1781 bGPDlayer *gpl,
1782 float diff_mat[4][4])
1783{
1784 Object *ob_eval = depsgraph != nullptr ? DEG_get_evaluated_object(depsgraph, obact) : obact;
1785 Object *obparent = gpl->parent;
1786 Object *obparent_eval = depsgraph != nullptr ? DEG_get_evaluated_object(depsgraph, obparent) :
1787 obparent;
1788
1789 /* if not layer parented, try with object parented */
1790 if (obparent_eval == nullptr) {
1791 if ((ob_eval != nullptr) && (ob_eval->type == OB_GPENCIL_LEGACY)) {
1792 copy_m4_m4(diff_mat, ob_eval->object_to_world().ptr());
1793 mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat);
1794 return;
1795 }
1796 /* not gpencil object */
1797 unit_m4(diff_mat);
1798 return;
1799 }
1800
1801 if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) {
1802 mul_m4_m4m4(diff_mat, obparent_eval->object_to_world().ptr(), gpl->inverse);
1803 add_v3_v3(diff_mat[3], ob_eval->object_to_world().location());
1804 mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat);
1805 return;
1806 }
1807 if (gpl->partype == PARBONE) {
1808 bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr);
1809 if (pchan) {
1810 float tmp_mat[4][4];
1811 mul_m4_m4m4(tmp_mat, obparent_eval->object_to_world().ptr(), pchan->pose_mat);
1812 mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse);
1813 add_v3_v3(diff_mat[3], ob_eval->object_to_world().location());
1814 }
1815 else {
1816 /* if bone not found use object (armature) */
1817 mul_m4_m4m4(diff_mat, obparent_eval->object_to_world().ptr(), gpl->inverse);
1818 add_v3_v3(diff_mat[3], ob_eval->object_to_world().location());
1819 }
1820 mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat);
1821 return;
1822 }
1823
1824 unit_m4(diff_mat); /* not defined type */
1825}
1826
1828{
1829 if (ob->type != OB_GPENCIL_LEGACY) {
1830 return;
1831 }
1832
1833 bGPdata *gpd = (bGPdata *)ob->data;
1834 float cur_mat[4][4];
1835
1836 LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1837 bool changed = false;
1838 unit_m4(cur_mat);
1839
1840 /* Skip non-visible layers. */
1841 if (gpl->flag & GP_LAYER_HIDE || is_zero_v3(gpl->scale)) {
1842 continue;
1843 }
1844
1845 /* Skip empty layers. */
1846 if (BLI_listbase_is_empty(&gpl->frames)) {
1847 continue;
1848 }
1849
1850 /* Determine frame range to transform. */
1851 bGPDframe *gpf_start = nullptr;
1852 bGPDframe *gpf_end = nullptr;
1853
1854 /* If onion skinning is activated, consider all frames. */
1855 if (gpl->onion_flag & GP_LAYER_ONIONSKIN) {
1856 gpf_start = static_cast<bGPDframe *>(gpl->frames.first);
1857 }
1858 /* Otherwise, consider only active frame. */
1859 else {
1860 /* Skip layer if it has no active frame to transform. */
1861 if (gpl->actframe == nullptr) {
1862 continue;
1863 }
1864 gpf_start = gpl->actframe;
1865 gpf_end = gpl->actframe->next;
1866 }
1867
1868 if (gpl->parent != nullptr) {
1869 Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent);
1870 /* calculate new matrix */
1871 if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) {
1872 mul_m4_m4m4(cur_mat, ob->world_to_object().ptr(), ob_parent->object_to_world().ptr());
1873 }
1874 else if (gpl->partype == PARBONE) {
1875 bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr);
1876 if (pchan != nullptr) {
1877 mul_m4_series(cur_mat,
1878 ob->world_to_object().ptr(),
1879 ob_parent->object_to_world().ptr(),
1880 pchan->pose_mat);
1881 }
1882 else {
1883 unit_m4(cur_mat);
1884 }
1885 }
1886 changed = !equals_m4m4(gpl->inverse, cur_mat);
1887 }
1888
1889 /* Calc local layer transform. Early out if we have non-animated zero transforms. */
1890 bool transformed = (!is_zero_v3(gpl->location) || !is_zero_v3(gpl->rotation) ||
1891 !is_one_v3(gpl->scale));
1892 float tmp_mat[4][4];
1893 loc_eul_size_to_mat4(tmp_mat, gpl->location, gpl->rotation, gpl->scale);
1894 transformed |= !equals_m4m4(gpl->layer_mat, tmp_mat);
1895 if (transformed) {
1896 copy_m4_m4(gpl->layer_mat, tmp_mat);
1897 }
1898
1899 /* Continue if no transformations are applied to this layer. */
1900 if (!changed && !transformed) {
1901 continue;
1902 }
1903
1904 /* Iterate over frame range. */
1905 for (bGPDframe *gpf = gpf_start; gpf != nullptr && gpf != gpf_end; gpf = gpf->next) {
1906 /* Skip frames without a valid onion skinning id (NOTE: active frame has one). */
1907 if (gpf->runtime.onion_id == INT_MAX) {
1908 continue;
1909 }
1910
1911 /* Apply transformations only if needed. */
1912 if (changed || transformed) {
1913 LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
1914 bGPDspoint *pt;
1915 int i;
1916 for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1917 if (changed) {
1918 mul_m4_v3(gpl->inverse, &pt->x);
1919 mul_m4_v3(cur_mat, &pt->x);
1920 }
1921
1922 if (transformed) {
1923 mul_m4_v3(gpl->layer_mat, &pt->x);
1924 }
1925 }
1926 }
1927 }
1928 }
1929 }
1930}
1931
1933{
1934 const int name_prefix_len = strlen(name_prefix);
1935 for (int i = 0; i < ob->totcol; i++) {
1936 Material *ma = BKE_object_material_get(ob, i + 1);
1937 if ((ma != nullptr) && (ma->gp_style != nullptr) &&
1938 STREQLEN(ma->id.name + 2, name_prefix, name_prefix_len))
1939 {
1940 return i;
1941 }
1942 }
1943
1944 return -1;
1945}
1946
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
void BKE_brush_tag_unsaved_changes(Brush *brush)
Definition brush.cc:621
float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value)
support for deformation groups and hooks.
void BKE_defvert_blend_write(BlendWriter *writer, int count, const MDeformVert *dvlist)
Definition deform.cc:1642
void BKE_defbase_blend_write(BlendWriter *writer, const ListBase *defbase)
Definition deform.cc:1635
void BKE_defvert_array_copy(MDeformVert *dst, const MDeformVert *src, int totvert)
Definition deform.cc:1029
void BKE_defgroup_copy_list(ListBase *outbase, const ListBase *inbase)
Definition deform.cc:76
void BKE_defvert_blend_read(BlendDataReader *reader, int count, MDeformVert *mdverts)
Definition deform.cc:1659
void(* gpIterCb)(struct bGPDlayer *layer, struct bGPDframe *frame, struct bGPDstroke *stroke, void *thunk)
eGP_GetFrame_Mode
@ GP_GETFRAME_ADD_COPY
void BKE_gpencil_free_update_cache(struct bGPdata *gpd)
bool BKE_icon_delete(int icon_id)
Definition icons.cc:469
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition BKE_idtype.hh:39
void * BKE_libblock_alloc(Main *bmain, short type, const char *name, int flag) ATTR_WARN_UNUSED_RESULT
Definition lib_id.cc:1415
void id_us_plus(ID *id)
Definition lib_id.cc:351
ID * BKE_id_copy(Main *bmain, const ID *id)
Definition lib_id.cc:765
void id_us_min(ID *id)
Definition lib_id.cc:359
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2560
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
@ IDWALK_CB_USER
@ IDWALK_CB_NOP
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
PaletteColor * BKE_palette_color_add(Palette *palette)
Definition paint.cc:1392
Palette * BKE_palette_add(Main *bmain, const char *name)
Definition paint.cc:1386
void BKE_paint_palette_set(Paint *paint, Palette *palette)
Definition paint.cc:1350
#define BLI_assert(a)
Definition BLI_assert.h:50
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:90
#define LISTBASE_FOREACH(type, var, list)
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:269
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:331
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void void BLI_listbase_sort(struct ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:370
void void void BLI_listbase_sort_r(ListBase *listbase, int(*cmp)(void *, const void *, const void *), void *thunk) ATTR_NONNULL(1
void hex_to_rgb(const char *hexcol, float *r_r, float *r_g, float *r_b)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void unit_m4(float m[4][4])
Definition rct.c:1127
void mul_m4_v3(const float M[4][4], float r[3])
#define mul_m4_series(...)
bool equals_m4m4(const float mat1[4][4], const float mat2[4][4])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void loc_eul_size_to_mat4(float R[4][4], const float loc[3], const float eul[3], const float size[3])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE bool is_one_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE bool is_zero_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE void copy_v2_fl(float r[2], float f)
#define STRNCPY_UTF8(dst, src)
void BLI_uniquename(const struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_maxncpy) ATTR_NONNULL(1
#define ARRAY_SIZE(arr)
#define ARRAY_SET_ITEMS(...)
#define STREQLEN(a, b, n)
#define ELEM(...)
#define STREQ(a, b)
#define CLAMP_MIN(a, b)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_read_struct_array(reader, struct_name, array_size, ptr_p)
#define BLO_write_struct_list(writer, struct_name, list_ptr)
void BLO_read_pointer_array(BlendDataReader *reader, int array_size, void **ptr_p)
Definition readfile.cc:5052
#define BLO_read_struct(reader, struct_name, ptr_p)
void BLO_write_pointer_array(BlendWriter *writer, uint num, const void *data_ptr)
#define BLT_I18NCONTEXT_ID_GPENCIL
#define DATA_(msgid)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
#define CLOG_STR_ERROR(clg_ref, str)
Definition CLG_log.h:188
void DEG_id_tag_update(ID *id, unsigned int flags)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
#define FILTER_ID_GD_LEGACY
Definition DNA_ID.h:1169
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1021
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
#define FILTER_ID_MA
Definition DNA_ID.h:1175
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:654
@ INDEX_ID_GD_LEGACY
Definition DNA_ID.h:1258
@ ID_GD_LEGACY
@ GP_ONION_MODE_RELATIVE
@ GP_ONION_MODE_SELECTED
@ GP_ONION_MODE_ABSOLUTE
#define GP_DEFAULT_CURVE_EDIT_CORNER_ANGLE
#define GP_DEFAULT_PIX_FACTOR
#define GPENCIL_PLAY_ON(gpd)
#define GP_DEFAULT_CURVE_RESOLUTION
#define GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)
#define GPENCIL_PAINT_MODE(gpd)
struct bGPdata bGPdata
@ GP_LAYER_DISABLE_MASKS_IN_VIEWLAYER
#define GP_DEFAULT_GRID_LINES
#define GP_DEFAULT_CURVE_ERROR
@ GP_ONION_GHOST_NEXTCOL
@ GP_ONION_GHOST_PREVCOL
@ GP_DATA_SHOW_ONIONSKINS
@ GP_DATA_CURVE_ADAPTIVE_RESOLUTION
@ GP_DATA_STROKE_WEIGHTMODE
@ GP_DATA_AUTOLOCK_LAYERS
@ PARSKEL
@ PAROBJECT
@ PARBONE
@ OB_GPENCIL_LEGACY
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static float frame_len(const Frame *frame)
Definition MOD_skin.cc:384
unsigned int U
Definition btGjkEpa3.h:78
local_group_size(16, 16) .push_constant(Type b
const Depsgraph * depsgraph
#define offsetof(t, d)
draw_view in_light_buf[] float
static void greasepencil_copy_data(Main *, std::optional< Library * >, ID *id_dst, const ID *id_src, const int)
bGPDframe * BKE_gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
bGPDframe * BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src, const bool dup_strokes)
void BKE_gpencil_tag(bGPdata *gpd)
void BKE_gpencil_free_stroke_weights(bGPDstroke *gps)
bGPDframe * BKE_gpencil_layer_frame_get(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
bGPDstroke * BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src, const bool dup_points, const bool)
void BKE_gpencil_frame_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_endframe)
void BKE_gpencil_layer_mask_copy(const bGPDlayer *gpl_src, bGPDlayer *gpl_dst)
bGPDlayer * BKE_gpencil_layer_named_get(bGPdata *gpd, const char *name)
bGPdata * BKE_gpencil_data_addnew(Main *bmain, const char name[])
void BKE_gpencil_batch_cache_free(bGPdata *gpd)
bGPDlayer * BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src, const bool dup_frames, const bool dup_strokes)
void BKE_gpencil_free_frames(bGPDlayer *gpl)
static int gpencil_cb_sort_masks(const void *arg1, const void *arg2)
bGPDlayer * BKE_gpencil_layer_active_get(bGPdata *gpd)
void BKE_gpencil_free_point_weights(MDeformVert *dvert)
static bool gpencil_is_layer_mask(ViewLayer *view_layer, bGPdata *gpd, bGPDlayer *gpl_mask)
bGPDstroke * BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness)
void BKE_gpencil_layer_mask_remove(bGPDlayer *gpl, bGPDlayer_Mask *mask)
bool BKE_gpencil_layer_is_editable(const bGPDlayer *gpl)
void(* BKE_gpencil_batch_cache_dirty_tag_cb)(bGPdata *gpd)
bGPDcurve * BKE_gpencil_stroke_editcurve_new(const int tot_curve_points)
void BKE_gpencil_free_stroke_editcurve(bGPDstroke *gps)
void BKE_gpencil_layer_autolock_set(bGPdata *gpd, const bool unlock)
void BKE_gpencil_free_layers(ListBase *list)
void BKE_gpencil_stroke_weights_duplicate(bGPDstroke *gps_src, bGPDstroke *gps_dst)
static void greasepencil_blend_write(BlendWriter *writer, ID *id, const void *id_address)
static void greasepencil_free_data(ID *id)
bool BKE_gpencil_free_strokes(bGPDframe *gpf)
void BKE_gpencil_layer_frames_sort(bGPDlayer *gpl, bool *r_has_duplicate_frames)
void BKE_gpencil_layer_original_pointers_update(const bGPDlayer *gpl_orig, const bGPDlayer *gpl_eval)
void BKE_gpencil_palette_ensure(Main *bmain, Scene *scene)
void BKE_gpencil_visible_stroke_advanced_iter(ViewLayer *view_layer, Object *ob, gpIterCb layer_cb, gpIterCb stroke_cb, void *thunk, bool do_onion, int cfra)
void BKE_gpencil_free_legacy_palette_data(ListBase *list)
bGPDstroke * BKE_gpencil_stroke_add(bGPDframe *gpf, int mat_idx, int totpoints, short thickness, const bool insert_at_head)
void BKE_gpencil_free_layer_masks(bGPDlayer *gpl)
bGPdata * BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy)
static int gpencil_cb_cmp_frame(void *thunk, const void *a, const void *b)
void BKE_gpencil_update_layer_transforms(const Depsgraph *depsgraph, Object *ob)
void(* BKE_gpencil_batch_cache_free_cb)(bGPdata *gpd)
bGPDframe * BKE_gpencil_layer_frame_find(bGPDlayer *gpl, int cframe)
void BKE_gpencil_update_orig_pointers(const Object *ob_orig, const Object *ob_eval)
static void greasepencil_foreach_id(ID *id, LibraryForeachIDData *data)
void BKE_gpencil_layer_mask_remove_ref(bGPdata *gpd, const char *name)
bGPDframe * BKE_gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
void BKE_gpencil_batch_cache_dirty_tag(bGPdata *gpd)
void BKE_gpencil_blend_read_data(BlendDataReader *reader, bGPdata *gpd)
bool BKE_gpencil_layer_frame_delete(bGPDlayer *gpl, bGPDframe *gpf)
float BKE_gpencil_multiframe_falloff_calc(bGPDframe *gpf, int actnum, int f_init, int f_end, CurveMapping *cur_falloff)
void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, float diff_mat[4][4])
int BKE_gpencil_material_find_index_by_name_prefix(Object *ob, const char *name_prefix)
IDTypeInfo IDType_ID_GD_LEGACY
void BKE_gpencil_layer_mask_sort_all(bGPdata *gpd)
static CLG_LogRef LOG
void BKE_gpencil_frame_original_pointers_update(const bGPDframe *gpf_orig, const bGPDframe *gpf_eval)
void BKE_gpencil_layer_mask_cleanup(bGPdata *gpd, bGPDlayer *gpl)
void BKE_gpencil_data_update_orig_pointers(const bGPdata *gpd_orig, const bGPdata *gpd_eval)
void BKE_gpencil_free_data(bGPdata *gpd, bool free_all)
void BKE_gpencil_free_stroke(bGPDstroke *gps)
bGPDlayer * BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, const bool setactive, const bool add_to_header)
void BKE_gpencil_brush_material_set(Brush *brush, Material *ma)
static void greasepencil_blend_read_data(BlendDataReader *reader, ID *id)
void BKE_gpencil_layer_active_set(bGPdata *gpd, bGPDlayer *active)
void BKE_gpencil_layer_mask_sort(bGPdata *gpd, bGPDlayer *gpl)
void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl)
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
ccl_device_inline float4 mask(const int4 mask, const float4 a)
static ulong state[N]
struct Material * material
struct BrushGpencilSettings * gpencil_settings
Definition DNA_ID.h:413
char name[66]
Definition DNA_ID.h:425
void * last
void * first
struct MDeformWeight * dw
ListBase palettes
Definition BKE_main.hh:237
struct MaterialGPencilStyle * gp_style
struct bPose * pose
struct Palette * palette
GpVertexPaint * gp_vertexpaint
char name[64]
bGPDcurve_point * curve_points
struct bGPDframe * gpf_orig
struct bGPDframe * next
bGPDframe_Runtime runtime
struct bGPDframe * prev
struct bGPDlayer_Mask * prev
struct bGPDlayer_Mask * next
struct bGPDlayer * gpl_orig
struct Object * parent
struct bGPDlayer * next
bGPDlayer_Runtime runtime
struct bGPDlayer * prev
struct bGPDspoint * pt_orig
bGPDspoint_Runtime runtime
struct bGPDstroke * gps_orig
struct bGPDstroke * prev
bGPDtriangle * triangles
bGPDstroke_Runtime runtime
struct bGPDcurve * editcurve
struct MDeformVert * dvert
struct bGPDstroke * next
struct GPencilUpdateCache * update_cache
ListBase vertex_group_names
struct Material ** mat
bGPdata_Runtime runtime
float pose_mat[4][4]
ccl_device_inline int abs(int x)
Definition util/math.h:120
#define N_(msgid)