Blender  V2.93
gpencil.c
Go to the documentation of this file.
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 
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 
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, true, true);
97 
98  /* Apply local layer transform to all frames. Calc the active frame is not enough
99  * because onion skin can use more frames. This is more slow but required here. */
100  if (gpl_dst->actframe != NULL) {
101  bool transformed = ((!is_zero_v3(gpl_dst->location)) || (!is_zero_v3(gpl_dst->rotation)) ||
102  (!is_one_v3(gpl_dst->scale)));
103  if (transformed) {
105  gpl_dst->layer_mat, gpl_dst->location, gpl_dst->rotation, gpl_dst->scale);
106  bool do_onion = ((gpl_dst->onion_flag & GP_LAYER_ONIONSKIN) != 0);
107  bGPDframe *init_gpf = (do_onion) ? gpl_dst->frames.first : gpl_dst->actframe;
108  for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
109  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
110  bGPDspoint *pt;
111  int i;
112  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
113  mul_m4_v3(gpl_dst->layer_mat, &pt->x);
114  }
115  }
116  /* if not onion, exit loop. */
117  if (!do_onion) {
118  break;
119  }
120  }
121  }
122  }
123 
124  BLI_addtail(&gpd_dst->layers, gpl_dst);
125  }
126 }
127 
128 static void greasepencil_free_data(ID *id)
129 {
130  /* Really not ideal, but for now will do... In theory custom behaviors like not freeing cache
131  * should be handled through specific API, and not be part of the generic one. */
132  BKE_gpencil_free((bGPdata *)id, true);
133 }
134 
136 {
137  bGPdata *gpencil = (bGPdata *)id;
138  /* materials */
139  for (int i = 0; i < gpencil->totcol; i++) {
141  }
142 
143  LISTBASE_FOREACH (bGPDlayer *, gplayer, &gpencil->layers) {
144  BKE_LIB_FOREACHID_PROCESS(data, gplayer->parent, IDWALK_CB_NOP);
145  }
146 }
147 
148 static void greasepencil_blend_write(BlendWriter *writer, ID *id, const void *id_address)
149 {
150  bGPdata *gpd = (bGPdata *)id;
151  if (gpd->id.us > 0 || BLO_write_is_undo(writer)) {
152  /* Clean up, important in undo case to reduce false detection of changed data-blocks. */
153  /* XXX not sure why the whole run-time data is not cleared in reading code,
154  * for now mimicking it here. */
155  gpd->runtime.sbuffer = NULL;
156  gpd->runtime.sbuffer_used = 0;
157  gpd->runtime.sbuffer_size = 0;
158  gpd->runtime.tot_cp_points = 0;
159 
160  /* write gpd data block to file */
161  BLO_write_id_struct(writer, bGPdata, id_address, &gpd->id);
162  BKE_id_blend_write(writer, &gpd->id);
163 
164  if (gpd->adt) {
165  BKE_animdata_blend_write(writer, gpd->adt);
166  }
167 
168  BLO_write_pointer_array(writer, gpd->totcol, gpd->mat);
169 
170  /* write grease-pencil layers to file */
171  BLO_write_struct_list(writer, bGPDlayer, &gpd->layers);
172  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
173  /* Write mask list. */
174  BLO_write_struct_list(writer, bGPDlayer_Mask, &gpl->mask_layers);
175  /* write this layer's frames to file */
176  BLO_write_struct_list(writer, bGPDframe, &gpl->frames);
177  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
178  /* write strokes */
179  BLO_write_struct_list(writer, bGPDstroke, &gpf->strokes);
180  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
181  BLO_write_struct_array(writer, bGPDspoint, gps->totpoints, gps->points);
182  BLO_write_struct_array(writer, bGPDtriangle, gps->tot_triangles, gps->triangles);
183  BKE_defvert_blend_write(writer, gps->totpoints, gps->dvert);
184  if (gps->editcurve != NULL) {
185  bGPDcurve *gpc = gps->editcurve;
186  BLO_write_struct(writer, bGPDcurve, gpc);
188  writer, bGPDcurve_point, gpc->tot_curve_points, gpc->curve_points);
189  }
190  }
191  }
192  }
193  }
194 }
195 
197 {
198  /* we must firstly have some grease-pencil data to link! */
199  if (gpd == NULL) {
200  return;
201  }
202 
203  /* relink animdata */
204  BLO_read_data_address(reader, &gpd->adt);
205  BKE_animdata_blend_read_data(reader, gpd->adt);
206 
207  /* Ensure full objectmode for linked grease pencil. */
208  if (gpd->id.lib != NULL) {
210  gpd->flag &= ~GP_DATA_STROKE_EDITMODE;
214  }
215 
216  /* init stroke buffer */
217  gpd->runtime.sbuffer = NULL;
218  gpd->runtime.sbuffer_used = 0;
219  gpd->runtime.sbuffer_size = 0;
220  gpd->runtime.tot_cp_points = 0;
221 
222  /* relink palettes (old palettes deprecated, only to convert old files) */
223  BLO_read_list(reader, &gpd->palettes);
224  if (gpd->palettes.first != NULL) {
225  LISTBASE_FOREACH (bGPDpalette *, palette, &gpd->palettes) {
226  BLO_read_list(reader, &palette->colors);
227  }
228  }
229 
230  /* materials */
231  BLO_read_pointer_array(reader, (void **)&gpd->mat);
232 
233  /* relink layers */
234  BLO_read_list(reader, &gpd->layers);
235 
236  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
237  /* relink frames */
238  BLO_read_list(reader, &gpl->frames);
239 
240  BLO_read_data_address(reader, &gpl->actframe);
241 
242  gpl->runtime.icon_id = 0;
243 
244  /* Relink masks. */
245  BLO_read_list(reader, &gpl->mask_layers);
246 
247  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
248  /* relink strokes (and their points) */
249  BLO_read_list(reader, &gpf->strokes);
250 
251  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
252  /* relink stroke points array */
253  BLO_read_data_address(reader, &gps->points);
254  /* Relink geometry*/
255  BLO_read_data_address(reader, &gps->triangles);
256 
257  /* relink stroke edit curve. */
258  BLO_read_data_address(reader, &gps->editcurve);
259  if (gps->editcurve != NULL) {
260  /* relink curve point array */
261  BLO_read_data_address(reader, &gps->editcurve->curve_points);
262  }
263 
264  /* relink weight data */
265  if (gps->dvert) {
266  BLO_read_data_address(reader, &gps->dvert);
267  BKE_defvert_blend_read(reader, gps->totpoints, gps->dvert);
268  }
269  }
270  }
271  }
272 }
273 
275 {
276  bGPdata *gpd = (bGPdata *)id;
277  BKE_gpencil_blend_read_data(reader, gpd);
278 }
279 
281 {
282  bGPdata *gpd = (bGPdata *)id;
283 
284  /* Relink all data-lock linked by GP data-lock */
285  /* Layers */
286  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
287  /* Layer -> Parent References */
288  BLO_read_id_address(reader, gpd->id.lib, &gpl->parent);
289  }
290 
291  /* materials */
292  for (int a = 0; a < gpd->totcol; a++) {
293  BLO_read_id_address(reader, gpd->id.lib, &gpd->mat[a]);
294  }
295 }
296 
298 {
299  bGPdata *gpd = (bGPdata *)id;
300  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
301  BLO_expand(expander, gpl->parent);
302  }
303 
304  for (int a = 0; a < gpd->totcol; a++) {
305  BLO_expand(expander, gpd->mat[a]);
306  }
307 }
308 
310  .id_code = ID_GD,
311  .id_filter = FILTER_ID_GD,
312  .main_listbase_index = INDEX_ID_GD,
313  .struct_size = sizeof(bGPdata),
314  .name = "GPencil",
315  .name_plural = "grease_pencils",
316  .translation_context = BLT_I18NCONTEXT_ID_GPENCIL,
317  .flags = 0,
318 
319  .init_data = NULL,
320  .copy_data = greasepencil_copy_data,
321  .free_data = greasepencil_free_data,
322  .make_local = NULL,
323  .foreach_id = greasepencil_foreach_id,
324  .foreach_cache = NULL,
325  .owner_get = NULL,
326 
327  .blend_write = greasepencil_blend_write,
328  .blend_read_data = greasepencil_blend_read_data,
329  .blend_read_lib = greasepencil_blend_read_lib,
330  .blend_read_expand = greasepencil_blend_read_expand,
331 
332  .blend_read_undo_preserve = NULL,
333 
334  .lib_override_apply_post = NULL,
335 };
336 
337 /* ************************************************** */
338 /* Draw Engine */
339 
342 
344 {
345  if (gpd) {
348  }
349 }
350 
352 {
353  if (gpd) {
355  }
356 }
357 
358 /* ************************************************** */
359 /* Memory Management */
360 
361 /* clean vertex groups weights */
363 {
364  if (dvert == NULL) {
365  return;
366  }
367  MEM_SAFE_FREE(dvert->dw);
368 }
369 
371 {
372  if (gps == NULL) {
373  return;
374  }
375 
376  if (gps->dvert == NULL) {
377  return;
378  }
379 
380  for (int i = 0; i < gps->totpoints; i++) {
381  MDeformVert *dvert = &gps->dvert[i];
383  }
384 }
385 
387 {
388  if (gps == NULL) {
389  return;
390  }
391  bGPDcurve *editcurve = gps->editcurve;
392  if (editcurve == NULL) {
393  return;
394  }
395  MEM_freeN(editcurve->curve_points);
396  MEM_freeN(editcurve);
397  gps->editcurve = NULL;
398 }
399 
400 /* free stroke, doesn't unlink from any listbase */
402 {
403  if (gps == NULL) {
404  return;
405  }
406  /* free stroke memory arrays, then stroke itself */
407  if (gps->points) {
408  MEM_freeN(gps->points);
409  }
410  if (gps->dvert) {
412  MEM_freeN(gps->dvert);
413  }
414  if (gps->triangles) {
415  MEM_freeN(gps->triangles);
416  }
417  if (gps->editcurve != NULL) {
419  }
420 
421  MEM_freeN(gps);
422 }
423 
424 /* Free strokes belonging to a gp-frame */
426 {
427  bool changed = (BLI_listbase_is_empty(&gpf->strokes) == false);
428 
429  /* free strokes */
432  }
434 
435  return changed;
436 }
437 
438 /* Free all of a gp-layer's frames */
440 {
441  bGPDframe *gpf_next;
442 
443  /* error checking */
444  if (gpl == NULL) {
445  return;
446  }
447 
448  /* free frames */
449  for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf_next) {
450  gpf_next = gpf->next;
451 
452  /* free strokes and their associated memory */
454  BLI_freelinkN(&gpl->frames, gpf);
455  }
456  gpl->actframe = NULL;
457 }
458 
460 {
461  /* Free masks.*/
462  bGPDlayer_Mask *mask_next = NULL;
463  for (bGPDlayer_Mask *mask = gpl->mask_layers.first; mask; mask = mask_next) {
464  mask_next = mask->next;
466  }
467 }
468 /* Free all of the gp-layers for a viewport (list should be &gpd->layers or so) */
470 {
471  bGPDlayer *gpl_next;
472 
473  /* error checking */
474  if (list == NULL) {
475  return;
476  }
477 
478  /* delete layers */
479  for (bGPDlayer *gpl = list->first; gpl; gpl = gpl_next) {
480  gpl_next = gpl->next;
481 
482  /* free layers and their data */
484 
485  /* Free masks.*/
487 
488  BLI_freelinkN(list, gpl);
489  }
490 }
491 
493 void BKE_gpencil_free(bGPdata *gpd, bool free_all)
494 {
495  /* free layers */
497 
498  /* materials */
499  MEM_SAFE_FREE(gpd->mat);
500 
501  /* free all data */
502  if (free_all) {
503  /* clear cache */
505  }
506 }
507 
513 {
514  BKE_gpencil_free(gpd_eval, true);
515  BKE_libblock_free_data(&gpd_eval->id, false);
516  BLI_assert(!gpd_eval->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
517  MEM_freeN(gpd_eval);
518 }
519 
526 {
528 }
529 
530 /* ************************************************** */
531 /* Container Creation */
532 
540 {
541  bGPDframe *gpf = NULL, *gf = NULL;
542  short state = 0;
543 
544  /* error checking */
545  if (gpl == NULL) {
546  return NULL;
547  }
548 
549  /* allocate memory for this frame */
550  gpf = MEM_callocN(sizeof(bGPDframe), "bGPDframe");
551  gpf->framenum = cframe;
552 
553  /* find appropriate place to add frame */
554  if (gpl->frames.first) {
555  for (gf = gpl->frames.first; gf; gf = gf->next) {
556  /* check if frame matches one that is supposed to be added */
557  if (gf->framenum == cframe) {
558  state = -1;
559  break;
560  }
561 
562  /* if current frame has already exceeded the frame to add, add before */
563  if (gf->framenum > cframe) {
564  BLI_insertlinkbefore(&gpl->frames, gf, gpf);
565  state = 1;
566  break;
567  }
568  }
569  }
570 
571  /* check whether frame was added successfully */
572  if (state == -1) {
573  CLOG_ERROR(
574  &LOG, "Frame (%d) existed already for this layer_active. Using existing frame", cframe);
575 
576  /* free the newly created one, and use the old one instead */
577  MEM_freeN(gpf);
578 
579  /* return existing frame instead... */
580  BLI_assert(gf != NULL);
581  gpf = gf;
582  }
583  else if (state == 0) {
584  /* add to end then! */
585  BLI_addtail(&gpl->frames, gpf);
586  }
587 
588  /* return frame */
589  return gpf;
590 }
591 
599 {
600  bGPDframe *new_frame;
601  bool found = false;
602 
603  /* Error checking/handling */
604  if (gpl == NULL) {
605  /* no layer */
606  return NULL;
607  }
608  if (gpl->actframe == NULL) {
609  /* no active frame, so just create a new one from scratch */
610  return BKE_gpencil_frame_addnew(gpl, cframe);
611  }
612 
613  /* Create a copy of the frame */
614  new_frame = BKE_gpencil_frame_duplicate(gpl->actframe, true);
615 
616  /* Find frame to insert it before */
617  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
618  if (gpf->framenum > cframe) {
619  /* Add it here */
620  BLI_insertlinkbefore(&gpl->frames, gpf, new_frame);
621 
622  found = true;
623  break;
624  }
625  if (gpf->framenum == cframe) {
626  /* This only happens when we're editing with framelock on...
627  * - Delete the new frame and don't do anything else here...
628  */
629  BKE_gpencil_free_strokes(new_frame);
630  MEM_freeN(new_frame);
631  new_frame = NULL;
632 
633  found = true;
634  break;
635  }
636  }
637 
638  if (found == false) {
639  /* Add new frame to the end */
640  BLI_addtail(&gpl->frames, new_frame);
641  }
642 
643  /* Ensure that frame is set up correctly, and return it */
644  if (new_frame) {
645  new_frame->framenum = cframe;
646  gpl->actframe = new_frame;
647  }
648 
649  return new_frame;
650 }
651 
659 bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setactive)
660 {
661  bGPDlayer *gpl = NULL;
662  bGPDlayer *gpl_active = NULL;
663 
664  /* check that list is ok */
665  if (gpd == NULL) {
666  return NULL;
667  }
668 
669  /* allocate memory for frame and add to end of list */
670  gpl = MEM_callocN(sizeof(bGPDlayer), "bGPDlayer");
671 
672  gpl_active = BKE_gpencil_layer_active_get(gpd);
673 
674  /* Add to data-block. */
675  if (gpl_active == NULL) {
676  BLI_addtail(&gpd->layers, gpl);
677  }
678  else {
679  /* if active layer, add after that layer */
680  BLI_insertlinkafter(&gpd->layers, gpl_active, gpl);
681  }
682 
683  /* annotation vs GP Object behavior is slightly different */
684  if (gpd->flag & GP_DATA_ANNOTATIONS) {
685  /* set default color of new strokes for this layer */
686  copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
687  gpl->opacity = 1.0f;
688 
689  /* set default thickness of new strokes for this layer */
690  gpl->thickness = 3;
691 
692  /* Onion colors */
693  ARRAY_SET_ITEMS(gpl->gcolor_prev, 0.302f, 0.851f, 0.302f);
694  ARRAY_SET_ITEMS(gpl->gcolor_next, 0.250f, 0.1f, 1.0f);
695  }
696  else {
697  /* thickness parameter represents "thickness change", not absolute thickness */
698  gpl->thickness = 0;
699  gpl->opacity = 1.0f;
700  /* default channel color */
701  ARRAY_SET_ITEMS(gpl->color, 0.2f, 0.2f, 0.2f);
702  /* Default vertex mix. */
703  gpl->vertex_paint_opacity = 1.0f;
704  /* Enable onion skin. */
706  }
707 
708  /* auto-name */
709  BLI_strncpy(gpl->info, name, sizeof(gpl->info));
710  BLI_uniquename(&gpd->layers,
711  gpl,
712  (gpd->flag & GP_DATA_ANNOTATIONS) ? DATA_("Note") : DATA_("GP_Layer"),
713  '.',
714  offsetof(bGPDlayer, info),
715  sizeof(gpl->info));
716 
717  /* Enable always affected by scene lights. */
718  gpl->flag |= GP_LAYER_USE_LIGHTS;
719 
720  /* Init transform. */
721  zero_v3(gpl->location);
722  zero_v3(gpl->rotation);
723  copy_v3_fl(gpl->scale, 1.0f);
724  loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale);
725  invert_m4_m4(gpl->layer_invmat, gpl->layer_mat);
726 
727  /* make this one the active one */
728  if (setactive) {
730  }
731 
732  /* return layer */
733  return gpl;
734 }
735 
742 bGPdata *BKE_gpencil_data_addnew(Main *bmain, const char name[])
743 {
744  bGPdata *gpd;
745 
746  /* allocate memory for a new block */
747  gpd = BKE_libblock_alloc(bmain, ID_GD, name, 0);
748 
749  /* initial settings */
751 
752  /* general flags */
753  gpd->flag |= GP_DATA_VIEWALIGN;
754  /* always enable object onion skin switch */
756  /* GP object specific settings */
757  ARRAY_SET_ITEMS(gpd->line_color, 0.6f, 0.6f, 0.6f, 0.5f);
758 
760 
764 
765  /* use adaptive curve resolution by default */
767 
768  gpd->zdepth_offset = 0.150f;
769 
770  /* grid settings */
771  ARRAY_SET_ITEMS(gpd->grid.color, 0.5f, 0.5f, 0.5f); /* Color */
772  ARRAY_SET_ITEMS(gpd->grid.scale, 1.0f, 1.0f); /* Scale */
773  gpd->grid.lines = GP_DEFAULT_GRID_LINES; /* Number of lines */
774 
775  /* Onion-skinning settings (data-block level) */
776  gpd->onion_keytype = -1; /* All by default. */
778  gpd->onion_flag |= GP_ONION_FADE;
780  gpd->onion_factor = 0.5f;
781  ARRAY_SET_ITEMS(gpd->gcolor_prev, 0.145098f, 0.419608f, 0.137255f); /* green */
782  ARRAY_SET_ITEMS(gpd->gcolor_next, 0.125490f, 0.082353f, 0.529412f); /* blue */
783  gpd->gstep = 1;
784  gpd->gstep_next = 1;
785 
786  return gpd;
787 }
788 
789 /* ************************************************** */
790 /* Primitive Creation */
791 /* Utilities for easier bulk-creation of geometry */
792 
801  const float *array,
802  const int totpoints,
803  const float mat[4][4])
804 {
805  for (int i = 0; i < totpoints; i++) {
806  bGPDspoint *pt = &gps->points[i];
807  const int x = GP_PRIM_DATABUF_SIZE * i;
808 
809  pt->x = array[x];
810  pt->y = array[x + 1];
811  pt->z = array[x + 2];
812  mul_m4_v3(mat, &pt->x);
813 
814  pt->pressure = array[x + 3];
815  pt->strength = array[x + 4];
816  }
817 }
818 
826 bGPDstroke *BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness)
827 {
828  /* allocate memory for a new stroke */
829  bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
830 
831  gps->thickness = thickness;
832  gps->fill_opacity_fac = 1.0f;
833  gps->hardeness = 1.0f;
834  copy_v2_fl(gps->aspect_ratio, 1.0f);
835 
836  gps->uv_scale = 1.0f;
837 
838  gps->inittime = 0;
839 
840  gps->flag = GP_STROKE_3DSPACE;
841 
842  gps->totpoints = totpoints;
843  if (gps->totpoints > 0) {
844  gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
845  }
846  else {
847  gps->points = NULL;
848  }
849 
850  /* initialize triangle memory to dummy data */
851  gps->triangles = NULL;
852  gps->tot_triangles = 0;
853 
854  gps->mat_nr = mat_idx;
855 
856  gps->dvert = NULL;
857  gps->editcurve = NULL;
858 
859  return gps;
860 }
861 
872  bGPDframe *gpf, int mat_idx, int totpoints, short thickness, const bool insert_at_head)
873 {
874  bGPDstroke *gps = BKE_gpencil_stroke_new(mat_idx, totpoints, thickness);
875 
876  /* Add to frame. */
877  if ((gps != NULL) && (gpf != NULL)) {
878  if (!insert_at_head) {
879  BLI_addtail(&gpf->strokes, gps);
880  }
881  else {
882  BLI_addhead(&gpf->strokes, gps);
883  }
884  }
885 
886  return gps;
887 }
888 
900  bGPDframe *gpf, bGPDstroke *existing, int mat_idx, int totpoints, short thickness)
901 {
902  bGPDstroke *gps = BKE_gpencil_stroke_add(gpf, mat_idx, totpoints, thickness, false);
903  /* Copy run-time color data so that strokes added in the modifier has the style.
904  * There are depsgraph reference pointers inside,
905  * change the copy function if interfere with future drawing implementation. */
906  memcpy(&gps->runtime, &existing->runtime, sizeof(bGPDstroke_Runtime));
907  return gps;
908 }
909 
910 bGPDcurve *BKE_gpencil_stroke_editcurve_new(const int tot_curve_points)
911 {
912  bGPDcurve *new_gp_curve = (bGPDcurve *)MEM_callocN(sizeof(bGPDcurve), __func__);
913  new_gp_curve->tot_curve_points = tot_curve_points;
914  new_gp_curve->curve_points = (bGPDcurve_point *)MEM_callocN(
915  sizeof(bGPDcurve_point) * tot_curve_points, __func__);
916 
917  return new_gp_curve;
918 }
919 
920 /* ************************************************** */
921 /* Data Duplication */
922 
929 {
930  if (gps_src == NULL) {
931  return;
932  }
933  BLI_assert(gps_src->totpoints == gps_dst->totpoints);
934 
935  BKE_defvert_array_copy(gps_dst->dvert, gps_src->dvert, gps_src->totpoints);
936 }
937 
938 /* Make a copy of a given gpencil stroke editcurve */
940 {
941  bGPDcurve *gpc_dst = MEM_dupallocN(gpc_src);
942 
943  if (gpc_src->curve_points != NULL) {
944  gpc_dst->curve_points = MEM_dupallocN(gpc_src->curve_points);
945  }
946 
947  return gpc_dst;
948 }
949 
958  const bool dup_points,
959  const bool dup_curve)
960 {
961  bGPDstroke *gps_dst = NULL;
962 
963  gps_dst = MEM_dupallocN(gps_src);
964  gps_dst->prev = gps_dst->next = NULL;
965  gps_dst->triangles = MEM_dupallocN(gps_src->triangles);
966 
967  if (dup_points) {
968  gps_dst->points = MEM_dupallocN(gps_src->points);
969 
970  if (gps_src->dvert != NULL) {
971  gps_dst->dvert = MEM_dupallocN(gps_src->dvert);
972  BKE_gpencil_stroke_weights_duplicate(gps_src, gps_dst);
973  }
974  else {
975  gps_dst->dvert = NULL;
976  }
977  }
978  else {
979  gps_dst->points = NULL;
980  gps_dst->dvert = NULL;
981  }
982 
983  if (dup_curve && gps_src->editcurve != NULL) {
985  }
986  else {
987  gps_dst->editcurve = NULL;
988  }
989 
990  /* return new stroke */
991  return gps_dst;
992 }
993 
999 bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src, const bool dup_strokes)
1000 {
1001  bGPDstroke *gps_dst = NULL;
1002  bGPDframe *gpf_dst;
1003 
1004  /* error checking */
1005  if (gpf_src == NULL) {
1006  return NULL;
1007  }
1008 
1009  /* make a copy of the source frame */
1010  gpf_dst = MEM_dupallocN(gpf_src);
1011  gpf_dst->prev = gpf_dst->next = NULL;
1012 
1013  /* Copy strokes. */
1014  BLI_listbase_clear(&gpf_dst->strokes);
1015  if (dup_strokes) {
1016  LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
1017  /* make copy of source stroke */
1018  gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true);
1019  BLI_addtail(&gpf_dst->strokes, gps_dst);
1020  }
1021  }
1022 
1023  /* return new frame */
1024  return gpf_dst;
1025 }
1026 
1032 void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, struct bGPDframe *gpf_dst)
1033 {
1034  bGPDstroke *gps_dst = NULL;
1035  /* error checking */
1036  if ((gpf_src == NULL) || (gpf_dst == NULL)) {
1037  return;
1038  }
1039 
1040  /* copy strokes */
1041  BLI_listbase_clear(&gpf_dst->strokes);
1042  LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
1043  /* make copy of source stroke */
1044  gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true);
1045  BLI_addtail(&gpf_dst->strokes, gps_dst);
1046  }
1047 }
1048 
1055  const bool dup_frames,
1056  const bool dup_strokes)
1057 {
1058  const bGPDframe *gpf_src;
1059  bGPDframe *gpf_dst;
1060  bGPDlayer *gpl_dst;
1061 
1062  /* error checking */
1063  if (gpl_src == NULL) {
1064  return NULL;
1065  }
1066 
1067  /* make a copy of source layer */
1068  gpl_dst = MEM_dupallocN(gpl_src);
1069  gpl_dst->prev = gpl_dst->next = NULL;
1070 
1071  /* Copy masks. */
1072  BLI_listbase_clear(&gpl_dst->mask_layers);
1073  LISTBASE_FOREACH (bGPDlayer_Mask *, mask_src, &gpl_src->mask_layers) {
1074  bGPDlayer_Mask *mask_dst = MEM_dupallocN(mask_src);
1075  mask_dst->prev = mask_dst->next = NULL;
1076  BLI_addtail(&gpl_dst->mask_layers, mask_dst);
1077  }
1078 
1079  /* copy frames */
1080  BLI_listbase_clear(&gpl_dst->frames);
1081  if (dup_frames) {
1082  for (gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) {
1083  /* make a copy of source frame */
1084  gpf_dst = BKE_gpencil_frame_duplicate(gpf_src, dup_strokes);
1085  BLI_addtail(&gpl_dst->frames, gpf_dst);
1086 
1087  /* if source frame was the current layer's 'active' frame, reassign that too */
1088  if (gpf_src == gpl_dst->actframe) {
1089  gpl_dst->actframe = gpf_dst;
1090  }
1091  }
1092  }
1093 
1094  /* return new layer */
1095  return gpl_dst;
1096 }
1097 
1103 bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy)
1104 {
1105  bGPdata *gpd_dst;
1106 
1107  /* Yuck and super-uber-hyper yuck!!!
1108  * Should be replaceable with a no-main copy (LIB_ID_COPY_NO_MAIN etc.), but not sure about it,
1109  * so for now keep old code for that one. */
1110 
1111  /* error checking */
1112  if (gpd_src == NULL) {
1113  return NULL;
1114  }
1115 
1116  if (internal_copy) {
1117  /* make a straight copy for undo buffers used during stroke drawing */
1118  gpd_dst = MEM_dupallocN(gpd_src);
1119  }
1120  else {
1121  BLI_assert(bmain != NULL);
1122  gpd_dst = (bGPdata *)BKE_id_copy(bmain, &gpd_src->id);
1123  }
1124 
1125  /* Copy internal data (layers, etc.) */
1126  greasepencil_copy_data(bmain, &gpd_dst->id, &gpd_src->id, 0);
1127 
1128  /* return new */
1129  return gpd_dst;
1130 }
1131 
1132 /* ************************************************** */
1133 /* GP Stroke API */
1134 
1140 {
1141  bGPDspoint *pt;
1142  int i;
1143 
1144  /* error checking */
1145  if (gps == NULL) {
1146  return;
1147  }
1148 
1149  /* we'll stop when we find the first selected point,
1150  * so initially, we must deselect
1151  */
1152  gps->flag &= ~GP_STROKE_SELECT;
1154 
1155  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1156  if (pt->flag & GP_SPOINT_SELECT) {
1157  gps->flag |= GP_STROKE_SELECT;
1158  break;
1159  }
1160  }
1161 
1162  if (gps->flag & GP_STROKE_SELECT) {
1164  }
1165 }
1166 
1168 {
1169  bGPDcurve *gpc = gps->editcurve;
1170  if (gpc == NULL) {
1171  return;
1172  }
1173 
1174  gps->flag &= ~GP_STROKE_SELECT;
1176  gpc->flag &= ~GP_CURVE_SELECT;
1177 
1178  bool is_selected = false;
1179  for (int i = 0; i < gpc->tot_curve_points; i++) {
1180  bGPDcurve_point *gpc_pt = &gpc->curve_points[i];
1181  BezTriple *bezt = &gpc_pt->bezt;
1182 
1183  if (BEZT_ISSEL_ANY(bezt)) {
1184  gpc_pt->flag |= GP_SPOINT_SELECT;
1185  }
1186  else {
1187  gpc_pt->flag &= ~GP_SPOINT_SELECT;
1188  }
1189 
1190  if (gpc_pt->flag & GP_SPOINT_SELECT) {
1191  is_selected = true;
1192  }
1193  }
1194 
1195  if (is_selected) {
1196  gpc->flag |= GP_CURVE_SELECT;
1197  gps->flag |= GP_STROKE_SELECT;
1199  }
1200 }
1201 
1202 /* Assign unique stroke ID for selection. */
1204 {
1205  gpd->select_last_index++;
1206  gps->select_index = gpd->select_last_index;
1207 }
1208 
1209 /* Reset unique stroke ID for selection. */
1211 {
1212  gps->select_index = 0;
1213 }
1214 
1215 /* ************************************************** */
1216 /* GP Frame API */
1217 
1224 {
1225  bGPDstroke *gps = (gpf) ? gpf->strokes.last : NULL;
1226  int cfra = (gpf) ? gpf->framenum : 0; /* assume that the current frame was not locked */
1227 
1228  /* error checking */
1229  if (ELEM(NULL, gpf, gps)) {
1230  return;
1231  }
1232 
1233  /* free the stroke and its data */
1234  if (gps->points) {
1235  MEM_freeN(gps->points);
1236  }
1237  if (gps->dvert) {
1239  MEM_freeN(gps->dvert);
1240  }
1241  MEM_freeN(gps->triangles);
1242  BLI_freelinkN(&gpf->strokes, gps);
1243 
1244  /* if frame has no strokes after this, delete it */
1245  if (BLI_listbase_is_empty(&gpf->strokes)) {
1248  }
1249 }
1250 
1251 /* ************************************************** */
1252 /* GP Layer API */
1253 
1260 {
1261  /* Sanity check */
1262  if (gpl == NULL) {
1263  return false;
1264  }
1265 
1266  /* Layer must be: Visible + Editable */
1267  if ((gpl->flag & (GP_LAYER_HIDE | GP_LAYER_LOCKED)) == 0) {
1268  return true;
1269  }
1270 
1271  /* Something failed */
1272  return false;
1273 }
1274 
1282 {
1283  bGPDframe *gpf;
1284 
1285  /* Search in reverse order, since this is often used for playback/adding,
1286  * where it's less likely that we're interested in the earlier frames
1287  */
1288  for (gpf = gpl->frames.last; gpf; gpf = gpf->prev) {
1289  if (gpf->framenum == cframe) {
1290  return gpf;
1291  }
1292  }
1293 
1294  return NULL;
1295 }
1296 
1308 {
1309  bGPDframe *gpf = NULL;
1310  bool found = false;
1311 
1312  /* error checking */
1313  if (gpl == NULL) {
1314  return NULL;
1315  }
1316 
1317  /* check if there is already an active frame */
1318  if (gpl->actframe) {
1319  gpf = gpl->actframe;
1320 
1321  /* do not allow any changes to layer's active frame if layer is locked from changes
1322  * or if the layer has been set to stay on the current frame
1323  */
1324  if (gpl->flag & GP_LAYER_FRAMELOCK) {
1325  return gpf;
1326  }
1327  /* do not allow any changes to actframe if frame has painting tag attached to it */
1328  if (gpf->flag & GP_FRAME_PAINT) {
1329  return gpf;
1330  }
1331 
1332  /* try to find matching frame */
1333  if (gpf->framenum < cframe) {
1334  for (; gpf; gpf = gpf->next) {
1335  if (gpf->framenum == cframe) {
1336  found = true;
1337  break;
1338  }
1339  if ((gpf->next) && (gpf->next->framenum > cframe)) {
1340  found = true;
1341  break;
1342  }
1343  }
1344 
1345  /* set the appropriate frame */
1346  if (addnew) {
1347  if ((found) && (gpf->framenum == cframe)) {
1348  gpl->actframe = gpf;
1349  }
1350  else if (addnew == GP_GETFRAME_ADD_COPY) {
1351  gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe);
1352  }
1353  else {
1354  gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
1355  }
1356  }
1357  else if (found) {
1358  gpl->actframe = gpf;
1359  }
1360  else {
1361  gpl->actframe = gpl->frames.last;
1362  }
1363  }
1364  else {
1365  for (; gpf; gpf = gpf->prev) {
1366  if (gpf->framenum <= cframe) {
1367  found = true;
1368  break;
1369  }
1370  }
1371 
1372  /* set the appropriate frame */
1373  if (addnew) {
1374  if ((found) && (gpf->framenum == cframe)) {
1375  gpl->actframe = gpf;
1376  }
1377  else if (addnew == GP_GETFRAME_ADD_COPY) {
1378  gpl->actframe = BKE_gpencil_frame_addcopy(gpl, cframe);
1379  }
1380  else {
1381  gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
1382  }
1383  }
1384  else if (found) {
1385  gpl->actframe = gpf;
1386  }
1387  else {
1388  gpl->actframe = gpl->frames.first;
1389  }
1390  }
1391  }
1392  else if (gpl->frames.first) {
1393  /* check which of the ends to start checking from */
1394  const int first = ((bGPDframe *)(gpl->frames.first))->framenum;
1395  const int last = ((bGPDframe *)(gpl->frames.last))->framenum;
1396 
1397  if (abs(cframe - first) > abs(cframe - last)) {
1398  /* find gp-frame which is less than or equal to cframe */
1399  for (gpf = gpl->frames.last; gpf; gpf = gpf->prev) {
1400  if (gpf->framenum <= cframe) {
1401  found = true;
1402  break;
1403  }
1404  }
1405  }
1406  else {
1407  /* find gp-frame which is less than or equal to cframe */
1408  for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1409  if (gpf->framenum <= cframe) {
1410  found = true;
1411  break;
1412  }
1413  }
1414  }
1415 
1416  /* set the appropriate frame */
1417  if (addnew) {
1418  if ((found) && (gpf->framenum == cframe)) {
1419  gpl->actframe = gpf;
1420  }
1421  else {
1422  gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
1423  }
1424  }
1425  else if (found) {
1426  gpl->actframe = gpf;
1427  }
1428  else {
1429  /* If delete first frame, need to find one. */
1430  if (gpl->frames.first != NULL) {
1431  gpl->actframe = gpl->frames.first;
1432  }
1433  else {
1434  /* unresolved errogenous situation! */
1435  CLOG_STR_ERROR(&LOG, "cannot find appropriate gp-frame");
1436  /* gpl->actframe should still be NULL */
1437  }
1438  }
1439  }
1440  else {
1441  /* currently no frames (add if allowed to) */
1442  if (addnew) {
1443  gpl->actframe = BKE_gpencil_frame_addnew(gpl, cframe);
1444  }
1445  else {
1446  /* don't do anything... this may be when no frames yet! */
1447  /* gpl->actframe should still be NULL */
1448  }
1449  }
1450 
1451  /* Don't select first frame if greater than current frame. */
1452  if ((gpl->actframe != NULL) && (gpl->actframe == gpl->frames.first) &&
1453  (gpl->actframe->framenum > cframe)) {
1454  gpl->actframe = NULL;
1455  }
1456 
1457  /* return */
1458  return gpl->actframe;
1459 }
1460 
1468 {
1469  bool changed = false;
1470 
1471  /* error checking */
1472  if (ELEM(NULL, gpl, gpf)) {
1473  return false;
1474  }
1475 
1476  /* if this frame was active, make the previous frame active instead
1477  * since it's tricky to set active frame otherwise
1478  */
1479  if (gpl->actframe == gpf) {
1480  gpl->actframe = gpf->prev;
1481  }
1482 
1483  /* free the frame and its data */
1484  changed = BKE_gpencil_free_strokes(gpf);
1485  BLI_freelinkN(&gpl->frames, gpf);
1486 
1487  return changed;
1488 }
1489 
1497 {
1498  if (name[0] == '\0') {
1499  return NULL;
1500  }
1501  return BLI_findstring(&gpd->layers, name, offsetof(bGPDlayer, info));
1502 }
1503 
1511 {
1512  if (name[0] == '\0') {
1513  return NULL;
1514  }
1515  return BLI_findstring(&gpl->mask_layers, name, offsetof(bGPDlayer_Mask, name));
1516 }
1517 
1525 {
1526 
1527  bGPDlayer_Mask *mask = MEM_callocN(sizeof(bGPDlayer_Mask), "bGPDlayer_Mask");
1528  BLI_addtail(&gpl->mask_layers, mask);
1529  BLI_strncpy(mask->name, name, sizeof(mask->name));
1530  gpl->act_mask++;
1531 
1532  return mask;
1533 }
1534 
1541 {
1542  BLI_freelinkN(&gpl->mask_layers, mask);
1543  gpl->act_mask--;
1544  CLAMP_MIN(gpl->act_mask, 0);
1545 }
1546 
1552 void BKE_gpencil_layer_mask_remove_ref(bGPdata *gpd, const char *name)
1553 {
1554  bGPDlayer_Mask *mask_next;
1555 
1556  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1557  for (bGPDlayer_Mask *mask = gpl->mask_layers.first; mask; mask = mask_next) {
1558  mask_next = mask->next;
1559  if (STREQ(mask->name, name)) {
1561  }
1562  }
1563  }
1564 }
1565 
1566 static int gpencil_cb_sort_masks(const void *arg1, const void *arg2)
1567 {
1568  /* sort is inverted as layer list. */
1569  const struct bGPDlayer_Mask *mask1 = arg1;
1570  const struct bGPDlayer_Mask *mask2 = arg2;
1571  int val = 0;
1572 
1573  if (mask1->sort_index < mask2->sort_index) {
1574  val = 1;
1575  }
1576  else if (mask1->sort_index > mask2->sort_index) {
1577  val = -1;
1578  }
1579 
1580  return val;
1581 }
1582 
1589 {
1590  /* Update sort index. */
1592  bGPDlayer *gpl_mask = BKE_gpencil_layer_named_get(gpd, mask->name);
1593  if (gpl_mask != NULL) {
1594  mask->sort_index = BLI_findindex(&gpd->layers, gpl_mask);
1595  }
1596  else {
1597  mask->sort_index = 0;
1598  }
1599  }
1601 }
1602 
1608 {
1609  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1610  BKE_gpencil_layer_mask_sort(gpd, gpl);
1611  }
1612 }
1613 
1614 static int gpencil_cb_cmp_frame(void *thunk, const void *a, const void *b)
1615 {
1616  const bGPDframe *frame_a = a;
1617  const bGPDframe *frame_b = b;
1618 
1619  if (frame_a->framenum < frame_b->framenum) {
1620  return -1;
1621  }
1622  if (frame_a->framenum > frame_b->framenum) {
1623  return 1;
1624  }
1625  if (thunk != NULL) {
1626  *((bool *)thunk) = true;
1627  }
1628  /* Sort selected last. */
1629  if ((frame_a->flag & GP_FRAME_SELECT) && ((frame_b->flag & GP_FRAME_SELECT) == 0)) {
1630  return 1;
1631  }
1632  return 0;
1633 }
1634 
1640 void BKE_gpencil_layer_frames_sort(struct bGPDlayer *gpl, bool *r_has_duplicate_frames)
1641 {
1642  BLI_listbase_sort_r(&gpl->frames, gpencil_cb_cmp_frame, r_has_duplicate_frames);
1643 }
1644 
1651 {
1652  /* error checking */
1653  if (ELEM(NULL, gpd, gpd->layers.first)) {
1654  return NULL;
1655  }
1656 
1657  /* loop over layers until found (assume only one active) */
1658  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1659  if (gpl->flag & GP_LAYER_ACTIVE) {
1660  return gpl;
1661  }
1662  }
1663 
1664  /* no active layer found */
1665  return NULL;
1666 }
1667 
1668 bGPDlayer *BKE_gpencil_layer_get_by_name(bGPdata *gpd, char *name, int first_if_not_found)
1669 {
1670  bGPDlayer *gpl;
1671  int i = 0;
1672 
1673  /* error checking */
1674  if (ELEM(NULL, gpd, gpd->layers.first)) {
1675  return NULL;
1676  }
1677 
1678  /* loop over layers until found (assume only one active) */
1679  for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1680  if (STREQ(name, gpl->info)) {
1681  return gpl;
1682  }
1683  i++;
1684  }
1685 
1686  /* no such layer */
1687  if (first_if_not_found) {
1688  return gpd->layers.first;
1689  }
1690  return NULL;
1691 }
1692 
1699 {
1700  /* error checking */
1701  if (ELEM(NULL, gpd, gpd->layers.first, active)) {
1702  return;
1703  }
1704 
1705  /* loop over layers deactivating all */
1706  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1707  gpl->flag &= ~GP_LAYER_ACTIVE;
1708  if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
1709  gpl->flag |= GP_LAYER_LOCKED;
1710  }
1711  }
1712 
1713  /* set as active one */
1714  active->flag |= GP_LAYER_ACTIVE;
1715  if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
1716  active->flag &= ~GP_LAYER_LOCKED;
1717  }
1718 }
1719 
1725 void BKE_gpencil_layer_autolock_set(bGPdata *gpd, const bool unlock)
1726 {
1727  BLI_assert(gpd != NULL);
1728 
1729  if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
1730  bGPDlayer *layer_active = BKE_gpencil_layer_active_get(gpd);
1731 
1732  /* Lock all other layers */
1733  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1734  /* unlock active layer */
1735  if (gpl == layer_active) {
1736  gpl->flag &= ~GP_LAYER_LOCKED;
1737  }
1738  else {
1739  gpl->flag |= GP_LAYER_LOCKED;
1740  }
1741  }
1742  }
1743  else {
1744  /* If disable is better unlock all layers by default or it looks there is
1745  * a problem in the UI because the user expects all layers will be unlocked
1746  */
1747  if (unlock) {
1748  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1749  gpl->flag &= ~GP_LAYER_LOCKED;
1750  }
1751  }
1752  }
1753 }
1754 
1761 {
1762  /* error checking */
1763  if (ELEM(NULL, gpd, gpl)) {
1764  return;
1765  }
1766 
1767  /* free layer */
1769 
1770  /* Free Masks. */
1772 
1773  /* Remove any reference to that layer in masking lists. */
1775 
1776  /* free icon providing preview of icon color */
1778 
1779  BLI_freelinkN(&gpd->layers, gpl);
1780 }
1781 
1788 {
1789  Material *ma = NULL;
1790 
1791  if ((brush != NULL) && (brush->gpencil_settings != NULL) &&
1792  (brush->gpencil_settings->material != NULL)) {
1793  ma = brush->gpencil_settings->material;
1794  }
1795 
1796  return ma;
1797 }
1798 
1805 {
1806  BLI_assert(brush);
1807  BLI_assert(brush->gpencil_settings);
1808  if (brush->gpencil_settings->material != ma) {
1809  if (brush->gpencil_settings->material) {
1811  }
1812  if (ma) {
1813  id_us_plus(&ma->id);
1814  }
1815  brush->gpencil_settings->material = ma;
1816  }
1817 }
1818 
1827 {
1830 
1831  /* check if the material is already on object material slots and add it if missing */
1832  if (ma && BKE_gpencil_object_material_index_get(ob, ma) < 0) {
1833  BKE_object_material_slot_add(bmain, ob);
1835  }
1836 
1837  return ma;
1838  }
1839 
1840  /* using active material instead */
1841  return BKE_object_material_get(ob, ob->actcol);
1842 }
1843 
1852 {
1853  if (!material) {
1854  return -1;
1855  }
1857  if (index < 0) {
1858  BKE_object_material_slot_add(bmain, ob);
1860  return ob->totcol - 1;
1861  }
1862  return index;
1863 }
1864 
1873 Material *BKE_gpencil_object_material_new(Main *bmain, Object *ob, const char *name, int *r_index)
1874 {
1875  Material *ma = BKE_gpencil_material_add(bmain, name);
1876  id_us_min(&ma->id); /* no users yet */
1877 
1878  BKE_object_material_slot_add(bmain, ob);
1880 
1881  if (r_index) {
1882  *r_index = ob->actcol - 1;
1883  }
1884  return ma;
1885 }
1886 
1894 {
1895  if ((brush) && (brush->gpencil_settings) &&
1898  return ma;
1899  }
1900 
1901  return BKE_object_material_get(ob, ob->actcol);
1902 }
1903 
1911 {
1912  if ((brush) && (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED)) {
1914  }
1915 
1916  return ob->actcol - 1;
1917 }
1918 
1926  Object *ob,
1927  ToolSettings *ts)
1928 {
1929  if (ts && ts->gp_paint && ts->gp_paint->paint.brush) {
1931  bmain, ob, ts->gp_paint->paint.brush);
1932  }
1933 
1935 }
1936 
1945  Object *ob,
1946  Brush *brush)
1947 {
1948  if (brush) {
1950  if (ma) {
1951  return ma;
1952  }
1954  /* it is easier to just unpin a NULL material, instead of setting a new one */
1956  }
1957  }
1959 }
1960 
1968 {
1969  Material *ma = BKE_object_material_get(ob, ob->actcol);
1970  if (ma) {
1971  return ma;
1972  }
1973 
1975 }
1976 
1983 {
1984  Material *ma = NULL;
1985 
1986  /* sanity checks */
1987  if (ob == NULL) {
1988  return NULL;
1989  }
1990 
1992  if (ma->gp_style == NULL) {
1994  }
1995 
1996  return ma;
1997 }
1998 
1999 /* ************************************************** */
2006 {
2007  const bGPDspoint *pt;
2008  int i;
2009  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
2010  if (pt->flag & GP_SPOINT_SELECT) {
2011  return true;
2012  }
2013  }
2014  return false;
2015 }
2016 
2017 /* ************************************************** */
2018 /* GP Object - Vertex Groups */
2019 
2026 {
2027  bGPdata *gpd = ob->data;
2028  MDeformVert *dvert = NULL;
2029  const int def_nr = BLI_findindex(&ob->defbase, defgroup);
2030  const int totgrp = BLI_listbase_count(&ob->defbase);
2031 
2032  /* Remove points data */
2033  if (gpd) {
2034  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2035  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2036  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
2037  if (gps->dvert != NULL) {
2038  for (int i = 0; i < gps->totpoints; i++) {
2039  dvert = &gps->dvert[i];
2040  MDeformWeight *dw = BKE_defvert_find_index(dvert, def_nr);
2041  if (dw != NULL) {
2042  BKE_defvert_remove_group(dvert, dw);
2043  }
2044  /* Reorganize weights for other groups after deleted one. */
2045  for (int g = 0; g < totgrp; g++) {
2046  dw = BKE_defvert_find_index(dvert, g);
2047  if ((dw != NULL) && (dw->def_nr > def_nr)) {
2048  dw->def_nr--;
2049  }
2050  }
2051  }
2052  }
2053  }
2054  }
2055  }
2056  }
2057 
2058  /* Remove the group */
2059  BLI_freelinkN(&ob->defbase, defgroup);
2061 }
2062 
2068 {
2069  if (gps->dvert == NULL) {
2070  gps->dvert = MEM_callocN(sizeof(MDeformVert) * gps->totpoints, "gp_stroke_weights");
2071  }
2072 }
2073 
2074 /* ************************************************** */
2075 
2084 void BKE_gpencil_frame_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_endframe)
2085 {
2086  *r_initframe = gpl->actframe->framenum;
2087  *r_endframe = gpl->actframe->framenum;
2088 
2089  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2090  if (gpf->flag & GP_FRAME_SELECT) {
2091  if (gpf->framenum < *r_initframe) {
2092  *r_initframe = gpf->framenum;
2093  }
2094  if (gpf->framenum > *r_endframe) {
2095  *r_endframe = gpf->framenum;
2096  }
2097  }
2098  }
2099 }
2100 
2110  bGPDframe *gpf, int actnum, int f_init, int f_end, CurveMapping *cur_falloff)
2111 {
2112  float fnum = 0.5f; /* default mid curve */
2113  float value;
2114 
2115  /* check curve is available */
2116  if (cur_falloff == NULL) {
2117  return 1.0f;
2118  }
2119 
2120  /* frames to the right of the active frame */
2121  if (gpf->framenum < actnum) {
2122  fnum = (float)(gpf->framenum - f_init) / (actnum - f_init);
2123  fnum *= 0.5f;
2124  value = BKE_curvemapping_evaluateF(cur_falloff, 0, fnum);
2125  }
2126  /* frames to the left of the active frame */
2127  else if (gpf->framenum > actnum) {
2128  fnum = (float)(gpf->framenum - actnum) / (f_end - actnum);
2129  fnum *= 0.5f;
2130  value = BKE_curvemapping_evaluateF(cur_falloff, 0, fnum + 0.5f);
2131  }
2132  else {
2133  /* Center of the curve. */
2134  value = BKE_curvemapping_evaluateF(cur_falloff, 0, 0.5f);
2135  }
2136 
2137  return value;
2138 }
2139 
2146 void BKE_gpencil_material_index_reassign(bGPdata *gpd, int totcol, int index)
2147 {
2148  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2149  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2150  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
2151  /* reassign strokes */
2152  if ((gps->mat_nr > index) || (gps->mat_nr > totcol - 1)) {
2153  gps->mat_nr--;
2154  CLAMP_MIN(gps->mat_nr, 0);
2155  }
2156  }
2157  }
2158  }
2159 }
2160 
2168 {
2169  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2170  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2171  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
2172  if (gps->mat_nr == index) {
2173  return true;
2174  }
2175  }
2176  }
2177  }
2178 
2179  return false;
2180 }
2181 
2189  const unsigned int *remap,
2190  unsigned int remap_len)
2191 {
2192  const short remap_len_short = (short)remap_len;
2193 
2194 #define MAT_NR_REMAP(n) \
2195  if (n < remap_len_short) { \
2196  BLI_assert(n >= 0 && remap[n] < remap_len_short); \
2197  n = remap[n]; \
2198  } \
2199  ((void)0)
2200 
2201  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2202  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2203  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
2204  /* reassign strokes */
2205  MAT_NR_REMAP(gps->mat_nr);
2206  }
2207  }
2208  }
2209 
2210 #undef MAT_NR_REMAP
2211 }
2212 
2223  const float hue_threshold,
2224  const float sat_threshold,
2225  const float val_threshold,
2226  GHash *r_mat_table)
2227 {
2228  bool changed = false;
2229 
2230  Material *ma_primary = NULL;
2231  Material *ma_secondary = NULL;
2232  MaterialGPencilStyle *gp_style_primary = NULL;
2233  MaterialGPencilStyle *gp_style_secondary = NULL;
2234  GHash *mat_used = BLI_ghash_int_new(__func__);
2235 
2236  short *totcol = BKE_object_material_len_p(ob);
2237  if (totcol == 0) {
2238  return changed;
2239  }
2240 
2241  for (int idx_primary = 0; idx_primary < *totcol; idx_primary++) {
2242  /* Read primary material to compare. */
2243  ma_primary = BKE_gpencil_material(ob, idx_primary + 1);
2244  if (ma_primary == NULL) {
2245  continue;
2246  }
2247  for (int idx_secondary = 0; idx_secondary < *totcol; idx_secondary++) {
2248  if ((idx_secondary == idx_primary) ||
2249  BLI_ghash_haskey(r_mat_table, POINTER_FROM_INT(idx_secondary))) {
2250  continue;
2251  }
2252  if (BLI_ghash_haskey(mat_used, POINTER_FROM_INT(idx_secondary))) {
2253  continue;
2254  }
2255 
2256  /* Read secondary material to compare with primary material. */
2257  ma_secondary = BKE_gpencil_material(ob, idx_secondary + 1);
2258  if ((ma_secondary == NULL) ||
2259  (BLI_ghash_haskey(r_mat_table, POINTER_FROM_INT(idx_secondary)))) {
2260  continue;
2261  }
2262  gp_style_primary = ma_primary->gp_style;
2263  gp_style_secondary = ma_secondary->gp_style;
2264 
2265  if ((gp_style_primary == NULL) || (gp_style_secondary == NULL) ||
2266  (gp_style_secondary->flag & GP_MATERIAL_LOCKED)) {
2267  continue;
2268  }
2269 
2270  /* Check materials have the same mode. */
2271  if (gp_style_primary->mode != gp_style_secondary->mode) {
2272  continue;
2273  }
2274 
2275  /* Check materials have same stroke and fill attributes. */
2276  if ((gp_style_primary->flag & GP_MATERIAL_STROKE_SHOW) !=
2277  (gp_style_secondary->flag & GP_MATERIAL_STROKE_SHOW)) {
2278  continue;
2279  }
2280 
2281  if ((gp_style_primary->flag & GP_MATERIAL_FILL_SHOW) !=
2282  (gp_style_secondary->flag & GP_MATERIAL_FILL_SHOW)) {
2283  continue;
2284  }
2285 
2286  /* Check materials have the same type. */
2287  if ((gp_style_primary->stroke_style != gp_style_secondary->stroke_style) ||
2288  (gp_style_primary->fill_style != gp_style_secondary->fill_style)) {
2289  continue;
2290  }
2291 
2292  float s_hsv_a[3], s_hsv_b[3], f_hsv_a[3], f_hsv_b[3], col[3];
2293  zero_v3(s_hsv_a);
2294  zero_v3(s_hsv_b);
2295  zero_v3(f_hsv_a);
2296  zero_v3(f_hsv_b);
2297 
2298  copy_v3_v3(col, gp_style_primary->stroke_rgba);
2299  rgb_to_hsv_compat_v(col, s_hsv_a);
2300  copy_v3_v3(col, gp_style_secondary->stroke_rgba);
2301  rgb_to_hsv_compat_v(col, s_hsv_b);
2302 
2303  copy_v3_v3(col, gp_style_primary->fill_rgba);
2304  rgb_to_hsv_compat_v(col, f_hsv_a);
2305  copy_v3_v3(col, gp_style_secondary->fill_rgba);
2306  rgb_to_hsv_compat_v(col, f_hsv_b);
2307 
2308  /* Check stroke and fill color. */
2309  if ((!compare_ff(s_hsv_a[0], s_hsv_b[0], hue_threshold)) ||
2310  (!compare_ff(s_hsv_a[1], s_hsv_b[1], sat_threshold)) ||
2311  (!compare_ff(s_hsv_a[2], s_hsv_b[2], val_threshold)) ||
2312  (!compare_ff(f_hsv_a[0], f_hsv_b[0], hue_threshold)) ||
2313  (!compare_ff(f_hsv_a[1], f_hsv_b[1], sat_threshold)) ||
2314  (!compare_ff(f_hsv_a[2], f_hsv_b[2], val_threshold)) ||
2315  (!compare_ff(gp_style_primary->stroke_rgba[3],
2316  gp_style_secondary->stroke_rgba[3],
2317  val_threshold)) ||
2318  (!compare_ff(
2319  gp_style_primary->fill_rgba[3], gp_style_secondary->fill_rgba[3], val_threshold))) {
2320  continue;
2321  }
2322 
2323  /* Save conversion indexes. */
2324  if (!BLI_ghash_haskey(r_mat_table, POINTER_FROM_INT(idx_secondary))) {
2326  r_mat_table, POINTER_FROM_INT(idx_secondary), POINTER_FROM_INT(idx_primary));
2327  changed = true;
2328 
2329  if (!BLI_ghash_haskey(mat_used, POINTER_FROM_INT(idx_primary))) {
2330  BLI_ghash_insert(mat_used, POINTER_FROM_INT(idx_primary), POINTER_FROM_INT(idx_primary));
2331  }
2332  }
2333  }
2334  }
2335  /* Free hash memory. */
2336  BLI_ghash_free(mat_used, NULL, NULL);
2337 
2338  return changed;
2339 }
2340 
2351  const float hue_threshold,
2352  const float sat_threshold,
2353  const float val_threshold,
2354  int *r_removed)
2355 {
2356  bGPdata *gpd = ob->data;
2357 
2358  short *totcol = BKE_object_material_len_p(ob);
2359  if (totcol == 0) {
2360  *r_removed = 0;
2361  return 0;
2362  }
2363 
2364  /* Review materials. */
2365  GHash *mat_table = BLI_ghash_int_new(__func__);
2366 
2368  ob, hue_threshold, sat_threshold, val_threshold, mat_table);
2369 
2370  *r_removed = BLI_ghash_len(mat_table);
2371 
2372  /* Update stroke material index. */
2373  if (changed) {
2374  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2375  if (gpl->flag & GP_LAYER_HIDE) {
2376  continue;
2377  }
2378 
2379  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2380  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
2381  /* Check if the color is editable. */
2382  MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
2383  if (gp_style != NULL) {
2384  if (gp_style->flag & GP_MATERIAL_HIDE) {
2385  continue;
2386  }
2387  if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) &&
2388  (gp_style->flag & GP_MATERIAL_LOCKED)) {
2389  continue;
2390  }
2391  }
2392 
2393  if (BLI_ghash_haskey(mat_table, POINTER_FROM_INT(gps->mat_nr))) {
2394  int *idx = BLI_ghash_lookup(mat_table, POINTER_FROM_INT(gps->mat_nr));
2395  gps->mat_nr = POINTER_AS_INT(idx);
2396  }
2397  }
2398  }
2399  }
2400  }
2401 
2402  /* Free hash memory. */
2403  BLI_ghash_free(mat_table, NULL, NULL);
2404 
2405  return changed;
2406 }
2407 
2413 {
2414  gpd->totlayer = 0;
2415  gpd->totframe = 0;
2416  gpd->totstroke = 0;
2417  gpd->totpoint = 0;
2418 
2419  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2420  gpd->totlayer++;
2421  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2422  gpd->totframe++;
2423  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
2424  gpd->totstroke++;
2425  gpd->totpoint += gps->totpoints;
2426  }
2427  }
2428  }
2429 }
2430 
2438 {
2439  short *totcol = BKE_object_material_len_p(ob);
2440  Material *read_ma = NULL;
2441  for (short i = 0; i < *totcol; i++) {
2442  read_ma = BKE_object_material_get(ob, i + 1);
2443  if (ma == read_ma) {
2444  return i;
2445  }
2446  }
2447 
2448  return -1;
2449 }
2450 
2452 {
2453  short *totcol = BKE_object_material_len_p(ob);
2454  Material *read_ma = NULL;
2455  for (short i = 0; i < *totcol; i++) {
2456  read_ma = BKE_object_material_get(ob, i + 1);
2457  /* Material names are like "MAMaterial.001" */
2458  if (STREQ(name, &read_ma->id.name[2])) {
2459  return i;
2460  }
2461  }
2462 
2463  return -1;
2464 }
2465 
2467  Object *ob,
2468  const char *name,
2469  int *r_index)
2470 {
2472  if (index != -1) {
2473  *r_index = index;
2474  return BKE_object_material_get(ob, index + 1);
2475  }
2476  return BKE_gpencil_object_material_new(bmain, ob, name, r_index);
2477 }
2478 
2485 {
2486  const char *hexcol[] = {
2487  "FFFFFF", "F2F2F2", "E6E6E6", "D9D9D9", "CCCCCC", "BFBFBF", "B2B2B2", "A6A6A6", "999999",
2488  "8C8C8C", "808080", "737373", "666666", "595959", "4C4C4C", "404040", "333333", "262626",
2489  "1A1A1A", "000000", "F2FC24", "FFEA00", "FEA711", "FE8B68", "FB3B02", "FE3521", "D00000",
2490  "A81F3D", "780422", "2B0000", "F1E2C5", "FEE4B3", "FEDABB", "FEC28E", "D88F57", "BD6340",
2491  "A2402B", "63352D", "6B2833", "34120C", "E7CB8F", "D1B38B", "C1B17F", "D7980B", "FFB100",
2492  "FE8B00", "FF6A00", "B74100", "5F3E1D", "3B2300", "FECADA", "FE65CB", "FE1392", "DD3062",
2493  "C04A6D", "891688", "4D2689", "441521", "2C1139", "241422", "FFFF7D", "FFFF00", "FF7F00",
2494  "FF7D7D", "FF7DFF", "FF00FE", "FF007F", "FF0000", "7F0000", "0A0A00", "F6FDFF", "E9F7FF",
2495  "CFE6FE", "AAC7FE", "77B3FE", "1E74FD", "0046AA", "2F4476", "003052", "0E0E25", "EEF5F0",
2496  "D6E5DE", "ACD8B9", "6CADC6", "42A9AF", "007F7F", "49675C", "2E4E4E", "1D3239", "0F1C21",
2497  "D8FFF4", "B8F4F5", "AECCB5", "76C578", "358757", "409B68", "468768", "1F512B", "2A3C37",
2498  "122E1D", "EFFFC9", "E6F385", "BCF51C", "D4DC18", "82D322", "5C7F00", "59932B", "297F00",
2499  "004320", "1C3322", "00FF7F", "00FF00", "7DFF7D", "7DFFFF", "00FFFF", "7D7DFF", "7F00FF",
2500  "0000FF", "3F007F", "00007F"};
2501 
2503  if (ts->gp_paint->paint.palette != NULL) {
2504  return;
2505  }
2506 
2507  /* Try to find the default palette. */
2508  const char *palette_id = "Palette";
2509  struct Palette *palette = BLI_findstring(&bmain->palettes, palette_id, offsetof(ID, name) + 2);
2510 
2511  if (palette == NULL) {
2512  /* Fall back to the first palette. */
2513  palette = bmain->palettes.first;
2514  }
2515 
2516  if (palette == NULL) {
2517  /* Fall back to creating a palette. */
2518  palette = BKE_palette_add(bmain, palette_id);
2519  id_us_min(&palette->id);
2520 
2521  /* Create Colors. */
2522  for (int i = 0; i < ARRAY_SIZE(hexcol); i++) {
2523  PaletteColor *palcol = BKE_palette_color_add(palette);
2524  hex_to_rgb(hexcol[i], palcol->rgb, palcol->rgb + 1, palcol->rgb + 2);
2525  }
2526  }
2527 
2528  BLI_assert(palette != NULL);
2529  BKE_paint_palette_set(&ts->gp_paint->paint, palette);
2530  BKE_paint_palette_set(&ts->gp_vertexpaint->paint, palette);
2531 }
2532 
2543  SpaceImage *sima, bGPdata *gpd, bGPDframe *gpf, const float size, const bool mask)
2544 {
2545  Image *image = sima->image;
2546  bool done = false;
2547 
2548  if (image == NULL) {
2549  return false;
2550  }
2551 
2552  ImageUser iuser = sima->iuser;
2553  void *lock;
2554  ImBuf *ibuf;
2555 
2556  ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
2557 
2558  if (ibuf && ibuf->rect) {
2559  int img_x = ibuf->x;
2560  int img_y = ibuf->y;
2561 
2562  float color[4];
2563  bGPDspoint *pt;
2564  for (int row = 0; row < img_y; row++) {
2565  /* Create new stroke */
2566  bGPDstroke *gps = BKE_gpencil_stroke_add(gpf, 0, img_x, size * 1000, false);
2567  done = true;
2568  for (int col = 0; col < img_x; col++) {
2569  IMB_sampleImageAtLocation(ibuf, col, row, true, color);
2570  pt = &gps->points[col];
2571  pt->pressure = 1.0f;
2572  pt->x = col * size;
2573  pt->z = row * size;
2574  if (!mask) {
2575  copy_v3_v3(pt->vert_color, color);
2576  pt->vert_color[3] = 1.0f;
2577  pt->strength = color[3];
2578  }
2579  else {
2580  zero_v3(pt->vert_color);
2581  pt->vert_color[3] = 1.0f;
2582  pt->strength = 1.0f - color[3];
2583  }
2584 
2585  /* Selet Alpha points. */
2586  if (pt->strength < 0.03f) {
2587  gps->flag |= GP_STROKE_SELECT;
2588  pt->flag |= GP_SPOINT_SELECT;
2589  }
2590  }
2591 
2592  if (gps->flag & GP_STROKE_SELECT) {
2594  }
2595 
2597  }
2598  }
2599 
2600  /* Free memory. */
2601  BKE_image_release_ibuf(image, ibuf, lock);
2602 
2603  return done;
2604 }
2605 
2613 static bool gpencil_is_layer_mask(ViewLayer *view_layer, bGPdata *gpd, bGPDlayer *gpl_mask)
2614 {
2615  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2616  if ((gpl->viewlayername[0] != '\0') && (!STREQ(view_layer->name, gpl->viewlayername))) {
2617  continue;
2618  }
2619 
2620  LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl->mask_layers) {
2621  if (STREQ(gpl_mask->info, mask->name)) {
2622  return true;
2623  }
2624  }
2625  }
2626 
2627  return false;
2628 }
2629 
2630 /* -------------------------------------------------------------------- */
2638  Object *ob,
2639  gpIterCb layer_cb,
2640  gpIterCb stroke_cb,
2641  void *thunk,
2642  bool do_onion,
2643  int cfra)
2644 {
2645  bGPdata *gpd = (bGPdata *)ob->data;
2646  const bool is_multiedit = ((GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) && (!GPENCIL_PLAY_ON(gpd)));
2647  const bool is_onion = do_onion && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0);
2648  const bool is_drawing = (gpd->runtime.sbuffer_used > 0);
2649 
2650  /* Onion skinning. */
2651  const bool onion_mode_abs = (gpd->onion_mode == GP_ONION_MODE_ABSOLUTE);
2652  const bool onion_mode_sel = (gpd->onion_mode == GP_ONION_MODE_SELECTED);
2653  const bool onion_loop = (gpd->onion_flag & GP_ONION_LOOP) != 0;
2654  const short onion_keytype = gpd->onion_keytype;
2655 
2656  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2657  /* Reset by layer. */
2658  bool is_before_first = false;
2659 
2660  bGPDframe *act_gpf = gpl->actframe;
2661  bGPDframe *sta_gpf = act_gpf;
2662  bGPDframe *end_gpf = act_gpf ? act_gpf->next : NULL;
2663  float prev_opacity = gpl->opacity;
2664 
2665  if (gpl->flag & GP_LAYER_HIDE) {
2666  continue;
2667  }
2668 
2669  /* If scale to 0 the layer must be invisible. */
2670  if (is_zero_v3(gpl->scale)) {
2671  continue;
2672  }
2673 
2674  /* Hide the layer if it's defined a view layer filter. This is used to
2675  * generate renders, putting only selected GP layers for each View Layer.
2676  * This is used only in final render and never in Viewport. */
2677  if ((view_layer != NULL) && (gpl->viewlayername[0] != '\0') &&
2678  (!STREQ(view_layer->name, gpl->viewlayername))) {
2679  /* Do not skip masks when rendering the viewlayer so that it can still be used to clip
2680  * other layers. Instead set their opacity to zero. */
2681  if (gpencil_is_layer_mask(view_layer, gpd, gpl)) {
2682  gpl->opacity = 0.0f;
2683  }
2684  else {
2685  continue;
2686  }
2687  }
2688 
2689  if (is_multiedit) {
2690  sta_gpf = end_gpf = NULL;
2691  /* Check the whole range and tag the editable frames. */
2692  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2693  if (act_gpf != NULL && (gpf == act_gpf || (gpf->flag & GP_FRAME_SELECT))) {
2694  gpf->runtime.onion_id = 0;
2695  if (do_onion) {
2696  if (gpf->framenum < act_gpf->framenum) {
2697  gpf->runtime.onion_id = -1;
2698  }
2699  else {
2700  gpf->runtime.onion_id = 1;
2701  }
2702  }
2703 
2704  if (sta_gpf == NULL) {
2705  sta_gpf = gpf;
2706  }
2707  end_gpf = gpf->next;
2708  }
2709  else {
2710  gpf->runtime.onion_id = INT_MAX;
2711  }
2712  }
2713  }
2714  else if (is_onion && (gpl->onion_flag & GP_LAYER_ONIONSKIN)) {
2715  /* Special cases when cframe is before first frame. */
2716  bGPDframe *gpf_first = gpl->frames.first;
2717  if ((gpf_first != NULL) && (act_gpf != NULL) && (gpf_first->framenum > act_gpf->framenum)) {
2718  is_before_first = true;
2719  }
2720  if ((gpf_first != NULL) && (act_gpf == NULL)) {
2721  act_gpf = gpf_first;
2722  is_before_first = true;
2723  }
2724 
2725  if (act_gpf) {
2726  bGPDframe *last_gpf = gpl->frames.last;
2727 
2728  int frame_len = 0;
2729  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2730  gpf->runtime.frameid = frame_len++;
2731  }
2732 
2733  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
2734  bool is_wrong_keytype = (onion_keytype > -1) && (gpf->key_type != onion_keytype);
2735  bool is_in_range;
2736  int delta = (onion_mode_abs) ? (gpf->framenum - cfra) :
2737  (gpf->runtime.frameid - act_gpf->runtime.frameid);
2738 
2739  if (is_before_first) {
2740  delta++;
2741  }
2742 
2743  if (onion_mode_sel) {
2744  is_in_range = (gpf->flag & GP_FRAME_SELECT) != 0;
2745  }
2746  else {
2747  is_in_range = (-delta <= gpd->gstep) && (delta <= gpd->gstep_next);
2748 
2749  if (onion_loop && !is_in_range) {
2750  /* We wrap the value using the last frame and 0 as reference. */
2751  /* FIXME: This might not be good for animations not starting at 0. */
2752  int shift = (onion_mode_abs) ? last_gpf->framenum : last_gpf->runtime.frameid;
2753  delta += (delta < 0) ? (shift + 1) : -(shift + 1);
2754  /* Test again with wrapped value. */
2755  is_in_range = (-delta <= gpd->gstep) && (delta <= gpd->gstep_next);
2756  }
2757  }
2758  /* Mask frames that have wrong keytype of are not in range. */
2759  gpf->runtime.onion_id = (is_wrong_keytype || !is_in_range) ? INT_MAX : delta;
2760  }
2761  /* Active frame is always shown. */
2762  if (!is_before_first || is_drawing) {
2763  act_gpf->runtime.onion_id = 0;
2764  }
2765  }
2766 
2767  sta_gpf = gpl->frames.first;
2768  end_gpf = NULL;
2769  }
2770  else {
2771  /* Bypass multiedit/onion skinning. */
2772  end_gpf = sta_gpf = NULL;
2773  }
2774 
2775  if (sta_gpf == NULL && act_gpf == NULL) {
2776  if (layer_cb) {
2777  layer_cb(gpl, act_gpf, NULL, thunk);
2778  }
2779  gpl->opacity = prev_opacity;
2780  continue;
2781  }
2782 
2783  /* Draw multiedit/onion skinning first */
2784  for (bGPDframe *gpf = sta_gpf; gpf && gpf != end_gpf; gpf = gpf->next) {
2785  if ((gpf->runtime.onion_id == INT_MAX || gpf == act_gpf) && (!is_before_first)) {
2786  continue;
2787  }
2788 
2789  /* Only do once for frame before first. */
2790  if (is_before_first && gpf == act_gpf) {
2791  is_before_first = false;
2792  }
2793 
2794  if (layer_cb) {
2795  layer_cb(gpl, gpf, NULL, thunk);
2796  }
2797 
2798  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
2799  if (gps->totpoints == 0) {
2800  continue;
2801  }
2802  stroke_cb(gpl, gpf, gps, thunk);
2803  }
2804  }
2805  /* Draw Active frame on top. */
2806  /* Use evaluated frame (with modifiers for active stroke)/ */
2807  act_gpf = gpl->actframe;
2808  if (act_gpf) {
2809  act_gpf->runtime.onion_id = 0;
2810  if (layer_cb) {
2811  layer_cb(gpl, act_gpf, NULL, thunk);
2812  }
2813 
2814  /* If layer solo mode and Paint mode, only keyframes with data are displayed. */
2815  if (GPENCIL_PAINT_MODE(gpd) && (gpl->flag & GP_LAYER_SOLO_MODE) &&
2816  (act_gpf->framenum != cfra)) {
2817  gpl->opacity = prev_opacity;
2818  continue;
2819  }
2820 
2821  LISTBASE_FOREACH (bGPDstroke *, gps, &act_gpf->strokes) {
2822  if (gps->totpoints == 0) {
2823  continue;
2824  }
2825  stroke_cb(gpl, act_gpf, gps, thunk);
2826  }
2827  }
2828 
2829  /* Restore the opacity in case it was overwritten (used to hide masks in render). */
2830  gpl->opacity = prev_opacity;
2831  }
2832 }
2833 
2840  const struct bGPDframe *gpf_eval)
2841 {
2842  bGPDstroke *gps_eval = gpf_eval->strokes.first;
2843  LISTBASE_FOREACH (bGPDstroke *, gps_orig, &gpf_orig->strokes) {
2844 
2845  /* Assign original stroke pointer. */
2846  if (gps_eval != NULL) {
2847  gps_eval->runtime.gps_orig = gps_orig;
2848 
2849  /* Assign original point pointer. */
2850  for (int i = 0; i < gps_orig->totpoints; i++) {
2851  if (i > gps_eval->totpoints - 1) {
2852  break;
2853  }
2854  bGPDspoint *pt_orig = &gps_orig->points[i];
2855  bGPDspoint *pt_eval = &gps_eval->points[i];
2856  pt_orig->runtime.pt_orig = NULL;
2857  pt_orig->runtime.idx_orig = i;
2858  pt_eval->runtime.pt_orig = pt_orig;
2859  pt_eval->runtime.idx_orig = i;
2860  }
2861  /* Increase pointer. */
2862  gps_eval = gps_eval->next;
2863  }
2864  }
2865 }
2866 
2872 void BKE_gpencil_update_orig_pointers(const Object *ob_orig, const Object *ob_eval)
2873 {
2874  bGPdata *gpd_eval = (bGPdata *)ob_eval->data;
2875  bGPdata *gpd_orig = (bGPdata *)ob_orig->data;
2876 
2877  /* Assign pointers to the original stroke and points to the evaluated data. This must
2878  * be done before applying any modifier because at this moment the structure is equals,
2879  * so we can assume the layer index is the same in both data-blocks.
2880  * This data will be used by operators. */
2881 
2882  bGPDlayer *gpl_eval = gpd_eval->layers.first;
2883  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_orig->layers) {
2884  if (gpl_eval != NULL) {
2885  /* Update layer reference pointers. */
2886  gpl_eval->runtime.gpl_orig = (bGPDlayer *)gpl;
2887 
2888  bGPDframe *gpf_eval = gpl_eval->frames.first;
2889  LISTBASE_FOREACH (bGPDframe *, gpf_orig, &gpl->frames) {
2890  if (gpf_eval != NULL) {
2891  /* Update frame reference pointers. */
2892  gpf_eval->runtime.gpf_orig = (bGPDframe *)gpf_orig;
2893  BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf_eval);
2894  gpf_eval = gpf_eval->next;
2895  }
2896  }
2897  gpl_eval = gpl_eval->next;
2898  }
2899  }
2900 }
2901 
2910  Object *obact,
2911  bGPDlayer *gpl,
2912  float diff_mat[4][4])
2913 {
2914  Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact;
2915  Object *obparent = gpl->parent;
2916  Object *obparent_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obparent) :
2917  obparent;
2918 
2919  /* if not layer parented, try with object parented */
2920  if (obparent_eval == NULL) {
2921  if ((ob_eval != NULL) && (ob_eval->type == OB_GPENCIL)) {
2922  copy_m4_m4(diff_mat, ob_eval->obmat);
2923  mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat);
2924  return;
2925  }
2926  /* not gpencil object */
2927  unit_m4(diff_mat);
2928  return;
2929  }
2930 
2931  if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) {
2932  mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
2933  add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
2934  mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat);
2935  return;
2936  }
2937  if (gpl->partype == PARBONE) {
2938  bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr);
2939  if (pchan) {
2940  float tmp_mat[4][4];
2941  mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat);
2942  mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse);
2943  add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
2944  }
2945  else {
2946  /* if bone not found use object (armature) */
2947  mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
2948  add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
2949  }
2950  mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat);
2951  return;
2952  }
2953 
2954  unit_m4(diff_mat); /* not defined type */
2955 }
2956 
2963 {
2964  if (ob->type != OB_GPENCIL) {
2965  return;
2966  }
2967 
2968  bGPdata *gpd = (bGPdata *)ob->data;
2969  float cur_mat[4][4];
2970 
2971  bool changed = false;
2972  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
2973  unit_m4(cur_mat);
2974  if (gpl->actframe != NULL) {
2975  if (gpl->parent != NULL) {
2976  Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent);
2977  /* calculate new matrix */
2978  if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) {
2979  copy_m4_m4(cur_mat, ob_parent->obmat);
2980  }
2981  else if (gpl->partype == PARBONE) {
2982  bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr);
2983  if (pchan != NULL) {
2984  copy_m4_m4(cur_mat, ob->imat);
2985  mul_m4_m4m4(cur_mat, ob_parent->obmat, pchan->pose_mat);
2986  }
2987  else {
2988  unit_m4(cur_mat);
2989  }
2990  }
2991  changed = !equals_m4m4(gpl->inverse, cur_mat);
2992  }
2993 
2994  /* Calc local layer transform. Early out if we have non-animated zero transforms. */
2995  bool transformed = ((!is_zero_v3(gpl->location)) || (!is_zero_v3(gpl->rotation)) ||
2996  (!is_one_v3(gpl->scale)));
2997  float tmp_mat[4][4];
2998  loc_eul_size_to_mat4(tmp_mat, gpl->location, gpl->rotation, gpl->scale);
2999  transformed |= !equals_m4m4(gpl->layer_mat, tmp_mat);
3000  if (transformed) {
3001  copy_m4_m4(gpl->layer_mat, tmp_mat);
3002  }
3003 
3004  /* only redo if any change */
3005  if (changed || transformed) {
3006  LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) {
3007  bGPDspoint *pt;
3008  int i;
3009  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
3010  if (changed) {
3011  mul_m4_v3(gpl->inverse, &pt->x);
3012  mul_m4_v3(cur_mat, &pt->x);
3013  }
3014 
3015  if (transformed) {
3016  mul_m4_v3(gpl->layer_mat, &pt->x);
3017  }
3018  }
3019  }
3020  }
3021  }
3022  }
3023 }
3024 
3032 {
3033  const int name_prefix_len = strlen(name_prefix);
3034  for (int i = 0; i < ob->totcol; i++) {
3035  Material *ma = BKE_object_material_get(ob, i + 1);
3036  if ((ma != NULL) && (ma->gp_style != NULL) &&
3037  (STREQLEN(ma->id.name + 2, name_prefix, name_prefix_len))) {
3038  return i;
3039  }
3040  }
3041 
3042  return -1;
3043 }
3044 
3045 /* Create a hash with the list of selected frame number. */
3047 {
3048  const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
3050 
3051  LISTBASE_FOREACH (bGPDlayer *, gpl_iter, &gpd->layers) {
3052  if ((gpl != NULL) && (!is_multiedit) && (gpl != gpl_iter)) {
3053  continue;
3054  }
3055 
3056  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_iter->frames) {
3057  if (((gpf == gpl->actframe) && (!is_multiedit)) ||
3058  ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
3059  if (!BLI_ghash_lookup(r_list, POINTER_FROM_INT(gpf->framenum))) {
3060  BLI_ghash_insert(r_list, POINTER_FROM_INT(gpf->framenum), gpf);
3061  }
3062  }
3063  }
3064  }
3065 }
3066 
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
void BKE_animdata_blend_read_data(struct BlendDataReader *reader, struct AnimData *adt)
Definition: anim_data.c:1574
void BKE_animdata_blend_write(struct BlendWriter *writer, struct AnimData *adt)
Definition: anim_data.c:1552
float BKE_curvemapping_evaluateF(const struct CurveMapping *cumap, int cur, float value)
support for deformation groups and hooks.
void BKE_defvert_blend_write(struct BlendWriter *writer, int count, struct MDeformVert *dvlist)
Definition: deform.c:1525
struct MDeformWeight * BKE_defvert_find_index(const struct MDeformVert *dv, const int defgroup)
void BKE_defvert_array_copy(struct MDeformVert *dst, const struct MDeformVert *src, int totvert)
void BKE_defvert_blend_read(struct BlendDataReader *reader, int count, struct MDeformVert *mdverts)
Definition: deform.c:1542
void BKE_defvert_remove_group(struct MDeformVert *dvert, struct MDeformWeight *dw)
Definition: deform.c:754
void(* gpIterCb)(struct bGPDlayer *layer, struct bGPDframe *frame, struct bGPDstroke *stroke, void *thunk)
Definition: BKE_gpencil.h:279
#define GP_PRIM_DATABUF_SIZE
Definition: BKE_gpencil.h:157
eGP_GetFrame_Mode
Definition: BKE_gpencil.h:185
@ GP_GETFRAME_ADD_COPY
Definition: BKE_gpencil.h:192
@ GP_GETFRAME_USE_PREV
Definition: BKE_gpencil.h:187
void BKE_gpencil_stroke_geometry_update(struct bGPdata *gpd, struct bGPDstroke *gps)
bool BKE_icon_delete(const int icon_id)
Definition: icons.cc:940
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock)
Definition: image.c:5113
struct ImBuf * BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock)
Definition: image.c:5100
struct ID * BKE_id_copy(struct Main *bmain, const struct ID *id)
void id_us_min(struct ID *id)
Definition: lib_id.c:297
void BKE_libblock_free_data(struct ID *id, const bool do_id_user) ATTR_NONNULL()
Definition: lib_id_delete.c:55
void * BKE_libblock_alloc(struct Main *bmain, short type, const char *name, const int flag) ATTR_WARN_UNUSED_RESULT
Definition: lib_id.c:1062
void id_us_plus(struct ID *id)
Definition: lib_id.c:288
void BKE_id_blend_write(struct BlendWriter *writer, struct ID *id)
Definition: lib_id.c:2395
#define BKE_LIB_FOREACHID_PROCESS(_data, _id_super, _cb_flag)
@ IDWALK_CB_USER
Definition: BKE_lib_query.h:87
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:47
General operations, lookup, etc. for materials.
struct MaterialGPencilStyle * BKE_gpencil_material_settings(struct Object *ob, short act)
Definition: material.c:713
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:697
@ BKE_MAT_ASSIGN_USERPREF
Definition: BKE_material.h:71
struct Material * BKE_gpencil_material(struct Object *ob, short act)
Definition: material.c:703
struct Material * BKE_gpencil_material_add(struct Main *bmain, const char *name)
Definition: material.c:310
void BKE_object_material_assign(struct Main *bmain, struct Object *ob, struct Material *ma, short act, int assign_type)
Definition: material.c:850
struct Material * BKE_material_default_gpencil(void)
Definition: material.c:1839
void BKE_gpencil_material_attr_init(struct Material *ma)
Definition: material.c:282
bool BKE_object_material_slot_add(struct Main *bmain, struct Object *ob)
Definition: material.c:1091
short * BKE_object_material_len_p(struct Object *ob)
Definition: material.c:356
struct Palette * BKE_palette_add(struct Main *bmain, const char *name)
Definition: paint.c:751
void BKE_paint_palette_set(struct Paint *p, struct Palette *palette)
Definition: paint.c:705
struct PaletteColor * BKE_palette_color_add(struct Palette *palette)
Definition: paint.c:757
#define BLI_assert(a)
Definition: BLI_assert.h:58
unsigned int BLI_ghash_len(GHash *gh) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:744
bool BLI_ghash_haskey(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:941
GHash * BLI_ghash_int_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:756
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
void * BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:803
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:87
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:281
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:188
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:128
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:352
void * BLI_findstring(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
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.c: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.c:395
void void void BLI_listbase_sort_r(ListBase *listbase, int(*cmp)(void *, const void *, const void *), void *thunk) ATTR_NONNULL(1
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int compare_ff(float a, float b, const float max_diff)
void rgb_to_hsv_compat_v(const float rgb[3], float r_hsv[3])
Definition: math_color.c:342
void hex_to_rgb(const char *hexcol, float *r_r, float *r_g, float *r_b)
Definition: math_color.c:198
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:262
void unit_m4(float m[4][4])
Definition: rct.c:1140
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
bool equals_m4m4(const float mat1[4][4], const float mat2[4][4])
Definition: math_matrix.c:2612
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:95
void loc_eul_size_to_mat4(float R[4][4], const float loc[3], const float eul[3], const float size[3])
Definition: math_matrix.c:2653
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE bool is_one_v3(const float a[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)
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
bool BLI_uniquename(struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t len)
Definition: string_utils.c:381
#define ARRAY_SIZE(arr)
#define ARRAY_SET_ITEMS(...)
#define STREQLEN(a, b, n)
#define POINTER_FROM_INT(i)
#define UNUSED(x)
#define POINTER_AS_INT(i)
#define ELEM(...)
#define STREQ(a, b)
#define CLAMP_MIN(a, b)
#define BLO_read_data_address(reader, ptr_p)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_read_list(BlendDataReader *reader, struct ListBase *list)
Definition: readfile.c:5654
#define BLO_read_id_address(reader, lib, id_ptr_p)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_expand(expander, id)
#define BLO_write_struct_list(writer, struct_name, list_ptr)
void BLO_read_pointer_array(BlendDataReader *reader, void **ptr_p)
Definition: readfile.c:5727
bool BLO_write_is_undo(BlendWriter *writer)
Definition: writefile.c:1412
void BLO_write_pointer_array(BlendWriter *writer, uint num, const void *data_ptr)
Definition: writefile.c:1388
#define BLT_I18NCONTEXT_ID_GPENCIL
#define DATA_(msgid)
#define CLOG_ERROR(clg_ref,...)
Definition: CLG_log.h:204
#define CLOG_STR_ERROR(clg_ref, str)
Definition: CLG_log.h:210
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:599
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
#define FILTER_ID_GD
Definition: DNA_ID.h:710
@ INDEX_ID_GD
Definition: DNA_ID.h:791
@ ID_GD
Definition: DNA_ID_enums.h:83
@ GP_BRUSH_MATERIAL_PINNED
#define BEZT_ISSEL_ANY(bezt)
@ 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)
@ GP_CURVE_SELECT
@ GP_STROKE_SELECT
@ GP_STROKE_3DSPACE
#define GP_DEFAULT_CURVE_RESOLUTION
#define GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)
#define GPENCIL_PAINT_MODE(gpd)
struct bGPdata bGPdata
@ GP_LAYER_SOLO_MODE
@ GP_LAYER_LOCKED
@ GP_LAYER_FRAMELOCK
@ GP_LAYER_ACTIVE
@ GP_LAYER_UNLOCK_COLOR
@ GP_LAYER_HIDE
@ GP_LAYER_USE_LIGHTS
#define GP_DEFAULT_GRID_LINES
@ GP_LAYER_ONIONSKIN
#define GP_DEFAULT_CURVE_ERROR
@ GP_ONION_GHOST_NEXTCOL
@ GP_ONION_GHOST_PREVCOL
@ GP_ONION_FADE
@ GP_ONION_LOOP
@ GP_FRAME_SELECT
@ GP_FRAME_PAINT
@ GP_DATA_SHOW_ONIONSKINS
@ GP_DATA_VIEWALIGN
@ GP_DATA_CURVE_ADAPTIVE_RESOLUTION
@ GP_DATA_STROKE_WEIGHTMODE
@ GP_DATA_EXPAND
@ GP_DATA_DISPINFO
@ GP_DATA_STROKE_VERTEXMODE
@ GP_DATA_STROKE_PAINTMODE
@ GP_DATA_STROKE_SCULPTMODE
@ GP_DATA_AUTOLOCK_LAYERS
@ GP_DATA_ANNOTATIONS
@ GP_DATA_STROKE_EDITMODE
@ GP_SPOINT_SELECT
@ GP_MATERIAL_LOCKED
@ GP_MATERIAL_HIDE
@ GP_MATERIAL_STROKE_SHOW
@ GP_MATERIAL_FILL_SHOW
@ PARSKEL
@ PAROBJECT
@ PARBONE
@ OB_GPENCIL
void IMB_sampleImageAtLocation(struct ImBuf *ibuf, float x, float y, bool make_linear_rgb, float color[4])
Definition: imageprocess.c:505
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static void init_data(ModifierData *md)
static float frame_len(const Frame *frame)
Definition: MOD_skin.c:392
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
unsigned int U
Definition: btGjkEpa3.h:78
Scene scene
Material material
const Depsgraph * depsgraph
Material * BKE_gpencil_object_material_ensure_from_active_input_toolsettings(Main *bmain, Object *ob, ToolSettings *ts)
Definition: gpencil.c:1925
void BKE_gpencil_tag(bGPdata *gpd)
Definition: gpencil.c:525
bool BKE_gpencil_merge_materials_table_get(Object *ob, const float hue_threshold, const float sat_threshold, const float val_threshold, GHash *r_mat_table)
Definition: gpencil.c:2222
void BKE_gpencil_free_stroke_weights(bGPDstroke *gps)
Definition: gpencil.c:370
bool BKE_gpencil_stroke_select_check(const bGPDstroke *gps)
Definition: gpencil.c:2005
bGPDcurve * BKE_gpencil_stroke_editcurve_new(const int tot_curve_points)
Definition: gpencil.c:910
bGPDlayer * BKE_gpencil_layer_active_get(bGPdata *gpd)
Definition: gpencil.c:1650
void BKE_gpencil_frame_range_selected(bGPDlayer *gpl, int *r_initframe, int *r_endframe)
Definition: gpencil.c:2084
void BKE_gpencil_stats_update(bGPdata *gpd)
Definition: gpencil.c:2412
int BKE_gpencil_object_material_get_index_from_brush(Object *ob, Brush *brush)
Definition: gpencil.c:1910
void BKE_gpencil_batch_cache_free(bGPdata *gpd)
Definition: gpencil.c:351
void BKE_gpencil_material_remap(struct bGPdata *gpd, const unsigned int *remap, unsigned int remap_len)
Definition: gpencil.c:2188
void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer, Object *ob, gpIterCb layer_cb, gpIterCb stroke_cb, void *thunk, bool do_onion, int cfra)
Definition: gpencil.c:2637
void BKE_gpencil_free_frames(bGPDlayer *gpl)
Definition: gpencil.c:439
static int gpencil_cb_sort_masks(const void *arg1, const void *arg2)
Definition: gpencil.c:1566
Material * BKE_gpencil_object_material_ensure_by_name(Main *bmain, Object *ob, const char *name, int *r_index)
Definition: gpencil.c:2466
void BKE_gpencil_free_point_weights(MDeformVert *dvert)
Definition: gpencil.c:362
static bool gpencil_is_layer_mask(ViewLayer *view_layer, bGPdata *gpd, bGPDlayer *gpl_mask)
Definition: gpencil.c:2613
static void greasepencil_blend_read_lib(BlendLibReader *reader, ID *id)
Definition: gpencil.c:280
void BKE_gpencil_layer_mask_remove(bGPDlayer *gpl, bGPDlayer_Mask *mask)
Definition: gpencil.c:1540
bGPDlayer * BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setactive)
Definition: gpencil.c:659
bool BKE_gpencil_layer_is_editable(const bGPDlayer *gpl)
Definition: gpencil.c:1259
void(* BKE_gpencil_batch_cache_dirty_tag_cb)(bGPdata *gpd)
Definition: gpencil.c:340
void BKE_gpencil_stroke_add_points(bGPDstroke *gps, const float *array, const int totpoints, const float mat[4][4])
Definition: gpencil.c:800
void BKE_gpencil_free_stroke_editcurve(bGPDstroke *gps)
Definition: gpencil.c:386
Material * BKE_gpencil_object_material_ensure_active(Object *ob)
Definition: gpencil.c:1982
void BKE_gpencil_layer_autolock_set(bGPdata *gpd, const bool unlock)
Definition: gpencil.c:1725
#define MAT_NR_REMAP(n)
void BKE_gpencil_free_layers(ListBase *list)
Definition: gpencil.c:469
void BKE_gpencil_layer_frames_sort(struct bGPDlayer *gpl, bool *r_has_duplicate_frames)
Definition: gpencil.c:1640
void BKE_gpencil_stroke_weights_duplicate(bGPDstroke *gps_src, bGPDstroke *gps_dst)
Definition: gpencil.c:928
static void greasepencil_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition: gpencil.c:148
static void greasepencil_free_data(ID *id)
Definition: gpencil.c:128
bool BKE_gpencil_free_strokes(bGPDframe *gpf)
Definition: gpencil.c:425
Material * BKE_gpencil_object_material_ensure_from_brush(Main *bmain, Object *ob, Brush *brush)
Definition: gpencil.c:1826
Material * BKE_gpencil_object_material_ensure_from_active_input_material(Object *ob)
Definition: gpencil.c:1967
void BKE_gpencil_material_index_reassign(bGPdata *gpd, int totcol, int index)
Definition: gpencil.c:2146
bGPDstroke * BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness)
Definition: gpencil.c:826
void BKE_gpencil_palette_ensure(Main *bmain, Scene *scene)
Definition: gpencil.c:2484
Material * BKE_gpencil_object_material_from_brush_get(Object *ob, Brush *brush)
Definition: gpencil.c:1893
int BKE_gpencil_object_material_ensure(Main *bmain, Object *ob, Material *material)
Definition: gpencil.c:1851
void BKE_gpencil_free_layer_masks(bGPDlayer *gpl)
Definition: gpencil.c:459
void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, struct bGPDframe *gpf_dst)
Definition: gpencil.c:1032
void BKE_gpencil_stroke_sync_selection(bGPdata *gpd, bGPDstroke *gps)
Definition: gpencil.c:1139
void BKE_gpencil_dvert_ensure(bGPDstroke *gps)
Definition: gpencil.c:2067
void BKE_gpencil_free(bGPdata *gpd, bool free_all)
Definition: gpencil.c:493
static int gpencil_cb_cmp_frame(void *thunk, const void *a, const void *b)
Definition: gpencil.c:1614
void BKE_gpencil_update_layer_transforms(const Depsgraph *depsgraph, Object *ob)
Definition: gpencil.c:2962
int BKE_gpencil_object_material_index_get_by_name(Object *ob, const char *name)
Definition: gpencil.c:2451
bool BKE_gpencil_from_image(SpaceImage *sima, bGPdata *gpd, bGPDframe *gpf, const float size, const bool mask)
Definition: gpencil.c:2542
void(* BKE_gpencil_batch_cache_free_cb)(bGPdata *gpd)
Definition: gpencil.c:341
bGPDlayer * BKE_gpencil_layer_named_get(bGPdata *gpd, const char *name)
Definition: gpencil.c:1496
bGPDframe * BKE_gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
Definition: gpencil.c:539
void BKE_gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
Definition: gpencil.c:1223
bGPDlayer_Mask * BKE_gpencil_layer_mask_add(bGPDlayer *gpl, const char *name)
Definition: gpencil.c:1524
bGPDframe * BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src, const bool dup_strokes)
Definition: gpencil.c:999
void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig, const struct bGPDframe *gpf_eval)
Definition: gpencil.c:2839
static void greasepencil_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int UNUSED(flag))
Definition: gpencil.c:77
void BKE_gpencil_update_orig_pointers(const Object *ob_orig, const Object *ob_eval)
Definition: gpencil.c:2872
bGPDframe * BKE_gpencil_layer_frame_find(bGPDlayer *gpl, int cframe)
Definition: gpencil.c:1281
void BKE_gpencil_stroke_select_index_reset(bGPDstroke *gps)
Definition: gpencil.c:1210
static void greasepencil_foreach_id(ID *id, LibraryForeachIDData *data)
Definition: gpencil.c:135
void BKE_gpencil_layer_mask_remove_ref(bGPdata *gpd, const char *name)
Definition: gpencil.c:1552
bGPDframe * BKE_gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
Definition: gpencil.c:598
void BKE_gpencil_batch_cache_dirty_tag(bGPdata *gpd)
Definition: gpencil.c:343
void BKE_gpencil_blend_read_data(BlendDataReader *reader, bGPdata *gpd)
Definition: gpencil.c:196
Material * BKE_gpencil_object_material_new(Main *bmain, Object *ob, const char *name, int *r_index)
Definition: gpencil.c:1873
bool BKE_gpencil_layer_frame_delete(bGPDlayer *gpl, bGPDframe *gpf)
Definition: gpencil.c:1467
bGPDlayer * BKE_gpencil_layer_get_by_name(bGPdata *gpd, char *name, int first_if_not_found)
Definition: gpencil.c:1668
float BKE_gpencil_multiframe_falloff_calc(bGPDframe *gpf, int actnum, int f_init, int f_end, CurveMapping *cur_falloff)
Definition: gpencil.c:2109
bool BKE_gpencil_merge_materials(Object *ob, const float hue_threshold, const float sat_threshold, const float val_threshold, int *r_removed)
Definition: gpencil.c:2350
void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, float diff_mat[4][4])
Definition: gpencil.c:2909
int BKE_gpencil_material_find_index_by_name_prefix(Object *ob, const char *name_prefix)
Definition: gpencil.c:3031
bGPdata * BKE_gpencil_data_addnew(Main *bmain, const char name[])
Definition: gpencil.c:742
bGPDlayer_Mask * BKE_gpencil_layer_mask_named_get(bGPDlayer *gpl, const char *name)
Definition: gpencil.c:1510
void BKE_gpencil_stroke_select_index_set(bGPdata *gpd, bGPDstroke *gps)
Definition: gpencil.c:1203
void BKE_gpencil_layer_mask_sort_all(bGPdata *gpd)
Definition: gpencil.c:1607
bGPDstroke * BKE_gpencil_stroke_add(bGPDframe *gpf, int mat_idx, int totpoints, short thickness, const bool insert_at_head)
Definition: gpencil.c:871
void BKE_gpencil_eval_delete(bGPdata *gpd_eval)
Definition: gpencil.c:512
IDTypeInfo IDType_ID_GD
Definition: gpencil.c:309
static CLG_LogRef LOG
Definition: gpencil.c:75
Material * BKE_gpencil_brush_material_get(Brush *brush)
Definition: gpencil.c:1787
static void greasepencil_blend_read_expand(BlendExpander *expander, ID *id)
Definition: gpencil.c:297
int BKE_gpencil_object_material_index_get(Object *ob, Material *ma)
Definition: gpencil.c:2437
void BKE_gpencil_frame_selected_hash(bGPdata *gpd, struct GHash *r_list)
Definition: gpencil.c:3046
void BKE_gpencil_vgroup_remove(Object *ob, bDeformGroup *defgroup)
Definition: gpencil.c:2025
bGPDcurve * BKE_gpencil_stroke_curve_duplicate(bGPDcurve *gpc_src)
Definition: gpencil.c:939
void BKE_gpencil_free_stroke(bGPDstroke *gps)
Definition: gpencil.c:401
bGPDstroke * BKE_gpencil_stroke_add_existing_style(bGPDframe *gpf, bGPDstroke *existing, int mat_idx, int totpoints, short thickness)
Definition: gpencil.c:899
bGPdata * BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy)
Definition: gpencil.c:1103
void BKE_gpencil_curve_sync_selection(bGPdata *gpd, bGPDstroke *gps)
Definition: gpencil.c:1167
void BKE_gpencil_brush_material_set(Brush *brush, Material *ma)
Definition: gpencil.c:1804
static void greasepencil_blend_read_data(BlendDataReader *reader, ID *id)
Definition: gpencil.c:274
void BKE_gpencil_layer_active_set(bGPdata *gpd, bGPDlayer *active)
Definition: gpencil.c:1698
bool BKE_gpencil_material_index_used(bGPdata *gpd, int index)
Definition: gpencil.c:2167
Material * BKE_gpencil_object_material_ensure_from_active_input_brush(Main *bmain, Object *ob, Brush *brush)
Definition: gpencil.c:1944
void BKE_gpencil_layer_mask_sort(bGPdata *gpd, bGPDlayer *gpl)
Definition: gpencil.c:1588
bGPDstroke * BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src, const bool dup_points, const bool dup_curve)
Definition: gpencil.c:957
bGPDframe * BKE_gpencil_layer_frame_get(bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
Definition: gpencil.c:1307
bGPDlayer * BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src, const bool dup_frames, const bool dup_strokes)
Definition: gpencil.c:1054
void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl)
Definition: gpencil.c:1760
uint col
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static ulong state[N]
static unsigned a[3]
Definition: RandGen.cpp:92
bool active
all scheduled work for the GPU.
struct Material * material
struct BrushGpencilSettings * gpencil_settings
short id_code
Definition: BKE_idtype.h:120
Definition: DNA_ID.h:273
void * py_instance
Definition: DNA_ID.h:340
struct Library * lib
Definition: DNA_ID.h:277
int us
Definition: DNA_ID.h:293
char name[66]
Definition: DNA_ID.h:283
unsigned int * rect
struct Library * parent
Definition: DNA_ID.h:365
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
struct MDeformWeight * dw
unsigned int def_nr
Definition: BKE_main.h:116
ListBase palettes
Definition: BKE_main.h:173
struct MaterialGPencilStyle * gp_style
ListBase defbase
struct bPose * pose
float imat[4][4]
float obmat[4][4]
void * data
struct Palette * palette
struct Brush * brush
struct ToolSettings * toolsettings
struct ImageUser iuser
struct Image * image
GpPaint * gp_paint
GpVertexPaint * gp_vertexpaint
char name[64]
bGPDcurve_point * curve_points
struct bGPDframe * gpf_orig
struct bGPDframe * next
bGPDframe_Runtime runtime
ListBase strokes
struct bGPDframe * prev
struct bGPDlayer_Mask * prev
struct bGPDlayer_Mask * next
struct bGPDlayer * gpl_orig
float inverse[4][4]
float gcolor_next[3]
struct Object * parent
float color[4]
char info[128]
struct bGPDlayer * next
bGPDframe * actframe
float layer_mat[4][4]
char parsubstr[64]
bGPDlayer_Runtime runtime
float layer_invmat[4][4]
ListBase frames
float vertex_paint_opacity
ListBase mask_layers
float gcolor_prev[3]
float rotation[3]
float scale[3]
float location[3]
struct bGPDlayer * prev
struct bGPDspoint * pt_orig
bGPDspoint_Runtime runtime
float vert_color[4]
struct bGPDstroke * gps_orig
struct bGPDstroke * prev
bGPDspoint * points
float fill_opacity_fac
float aspect_ratio[2]
bGPDtriangle * triangles
bGPDstroke_Runtime runtime
struct bGPDcurve * editcurve
struct MDeformVert * dvert
struct bGPDstroke * next
float zdepth_offset
float curve_edit_corner_angle
int curve_edit_resolution
int select_last_index
float gcolor_prev[3]
float line_color[4]
ListBase layers
short gstep_next
float gcolor_next[3]
float curve_edit_threshold
bGPgrid grid
struct Material ** mat
short onion_keytype
float onion_factor
bGPdata_Runtime runtime
struct AnimData * adt
float scale[2]
float color[3]
float pose_mat[4][4]
__forceinline const avxi abs(const avxi &a)
Definition: util_avxi.h:186
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)