Blender  V3.3
gpencil_data.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2008 Blender Foundation. */
3 
10 #include <math.h>
11 #include <stddef.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include "MEM_guardedalloc.h"
17 
18 #include "BLI_blenlib.h"
19 #include "BLI_ghash.h"
20 #include "BLI_math.h"
21 #include "BLI_string_utils.h"
22 #include "BLI_utildefines.h"
23 
24 #include "BLT_translation.h"
25 
26 #include "DNA_anim_types.h"
27 #include "DNA_brush_types.h"
28 #include "DNA_gpencil_types.h"
29 #include "DNA_material_types.h"
30 #include "DNA_meshdata_types.h"
31 #include "DNA_modifier_types.h"
32 #include "DNA_object_types.h"
33 #include "DNA_scene_types.h"
34 #include "DNA_screen_types.h"
35 #include "DNA_space_types.h"
36 #include "DNA_view3d_types.h"
37 
38 #include "BKE_anim_data.h"
39 #include "BKE_animsys.h"
40 #include "BKE_brush.h"
41 #include "BKE_context.h"
42 #include "BKE_deform.h"
43 #include "BKE_fcurve_driver.h"
44 #include "BKE_gpencil.h"
45 #include "BKE_gpencil_modifier.h"
46 #include "BKE_lib_id.h"
47 #include "BKE_main.h"
48 #include "BKE_material.h"
49 #include "BKE_modifier.h"
50 #include "BKE_object.h"
51 #include "BKE_paint.h"
52 #include "BKE_report.h"
53 #include "BKE_scene.h"
54 
55 #include "UI_interface.h"
56 #include "UI_resources.h"
57 
58 #include "WM_api.h"
59 #include "WM_types.h"
60 
61 #include "RNA_access.h"
62 #include "RNA_define.h"
63 #include "RNA_enum_types.h"
64 
65 #include "ED_gpencil.h"
66 #include "ED_object.h"
67 
68 #include "DEG_depsgraph.h"
69 #include "DEG_depsgraph_build.h"
70 #include "DEG_depsgraph_query.h"
71 
72 #include "gpencil_intern.h"
73 
74 /* ************************************************ */
75 /* Datablock Operators */
76 
77 /* ******************* Add New Data ************************ */
79 {
80 
81  /* the base line we have is that we have somewhere to add Grease Pencil data */
83 }
84 
85 /* add new datablock - wrapper around API */
87 {
88  PointerRNA gpd_owner = {NULL};
89  bGPdata **gpd_ptr = ED_annotation_data_get_pointers(C, &gpd_owner);
90 
91  if (gpd_ptr == NULL) {
92  BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
93  return OPERATOR_CANCELLED;
94  }
95 
96  /* decrement user count and add new datablock */
97  /* TODO: if a datablock exists,
98  * we should make a copy of it instead of starting fresh (as in other areas) */
99  Main *bmain = CTX_data_main(C);
100 
101  /* decrement user count of old GP datablock */
102  if (*gpd_ptr) {
103  bGPdata *gpd = (*gpd_ptr);
104  id_us_min(&gpd->id);
105  }
106 
107  /* Add new datablock, with a single layer ready to use
108  * (so users don't have to perform an extra step). */
109  bGPdata *gpd = BKE_gpencil_data_addnew(bmain, DATA_("Annotations"));
110  *gpd_ptr = gpd;
111 
112  /* tag for annotations */
113  gpd->flag |= GP_DATA_ANNOTATIONS;
114 
115  /* add new layer (i.e. a "note") */
116  BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true, false);
117 
118  /* notifiers */
120 
121  return OPERATOR_FINISHED;
122 }
123 
125 {
126  /* identifiers */
127  ot->name = "Annotation Add New";
128  ot->idname = "GPENCIL_OT_annotation_add";
129  ot->description = "Add new Annotation data-block";
131 
132  /* callbacks */
135 }
136 
137 /* ******************* Unlink Data ************************ */
138 
139 /* poll callback for adding data/layers - special */
141 {
143 
144  /* only unlink annotation datablocks */
145  if ((gpd_ptr != NULL) && (*gpd_ptr != NULL)) {
146  bGPdata *gpd = (*gpd_ptr);
147  if ((gpd->flag & GP_DATA_ANNOTATIONS) == 0) {
148  return false;
149  }
150  }
151  /* if we have access to some active data, make sure there's a datablock before enabling this */
152  return (gpd_ptr && *gpd_ptr);
153 }
154 
155 /* unlink datablock - wrapper around API */
157 {
159 
160  if (gpd_ptr == NULL) {
161  BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
162  return OPERATOR_CANCELLED;
163  }
164  /* just unlink datablock now, decreasing its user count */
165  bGPdata *gpd = (*gpd_ptr);
166 
167  id_us_min(&gpd->id);
168  *gpd_ptr = NULL;
169 
170  /* notifiers */
172 
173  return OPERATOR_FINISHED;
174 }
175 
177 {
178  /* identifiers */
179  ot->name = "Annotation Unlink";
180  ot->idname = "GPENCIL_OT_data_unlink";
181  ot->description = "Unlink active Annotation data-block";
183 
184  /* callbacks */
187 }
188 
189 /* ************************************************ */
190 /* Layer Operators */
191 
192 /* ******************* Add New Layer ************************ */
193 
194 /* add new layer - wrapper around API */
196 {
197  const bool is_annotation = STREQ(op->idname, "GPENCIL_OT_layer_annotation_add");
198 
199  PointerRNA gpd_owner = {NULL};
200  Main *bmain = CTX_data_main(C);
202  bGPdata *gpd = NULL;
203 
204  if (is_annotation) {
205  bGPdata **gpd_ptr = ED_annotation_data_get_pointers(C, &gpd_owner);
206  /* if there's no existing Grease-Pencil data there, add some */
207  if (gpd_ptr == NULL) {
208  BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
209  return OPERATOR_CANCELLED;
210  }
211  /* Annotations */
212  if (*gpd_ptr == NULL) {
213  *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("Annotations"));
214  }
215 
216  /* mark as annotation */
217  (*gpd_ptr)->flag |= GP_DATA_ANNOTATIONS;
218  BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true, false);
219  gpd = *gpd_ptr;
220  }
221  else {
222  /* GP Object */
224  if ((ob != NULL) && (ob->type == OB_GPENCIL)) {
225  gpd = (bGPdata *)ob->data;
226  bGPDlayer *gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true, false);
227  /* Add a new frame to make it visible in Dopesheet. */
228  if (gpl != NULL) {
230  }
231  }
232  }
233 
234  /* notifiers */
235  if (gpd) {
236  DEG_id_tag_update(&gpd->id,
238  }
241 
242  return OPERATOR_FINISHED;
243 }
244 
246 {
247  /* identifiers */
248  ot->name = "Add New Layer";
249  ot->idname = "GPENCIL_OT_layer_add";
250  ot->description = "Add new layer or note for the active data-block";
251 
253 
254  /* callbacks */
257 }
258 
260 {
262 }
263 
265 {
266  /* identifiers */
267  ot->name = "Add New Annotation Layer";
268  ot->idname = "GPENCIL_OT_layer_annotation_add";
269  ot->description = "Add new Annotation layer or note for the active data-block";
270 
272 
273  /* callbacks */
276 }
277 /* ******************* Remove Active Layer ************************* */
278 
280 {
281  const bool is_annotation = STREQ(op->idname, "GPENCIL_OT_layer_annotation_remove");
282 
283  bGPdata *gpd = (!is_annotation) ? ED_gpencil_data_get_active(C) :
286 
287  /* sanity checks */
288  if (ELEM(NULL, gpd, gpl)) {
289  return OPERATOR_CANCELLED;
290  }
291 
292  if (gpl->flag & GP_LAYER_LOCKED) {
293  BKE_report(op->reports, RPT_ERROR, "Cannot delete locked layers");
294  return OPERATOR_CANCELLED;
295  }
296 
297  /* make the layer before this the new active layer
298  * - use the one after if this is the first
299  * - if this is the only layer, this naturally becomes NULL
300  */
301  if (gpl->prev) {
303  }
304  else {
306  }
307 
308  /* delete the layer now... */
309  BKE_gpencil_layer_delete(gpd, gpl);
310 
311  /* Reorder masking. */
313 
314  /* notifiers */
318 
319  /* Free Grease Pencil data block when last annotation layer is removed, see: #112683. */
320  if (is_annotation && gpd->layers.first == NULL) {
321  BKE_gpencil_free_data(gpd, true);
322 
324  *gpd_ptr = NULL;
325 
326  Main *bmain = CTX_data_main(C);
327  BKE_id_free_us(bmain, gpd);
328  }
329 
330  return OPERATOR_FINISHED;
331 }
332 
334 {
335  /* identifiers */
336  ot->name = "Remove Layer";
337  ot->idname = "GPENCIL_OT_layer_remove";
338  ot->description = "Remove active Grease Pencil layer";
339 
341 
342  /* callbacks */
345 }
346 
348 {
351 
352  return (gpl != NULL);
353 }
354 
356 {
357  /* identifiers */
358  ot->name = "Remove Annotation Layer";
359  ot->idname = "GPENCIL_OT_layer_annotation_remove";
360  ot->description = "Remove active Annotation layer";
361 
363 
364  /* callbacks */
367 }
368 /* ******************* Move Layer Up/Down ************************** */
369 
370 enum {
373 };
374 
376 {
377  const bool is_annotation = STREQ(op->idname, "GPENCIL_OT_layer_annotation_move");
378 
379  bGPdata *gpd = (!is_annotation) ? ED_gpencil_data_get_active(C) :
382 
383  const int direction = RNA_enum_get(op->ptr, "type") * -1;
384 
385  /* sanity checks */
386  if (ELEM(NULL, gpd, gpl)) {
387  return OPERATOR_CANCELLED;
388  }
389 
390  BLI_assert(ELEM(direction, -1, 0, 1)); /* we use value below */
391  if (BLI_listbase_link_move(&gpd->layers, gpl, direction)) {
392  /* Reorder masking. */
394 
397  }
398 
399  return OPERATOR_FINISHED;
400 }
401 
403 {
404  static const EnumPropertyItem slot_move[] = {
405  {GP_LAYER_MOVE_UP, "UP", 0, "Up", ""},
406  {GP_LAYER_MOVE_DOWN, "DOWN", 0, "Down", ""},
407  {0, NULL, 0, NULL, NULL},
408  };
409 
410  /* identifiers */
411  ot->name = "Move Grease Pencil Layer";
412  ot->idname = "GPENCIL_OT_layer_move";
413  ot->description = "Move the active Grease Pencil layer up/down in the list";
414 
415  /* api callbacks */
418 
419  /* flags */
421 
422  ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
423 }
424 
426 {
427  static const EnumPropertyItem slot_move[] = {
428  {GP_LAYER_MOVE_UP, "UP", 0, "Up", ""},
429  {GP_LAYER_MOVE_DOWN, "DOWN", 0, "Down", ""},
430  {0, NULL, 0, NULL, NULL},
431  };
432 
433  /* identifiers */
434  ot->name = "Move Annotation Layer";
435  ot->idname = "GPENCIL_OT_layer_annotation_move";
436  ot->description = "Move the active Annotation layer up/down in the list";
437 
438  /* api callbacks */
441 
442  /* flags */
444 
445  ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
446 }
447 /* ********************* Duplicate Layer ************************** */
448 enum {
451 };
452 
454 {
457  bGPDlayer *new_layer;
458  const int mode = RNA_enum_get(op->ptr, "mode");
459  const bool dup_strokes = (bool)(mode == GP_LAYER_DUPLICATE_ALL);
460  /* sanity checks */
461  if (ELEM(NULL, gpd, gpl)) {
462  return OPERATOR_CANCELLED;
463  }
464 
465  /* Make copy of layer, and add it immediately after or before the existing layer. */
466  new_layer = BKE_gpencil_layer_duplicate(gpl, true, dup_strokes);
467  if (dup_strokes) {
468  BLI_insertlinkafter(&gpd->layers, gpl, new_layer);
469  }
470  else {
471  /* For empty strokes is better add below. */
472  BLI_insertlinkbefore(&gpd->layers, gpl, new_layer);
473  }
474 
475  /* ensure new layer has a unique name, and is now the active layer */
476  BLI_uniquename(&gpd->layers,
477  new_layer,
478  DATA_("GP_Layer"),
479  '.',
480  offsetof(bGPDlayer, info),
481  sizeof(new_layer->info));
482  BKE_gpencil_layer_active_set(gpd, new_layer);
483 
484  /* notifiers */
488 
489  return OPERATOR_FINISHED;
490 }
491 
493 {
494  static const EnumPropertyItem copy_mode[] = {
495  {GP_LAYER_DUPLICATE_ALL, "ALL", 0, "All Data", ""},
496  {GP_LAYER_DUPLICATE_EMPTY, "EMPTY", 0, "Empty Keyframes", ""},
497  {0, NULL, 0, NULL, NULL},
498  };
499 
500  /* identifiers */
501  ot->name = "Duplicate Layer";
502  ot->idname = "GPENCIL_OT_layer_duplicate";
503  ot->description = "Make a copy of the active Grease Pencil layer";
504 
505  /* callbacks */
508 
509  /* flags */
511 
512  RNA_def_enum(ot->srna, "mode", copy_mode, GP_LAYER_DUPLICATE_ALL, "Mode", "");
513 }
514 
515 /* ********************* Duplicate Layer in a new object ************************** */
516 enum {
519 };
520 
522 {
524  if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
525  return false;
526  }
527 
528  bGPdata *gpd = (bGPdata *)ob->data;
530 
531  if (gpl == NULL) {
532  return false;
533  }
534 
535  return true;
536 }
537 
539 {
540  Main *bmain = CTX_data_main(C);
541  const bool only_active = RNA_boolean_get(op->ptr, "only_active");
542  const int mode = RNA_enum_get(op->ptr, "mode");
543 
544  Object *ob_src = CTX_data_active_object(C);
545  bGPdata *gpd_src = (bGPdata *)ob_src->data;
546  bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd_src);
547 
548  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
549  if ((ob == ob_src) || (ob->type != OB_GPENCIL)) {
550  continue;
551  }
552  bGPdata *gpd_dst = (bGPdata *)ob->data;
553  LISTBASE_FOREACH_BACKWARD (bGPDlayer *, gpl_src, &gpd_src->layers) {
554  if ((only_active) && (gpl_src != gpl_active)) {
555  continue;
556  }
557  /* Create new layer (adding at head of the list). */
558  bGPDlayer *gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, gpl_src->info, true, true);
559  /* Need to copy some variables (not all). */
560  gpl_dst->onion_flag = gpl_src->onion_flag;
561  gpl_dst->thickness = gpl_src->thickness;
562  gpl_dst->line_change = gpl_src->line_change;
563  copy_v4_v4(gpl_dst->tintcolor, gpl_src->tintcolor);
564  gpl_dst->opacity = gpl_src->opacity;
565 
566  /* Create all frames. */
567  LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) {
568 
569  if ((mode == GP_LAYER_COPY_OBJECT_ACT_FRAME) && (gpf_src != gpl_src->actframe)) {
570  continue;
571  }
572 
573  /* Create new frame. */
574  bGPDframe *gpf_dst = BKE_gpencil_frame_addnew(gpl_dst, gpf_src->framenum);
575 
576  /* Copy strokes. */
577  LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
578 
579  /* Make copy of source stroke. */
580  bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true);
581 
582  /* Check if material is in destination object,
583  * otherwise add the slot with the material. */
584  Material *ma_src = BKE_object_material_get(ob_src, gps_src->mat_nr + 1);
585  if (ma_src != NULL) {
586  int idx = BKE_gpencil_object_material_ensure(bmain, ob, ma_src);
587 
588  /* Reassign the stroke material to the right slot in destination object. */
589  gps_dst->mat_nr = idx;
590  }
591 
592  /* Add new stroke to frame. */
593  BLI_addtail(&gpf_dst->strokes, gps_dst);
594  }
595  }
596  }
597  /* notifiers */
598  DEG_id_tag_update(&gpd_dst->id,
601  }
602  CTX_DATA_END;
603 
605 
606  return OPERATOR_FINISHED;
607 }
608 
610 {
611  PropertyRNA *prop;
612 
613  static const EnumPropertyItem copy_mode[] = {
614  {GP_LAYER_COPY_OBJECT_ALL_FRAME, "ALL", 0, "All Frames", ""},
615  {GP_LAYER_COPY_OBJECT_ACT_FRAME, "ACTIVE", 0, "Active Frame", ""},
616  {0, NULL, 0, NULL, NULL},
617  };
618 
619  /* identifiers */
620  ot->name = "Duplicate Layer to New Object";
621  ot->idname = "GPENCIL_OT_layer_duplicate_object";
622  ot->description = "Make a copy of the active Grease Pencil layer to selected object";
623 
624  /* callbacks */
627 
628  /* flags */
630 
631  ot->prop = RNA_def_enum(ot->srna, "mode", copy_mode, GP_LAYER_COPY_OBJECT_ALL_FRAME, "Mode", "");
632 
633  prop = RNA_def_boolean(ot->srna,
634  "only_active",
635  true,
636  "Only Active",
637  "Copy only active Layer, uncheck to append all layers");
639 }
640 
641 /* ********************* Duplicate Frame ************************** */
642 enum {
645 };
646 
648 {
650  bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd);
652 
653  int mode = RNA_enum_get(op->ptr, "mode");
654 
655  /* sanity checks */
656  if (ELEM(NULL, gpd, gpl_active)) {
657  return OPERATOR_CANCELLED;
658  }
659 
660  if (mode == 0) {
661  BKE_gpencil_frame_addcopy(gpl_active, scene->r.cfra);
662  }
663  else {
664  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
665  if ((gpl->flag & GP_LAYER_LOCKED) == 0) {
667  }
668  }
669  }
670  /* notifiers */
673 
674  return OPERATOR_FINISHED;
675 }
676 
678 {
679  static const EnumPropertyItem duplicate_mode[] = {
680  {GP_FRAME_DUP_ACTIVE, "ACTIVE", 0, "Active", "Duplicate frame in active layer only"},
681  {GP_FRAME_DUP_ALL, "ALL", 0, "All", "Duplicate active frames in all layers"},
682  {0, NULL, 0, NULL, NULL},
683  };
684 
685  /* identifiers */
686  ot->name = "Duplicate Frame";
687  ot->idname = "GPENCIL_OT_frame_duplicate";
688  ot->description = "Make a copy of the active Grease Pencil Frame";
689 
690  /* callbacks */
693 
694  /* flags */
696 
697  ot->prop = RNA_def_enum(ot->srna, "mode", duplicate_mode, GP_FRAME_DUP_ACTIVE, "Mode", "");
698 }
699 
700 /* ********************* Clean Fill Boundaries on Frame ************************** */
701 enum {
704 };
705 
707 {
708  bool changed = false;
710  int mode = RNA_enum_get(op->ptr, "mode");
711 
712  CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
713  bGPDframe *init_gpf = gpl->actframe;
714  if (mode == GP_FRAME_CLEAN_FILL_ALL) {
715  init_gpf = gpl->frames.first;
716  }
717 
718  for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
719  if ((gpf == gpl->actframe) || (mode == GP_FRAME_CLEAN_FILL_ALL)) {
720 
721  if (gpf == NULL) {
722  continue;
723  }
724 
725  /* simply delete strokes which are no fill */
726  LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
727  /* skip strokes that are invalid for current view */
728  if (ED_gpencil_stroke_can_use(C, gps) == false) {
729  continue;
730  }
731 
732  /* free stroke */
733  if (gps->flag & GP_STROKE_NOFILL) {
734  /* free stroke memory arrays, then stroke itself */
735  if (gps->points) {
736  MEM_freeN(gps->points);
737  }
738  if (gps->dvert) {
740  MEM_freeN(gps->dvert);
741  }
742  MEM_SAFE_FREE(gps->triangles);
743  BLI_freelinkN(&gpf->strokes, gps);
744 
745  changed = true;
746  }
747  }
748  }
749  }
750  }
751  CTX_DATA_END;
752 
753  /* notifiers */
754  if (changed) {
757  }
758 
759  return OPERATOR_FINISHED;
760 }
761 
763 {
764  static const EnumPropertyItem duplicate_mode[] = {
765  {GP_FRAME_CLEAN_FILL_ACTIVE, "ACTIVE", 0, "Active Frame Only", "Clean active frame only"},
766  {GP_FRAME_CLEAN_FILL_ALL, "ALL", 0, "All Frames", "Clean all frames in all layers"},
767  {0, NULL, 0, NULL, NULL},
768  };
769 
770  /* identifiers */
771  ot->name = "Clean Fill Boundaries";
772  ot->idname = "GPENCIL_OT_frame_clean_fill";
773  ot->description = "Remove 'no fill' boundary strokes";
774 
775  /* callbacks */
778 
779  /* flags */
781 
782  ot->prop = RNA_def_enum(ot->srna, "mode", duplicate_mode, GP_FRAME_DUP_ACTIVE, "Mode", "");
783 }
784 
785 /* ********************* Clean Loose Boundaries on Frame ************************** */
787 {
788  bool changed = false;
790  int limit = RNA_int_get(op->ptr, "limit");
791  const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
792 
793  CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
794  bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
795 
796  for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
797  if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
798  if (gpf == NULL) {
799  continue;
800  }
801 
802  /* simply delete strokes which are no loose */
803  LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
804  /* skip strokes that are invalid for current view */
805  if (ED_gpencil_stroke_can_use(C, gps) == false) {
806  continue;
807  }
808 
809  /* free stroke */
810  if (gps->totpoints <= limit) {
811  /* free stroke memory arrays, then stroke itself */
812  if (gps->points) {
813  MEM_freeN(gps->points);
814  }
815  if (gps->dvert) {
817  MEM_freeN(gps->dvert);
818  }
819  MEM_SAFE_FREE(gps->triangles);
820  BLI_freelinkN(&gpf->strokes, gps);
821 
822  changed = true;
823  }
824  }
825  }
826 
827  /* If not multi-edit, exit loop. */
828  if (!is_multiedit) {
829  break;
830  }
831  }
832  }
833  CTX_DATA_END;
834 
835  /* notifiers */
836  if (changed) {
839  }
840 
841  return OPERATOR_FINISHED;
842 }
843 
845 {
846  /* identifiers */
847  ot->name = "Clean Loose Points";
848  ot->idname = "GPENCIL_OT_frame_clean_loose";
849  ot->description = "Remove loose points";
850 
851  /* callbacks */
854 
855  /* flags */
857 
859  "limit",
860  1,
861  1,
862  INT_MAX,
863  "Limit",
864  "Number of points to consider stroke as loose",
865  1,
866  INT_MAX);
867 }
868 
869 /* ********************* Clean Duplicated Frames ************************** */
870 static bool gpencil_frame_is_equal(const bGPDframe *gpf_a, const bGPDframe *gpf_b)
871 {
872  if ((gpf_a == NULL) || (gpf_b == NULL)) {
873  return false;
874  }
875  /* If the number of strokes is different, cannot be equal. */
876  const int totstrokes_a = BLI_listbase_count(&gpf_a->strokes);
877  const int totstrokes_b = BLI_listbase_count(&gpf_b->strokes);
878  if ((totstrokes_a == 0) || (totstrokes_b == 0) || (totstrokes_a != totstrokes_b)) {
879  return false;
880  }
881  /* Loop all strokes and check. */
882  const bGPDstroke *gps_a = gpf_a->strokes.first;
883  const bGPDstroke *gps_b = gpf_b->strokes.first;
884  for (int i = 0; i < totstrokes_a; i++) {
885  /* If the number of points is different, cannot be equal. */
886  if (gps_a->totpoints != gps_b->totpoints) {
887  return false;
888  }
889  /* Check other variables. */
890  if (!equals_v4v4(gps_a->vert_color_fill, gps_b->vert_color_fill)) {
891  return false;
892  }
893  if (gps_a->thickness != gps_b->thickness) {
894  return false;
895  }
896  if (gps_a->mat_nr != gps_b->mat_nr) {
897  return false;
898  }
899  if (gps_a->caps[0] != gps_b->caps[0]) {
900  return false;
901  }
902  if (gps_a->caps[1] != gps_b->caps[1]) {
903  return false;
904  }
905  if (gps_a->hardeness != gps_b->hardeness) {
906  return false;
907  }
908  if (!equals_v2v2(gps_a->aspect_ratio, gps_b->aspect_ratio)) {
909  return false;
910  }
911  if (gps_a->uv_rotation != gps_b->uv_rotation) {
912  return false;
913  }
914  if (!equals_v2v2(gps_a->uv_translation, gps_b->uv_translation)) {
915  return false;
916  }
917  if (gps_a->uv_scale != gps_b->uv_scale) {
918  return false;
919  }
920 
921  /* Loop points and check if equals or not. */
922  for (int p = 0; p < gps_a->totpoints; p++) {
923  const bGPDspoint *pt_a = &gps_a->points[p];
924  const bGPDspoint *pt_b = &gps_b->points[p];
925  if (!equals_v3v3(&pt_a->x, &pt_b->x)) {
926  return false;
927  }
928  if (pt_a->pressure != pt_b->pressure) {
929  return false;
930  }
931  if (pt_a->strength != pt_b->strength) {
932  return false;
933  }
934  if (pt_a->uv_fac != pt_b->uv_fac) {
935  return false;
936  }
937  if (pt_a->uv_rot != pt_b->uv_rot) {
938  return false;
939  }
940  if (!equals_v4v4(pt_a->vert_color, pt_b->vert_color)) {
941  return false;
942  }
943  }
944 
945  /* Look at next pair of strokes. */
946  gps_a = gps_a->next;
947  gps_b = gps_b->next;
948  }
949 
950  return true;
951 }
952 
954 {
955 #define SELECTED 1
956 
957  bool changed = false;
959  bGPdata *gpd = (bGPdata *)ob->data;
960  const int type = RNA_enum_get(op->ptr, "type");
961 
962  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
963  /* Only editable and visible layers are considered. */
964  if (BKE_gpencil_layer_is_editable(gpl) && (gpl->frames.first != NULL)) {
965  bGPDframe *gpf = gpl->frames.first;
966 
967  if ((type == SELECTED) && ((gpf->flag & GP_FRAME_SELECT) == 0)) {
968  continue;
969  }
970 
971  while (gpf != NULL) {
972  if (gpencil_frame_is_equal(gpf, gpf->next)) {
973  /* Remove frame. */
975  /* Tag for recalc. */
976  changed = true;
977  }
978  else {
979  gpf = gpf->next;
980  }
981  }
982  }
983  }
984 
985  /* notifiers */
986  if (changed) {
989  }
990 
991  return OPERATOR_FINISHED;
992 }
993 
995 {
996  static const EnumPropertyItem clean_type[] = {
997  {0, "ALL", 0, "All Frames", ""},
998  {1, "SELECTED", 0, "Selected Frames", ""},
999  {0, NULL, 0, NULL, NULL},
1000  };
1001 
1002  /* identifiers */
1003  ot->name = "Clean Duplicated Frames";
1004  ot->idname = "GPENCIL_OT_frame_clean_duplicate";
1005  ot->description = "Remove any duplicated frame";
1006 
1007  /* callbacks */
1010 
1011  /* flags */
1013 
1014  ot->prop = RNA_def_enum(ot->srna, "type", clean_type, 0, "Type", "");
1015 }
1016 
1017 /* *********************** Hide Layers ******************************** */
1018 
1020 {
1023  bool unselected = RNA_boolean_get(op->ptr, "unselected");
1024 
1025  /* sanity checks */
1026  if (ELEM(NULL, gpd, layer)) {
1027  return OPERATOR_CANCELLED;
1028  }
1029 
1030  if (unselected) {
1031  /* hide unselected */
1032  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1033  if (gpl != layer) {
1034  gpl->flag |= GP_LAYER_HIDE;
1035  }
1036  else {
1037  /* Be sure the active layer is unhidden. */
1038  gpl->flag &= ~GP_LAYER_HIDE;
1039  }
1040  }
1041  }
1042  else {
1043  /* hide selected/active */
1044  layer->flag |= GP_LAYER_HIDE;
1045  }
1046 
1047  /* notifiers */
1050 
1051  return OPERATOR_FINISHED;
1052 }
1053 
1055 {
1056  /* identifiers */
1057  ot->name = "Hide Layer(s)";
1058  ot->idname = "GPENCIL_OT_hide";
1059  ot->description = "Hide selected/unselected Grease Pencil layers";
1060 
1061  /* callbacks */
1063  ot->poll = gpencil_active_layer_poll; /* NOTE: we need an active layer to play with */
1064 
1065  /* flags */
1067 
1068  /* props */
1070  ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers");
1071 }
1072 
1073 /* ********************** Show All Layers ***************************** */
1074 
1075 /* poll callback for showing layers */
1077 {
1078  return ED_gpencil_data_get_active(C) != NULL;
1079 }
1080 
1082 {
1083  bGPDstroke *gps;
1084  for (gps = frame->strokes.first; gps; gps = gps->next) {
1085 
1086  /* only deselect strokes that are valid in this view */
1087  if (ED_gpencil_stroke_can_use(C, gps)) {
1088 
1089  /* (de)select points */
1090  int i;
1091  bGPDspoint *pt;
1092  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
1094  }
1095 
1096  /* (de)select stroke */
1098  }
1099  }
1100 }
1101 
1103 {
1105  const bool select = RNA_boolean_get(op->ptr, "select");
1106 
1107  /* sanity checks */
1108  if (gpd == NULL) {
1109  return OPERATOR_CANCELLED;
1110  }
1111 
1112  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1113  if (gpl->flag & GP_LAYER_HIDE) {
1114  gpl->flag &= ~GP_LAYER_HIDE;
1115 
1116  /* select or deselect if requested, only on hidden layers */
1117  if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
1118  if (select) {
1119  /* select all strokes on active frame only (same as select all operator) */
1120  if (gpl->actframe) {
1121  gpencil_reveal_select_frame(C, gpl->actframe, true);
1122  }
1123  }
1124  else {
1125  /* deselect strokes on all frames (same as deselect all operator) */
1126  bGPDframe *gpf;
1127  for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1128  gpencil_reveal_select_frame(C, gpf, false);
1129  }
1130  }
1131  }
1132  }
1133  }
1134 
1135  /* notifiers */
1138 
1139  return OPERATOR_FINISHED;
1140 }
1141 
1143 {
1144  /* identifiers */
1145  ot->name = "Show All Layers";
1146  ot->idname = "GPENCIL_OT_reveal";
1147  ot->description = "Show all Grease Pencil layers";
1148 
1149  /* callbacks */
1152 
1153  /* flags */
1155 
1156  /* props */
1157  RNA_def_boolean(ot->srna, "select", true, "Select", "");
1158 }
1159 
1160 /* ***************** Lock/Unlock All Layers ************************ */
1161 
1163 {
1165 
1166  /* sanity checks */
1167  if (gpd == NULL) {
1168  return OPERATOR_CANCELLED;
1169  }
1170 
1171  /* make all layers non-editable */
1172  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1173  gpl->flag |= GP_LAYER_LOCKED;
1174  }
1175 
1176  /* notifiers */
1179 
1180  return OPERATOR_FINISHED;
1181 }
1182 
1184 {
1185  /* identifiers */
1186  ot->name = "Lock All Layers";
1187  ot->idname = "GPENCIL_OT_lock_all";
1188  ot->description =
1189  "Lock all Grease Pencil layers to prevent them from being accidentally modified";
1190 
1191  /* callbacks */
1194 
1195  /* flags */
1197 }
1198 
1199 /* -------------------------- */
1200 
1202 {
1204 
1205  /* sanity checks */
1206  if (gpd == NULL) {
1207  return OPERATOR_CANCELLED;
1208  }
1209 
1210  /* make all layers editable again */
1211  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1212  gpl->flag &= ~GP_LAYER_LOCKED;
1213  }
1214 
1215  /* notifiers */
1218 
1219  return OPERATOR_FINISHED;
1220 }
1221 
1223 {
1224  /* identifiers */
1225  ot->name = "Unlock All Layers";
1226  ot->idname = "GPENCIL_OT_unlock_all";
1227  ot->description = "Unlock all Grease Pencil layers so that they can be edited";
1228 
1229  /* callbacks */
1232 
1233  /* flags */
1235 }
1236 
1237 /* ********************** Isolate Layer **************************** */
1238 
1240 {
1243  int flags = GP_LAYER_LOCKED;
1244  bool isolate = false;
1245 
1246  if (RNA_boolean_get(op->ptr, "affect_visibility")) {
1247  flags |= GP_LAYER_HIDE;
1248  }
1249 
1250  if (ELEM(NULL, gpd, layer)) {
1251  BKE_report(op->reports, RPT_ERROR, "No active layer to isolate");
1252  return OPERATOR_CANCELLED;
1253  }
1254 
1255  /* Test whether to isolate or clear all flags */
1256  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1257  /* Skip if this is the active layer */
1258  if (gpl == layer) {
1259  continue;
1260  }
1261 
1262  /* If the flags aren't set, that means that the layer is
1263  * not alone, so we have some layers to isolate still
1264  */
1265  if ((gpl->flag & flags) == 0) {
1266  isolate = true;
1267  break;
1268  }
1269  }
1270 
1271  /* Set/Clear flags as appropriate */
1272  /* TODO: Include onion-skinning on this list? */
1273  if (isolate) {
1274  /* Set flags on all "other" layers */
1275  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1276  if (gpl == layer) {
1277  continue;
1278  }
1279  gpl->flag |= flags;
1280  }
1281  }
1282  else {
1283  /* Clear flags - Restore everything else */
1284  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1285  gpl->flag &= ~flags;
1286  }
1287  }
1288 
1289  /* notifiers */
1292 
1293  return OPERATOR_FINISHED;
1294 }
1295 
1297 {
1298  /* identifiers */
1299  ot->name = "Isolate Layer";
1300  ot->idname = "GPENCIL_OT_layer_isolate";
1301  ot->description =
1302  "Toggle whether the active layer is the only one that can be edited and/or visible";
1303 
1304  /* callbacks */
1307 
1308  /* flags */
1310 
1311  /* properties */
1313  "affect_visibility",
1314  false,
1315  "Affect Visibility",
1316  "In addition to toggling the editability, also affect the visibility");
1317 }
1318 
1319 /* ********************** Merge Layer with the next layer **************************** */
1320 enum {
1323 };
1324 
1326 {
1327  /* Apply layer attributes. */
1328  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
1329  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
1330  gps->fill_opacity_fac *= gpl->opacity;
1331  gps->vert_color_fill[3] *= gpl->opacity;
1332  for (int p = 0; p < gps->totpoints; p++) {
1333  bGPDspoint *pt = &gps->points[p];
1334  float factor = (((float)gps->thickness * pt->pressure) + (float)gpl->line_change) /
1335  ((float)gps->thickness * pt->pressure);
1336  pt->pressure *= factor;
1337  pt->strength *= gpl->opacity;
1338 
1339  /* Layer transformation. */
1340  mul_v3_m4v3(&pt->x, gpl->layer_mat, &pt->x);
1341  zero_v3(gpl->location);
1342  zero_v3(gpl->rotation);
1343  copy_v3_fl(gpl->scale, 1.0f);
1344  }
1345  }
1346  }
1347 
1348  gpl->line_change = 0;
1349  gpl->opacity = 1.0f;
1350  unit_m4(gpl->layer_mat);
1351  invert_m4_m4(gpl->layer_invmat, gpl->layer_mat);
1352 }
1353 
1355 {
1357  bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd);
1358  bGPDlayer *gpl_dst = gpl_active->prev;
1359  const int mode = RNA_enum_get(op->ptr, "mode");
1360 
1361  if (mode == GP_LAYER_MERGE_ACTIVE) {
1362  if (ELEM(NULL, gpd, gpl_dst, gpl_active)) {
1363  BKE_report(op->reports, RPT_ERROR, "No layers to merge");
1364  return OPERATOR_CANCELLED;
1365  }
1366  }
1367  else {
1368  if (ELEM(NULL, gpd, gpl_active)) {
1369  BKE_report(op->reports, RPT_ERROR, "No layers to flatten");
1370  return OPERATOR_CANCELLED;
1371  }
1372  }
1373 
1374  if (mode == GP_LAYER_MERGE_ACTIVE) {
1375  /* Apply destination layer attributes. */
1376  apply_layer_settings(gpl_active);
1377  ED_gpencil_layer_merge(gpd, gpl_active, gpl_dst, false);
1378  }
1379  else if (mode == GP_LAYER_MERGE_ALL) {
1380  /* Apply layer attributes to all layers. */
1381  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1382  apply_layer_settings(gpl);
1383  }
1384  gpl_dst = gpl_active;
1385  /* Merge layers on top of active layer. */
1386  if (gpd->layers.last != gpl_dst) {
1388  if (gpl == gpl_dst) {
1389  break;
1390  }
1391  ED_gpencil_layer_merge(gpd, gpl, gpl->prev, false);
1392  }
1393  }
1394  /* Merge layers below active layer. */
1396  if (gpl == gpl_dst) {
1397  continue;
1398  }
1399  ED_gpencil_layer_merge(gpd, gpl, gpl_dst, true);
1400  }
1401  /* Set general layers settings to default values. */
1402  gpl_active->blend_mode = eGplBlendMode_Regular;
1403  gpl_active->flag &= ~GP_LAYER_LOCKED;
1404  gpl_active->flag &= ~GP_LAYER_HIDE;
1405  gpl_active->flag |= GP_LAYER_USE_LIGHTS;
1406  gpl_active->onion_flag |= GP_LAYER_ONIONSKIN;
1407  }
1408  else {
1409  return OPERATOR_CANCELLED;
1410  }
1411 
1412  /* Clear any invalid mask. Some other layer could be using the merged layer. */
1413  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1415  }
1416 
1417  /* notifiers */
1421 
1422  return OPERATOR_FINISHED;
1423 }
1424 
1426 {
1427  static const EnumPropertyItem merge_modes[] = {
1428  {GP_LAYER_MERGE_ACTIVE, "ACTIVE", 0, "Active", "Combine active layer into the layer below"},
1429  {GP_LAYER_MERGE_ALL, "ALL", 0, "All", "Combine all layers into the active layer"},
1430  {0, NULL, 0, NULL, NULL},
1431  };
1432 
1433  /* identifiers */
1434  ot->name = "Merge Down";
1435  ot->idname = "GPENCIL_OT_layer_merge";
1436  ot->description = "Combine Layers";
1437 
1438  /* callbacks */
1441 
1442  /* flags */
1444 
1445  ot->prop = RNA_def_enum(ot->srna, "mode", merge_modes, GP_LAYER_MERGE_ACTIVE, "Mode", "");
1446 }
1447 
1448 /* ********************** Change Layer ***************************** */
1449 
1451 {
1452  uiPopupMenu *pup;
1453  uiLayout *layout;
1454 
1455  /* call the menu, which will call this operator again, hence the canceled */
1456  pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
1457  layout = UI_popup_menu_layout(pup);
1458  uiItemsEnumO(layout, "GPENCIL_OT_layer_change", "layer");
1459  UI_popup_menu_end(C, pup);
1460 
1461  return OPERATOR_INTERFACE;
1462 }
1463 
1465 {
1467  if (gpd == NULL) {
1468  return OPERATOR_CANCELLED;
1469  }
1470 
1471  bGPDlayer *gpl = NULL;
1472  int layer_num = RNA_enum_get(op->ptr, "layer");
1473 
1474  /* Get layer or create new one */
1475  if (layer_num == -1) {
1476  /* Create layer */
1477  gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true, false);
1478  }
1479  else {
1480  /* Try to get layer */
1481  gpl = BLI_findlink(&gpd->layers, layer_num);
1482 
1483  if (gpl == NULL) {
1484  BKE_reportf(
1485  op->reports, RPT_ERROR, "Cannot change to non-existent layer (index = %d)", layer_num);
1486  return OPERATOR_CANCELLED;
1487  }
1488  }
1489 
1490  /* Set active layer */
1491  BKE_gpencil_layer_active_set(gpd, gpl);
1492 
1493  /* updates */
1497 
1498  return OPERATOR_FINISHED;
1499 }
1500 
1502 {
1503  /* identifiers */
1504  ot->name = "Change Layer";
1505  ot->idname = "GPENCIL_OT_layer_change";
1506  ot->description = "Change active Grease Pencil layer";
1507 
1508  /* callbacks */
1512 
1513  /* flags */
1515 
1516  /* gp layer to use (dynamic enum) */
1517  ot->prop = RNA_def_enum(ot->srna, "layer", DummyRNA_DEFAULT_items, 0, "Grease Pencil Layer", "");
1519 }
1520 
1522 {
1524  bGPdata *gpd = (bGPdata *)ob->data;
1525  int layer_num = RNA_int_get(op->ptr, "layer");
1526 
1527  /* Try to get layer */
1528  bGPDlayer *gpl = BLI_findlink(&gpd->layers, layer_num);
1529 
1530  if (gpl == NULL) {
1531  BKE_reportf(
1532  op->reports, RPT_ERROR, "Cannot change to non-existent layer (index = %d)", layer_num);
1533  return OPERATOR_CANCELLED;
1534  }
1535 
1536  /* Set active layer */
1537  BKE_gpencil_layer_active_set(gpd, gpl);
1538 
1539  /* updates */
1543 
1544  return OPERATOR_FINISHED;
1545 }
1546 
1548 {
1549  /* identifiers */
1550  ot->name = "Active Layer";
1551  ot->idname = "GPENCIL_OT_layer_active";
1552  ot->description = "Active Grease Pencil layer";
1553 
1554  /* callbacks */
1557 
1558  /* flags */
1560 
1561  /* GPencil layer to use. */
1562  ot->prop = RNA_def_int(ot->srna, "layer", 0, 0, INT_MAX, "Grease Pencil Layer", "", 0, INT_MAX);
1564 }
1565 /* ************************************************ */
1566 
1567 /* ******************* Arrange Stroke Up/Down in drawing order ************************** */
1568 
1569 enum {
1574 };
1575 
1577 {
1580  bGPDlayer *gpl_act = BKE_gpencil_layer_active_get(gpd);
1581 
1582  /* sanity checks */
1583  if (ELEM(NULL, gpd, gpl_act, gpl_act->actframe)) {
1584  return OPERATOR_CANCELLED;
1585  }
1586 
1587  const int direction = RNA_enum_get(op->ptr, "direction");
1588  const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
1589  bGPDstroke *gps_target = NULL;
1590 
1591  bool changed = false;
1592  CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
1593  /* temp listbase to store selected strokes */
1594  ListBase selected = {NULL};
1595 
1596  bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
1597  bGPDstroke *gps = NULL;
1598 
1599  for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
1600  if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
1601  if (gpf == NULL) {
1602  continue;
1603  }
1604  /* verify if any selected stroke is in the extreme of the stack and select to move */
1605  for (gps = gpf->strokes.first; gps; gps = gps->next) {
1606  /* only if selected */
1607  if (gps->flag & GP_STROKE_SELECT) {
1608  /* skip strokes that are invalid for current view */
1609  if (ED_gpencil_stroke_can_use(C, gps) == false) {
1610  continue;
1611  }
1612  /* check if the color is editable */
1613  if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) {
1614  continue;
1615  }
1616  bool gpf_lock = false;
1617  /* Some stroke is already at front. */
1618  if (ELEM(direction, GP_STROKE_MOVE_TOP, GP_STROKE_MOVE_UP)) {
1619  if (gps == gpf->strokes.last) {
1620  gpf_lock = true;
1621  gps_target = gps;
1622  }
1623  }
1624  /* Some stroke is already at bottom. */
1625  if (ELEM(direction, GP_STROKE_MOVE_BOTTOM, GP_STROKE_MOVE_DOWN)) {
1626  if (gps == gpf->strokes.first) {
1627  gpf_lock = true;
1628  gps_target = gps;
1629  }
1630  }
1631  /* add to list (if not locked) */
1632  if (!gpf_lock) {
1633  BLI_addtail(&selected, BLI_genericNodeN(gps));
1634  }
1635  }
1636  }
1637 
1638  const int target_index = (gps_target) ? BLI_findindex(&gpf->strokes, gps_target) : -1;
1639  int prev_index = target_index;
1640  /* Now do the movement of the stroke */
1641  switch (direction) {
1642  /* Bring to Front */
1643  case GP_STROKE_MOVE_TOP:
1644  LISTBASE_FOREACH (LinkData *, link, &selected) {
1645  gps = link->data;
1646  BLI_remlink(&gpf->strokes, gps);
1647  if (gps_target) {
1648  BLI_insertlinkbefore(&gpf->strokes, gps_target, gps);
1649  }
1650  else {
1651  BLI_addtail(&gpf->strokes, gps);
1652  }
1653  changed = true;
1654  }
1655  break;
1656  /* Bring Forward */
1657  case GP_STROKE_MOVE_UP:
1658  LISTBASE_FOREACH_BACKWARD (LinkData *, link, &selected) {
1659  gps = link->data;
1660  if (gps_target) {
1661  int gps_index = BLI_findindex(&gpf->strokes, gps);
1662  if (gps_index + 1 >= prev_index) {
1663  prev_index = gps_index;
1664  continue;
1665  }
1666  prev_index = gps_index;
1667  }
1668  BLI_listbase_link_move(&gpf->strokes, gps, 1);
1669  changed = true;
1670  }
1671  break;
1672  /* Send Backward */
1673  case GP_STROKE_MOVE_DOWN:
1674  LISTBASE_FOREACH (LinkData *, link, &selected) {
1675  gps = link->data;
1676  if (gps_target) {
1677  int gps_index = BLI_findindex(&gpf->strokes, gps);
1678  if (gps_index - 1 <= prev_index) {
1679  prev_index = gps_index;
1680  continue;
1681  }
1682  prev_index = gps_index;
1683  }
1684  BLI_listbase_link_move(&gpf->strokes, gps, -1);
1685  changed = true;
1686  }
1687  break;
1688  /* Send to Back */
1689  case GP_STROKE_MOVE_BOTTOM:
1690  LISTBASE_FOREACH_BACKWARD (LinkData *, link, &selected) {
1691  gps = link->data;
1692  BLI_remlink(&gpf->strokes, gps);
1693  if (gps_target) {
1694  BLI_insertlinkafter(&gpf->strokes, gps_target, gps);
1695  }
1696  else {
1697  BLI_addhead(&gpf->strokes, gps);
1698  }
1699  changed = true;
1700  }
1701  break;
1702  default:
1703  BLI_assert(0);
1704  break;
1705  }
1706  BLI_freelistN(&selected);
1707  }
1708 
1709  /* If not multi-edit, exit loop. */
1710  if (!is_multiedit) {
1711  break;
1712  }
1713  }
1714  }
1715  CTX_DATA_END;
1716 
1717  if (changed) {
1718  /* notifiers */
1721  }
1722 
1723  return OPERATOR_FINISHED;
1724 }
1725 
1727 {
1728  static const EnumPropertyItem slot_move[] = {
1729  {GP_STROKE_MOVE_TOP, "TOP", 0, "Bring to Front", ""},
1730  {GP_STROKE_MOVE_UP, "UP", 0, "Bring Forward", ""},
1731  {GP_STROKE_MOVE_DOWN, "DOWN", 0, "Send Backward", ""},
1732  {GP_STROKE_MOVE_BOTTOM, "BOTTOM", 0, "Send to Back", ""},
1733  {0, NULL, 0, NULL, NULL}};
1734 
1735  /* identifiers */
1736  ot->name = "Arrange Stroke";
1737  ot->idname = "GPENCIL_OT_stroke_arrange";
1738  ot->description = "Arrange selected strokes up/down in the display order of the active layer";
1739 
1740  /* callbacks */
1743 
1744  /* flags */
1746 
1747  /* properties */
1748  ot->prop = RNA_def_enum(ot->srna, "direction", slot_move, GP_STROKE_MOVE_UP, "Direction", "");
1749 }
1750 
1751 /* ******************* Move Stroke to new color ************************** */
1752 
1754 {
1755  Main *bmain = CTX_data_main(C);
1756  Material *ma = NULL;
1757  char name[MAX_ID_NAME - 2];
1758  RNA_string_get(op->ptr, "material", name);
1759 
1762  if (name[0] == '\0') {
1763  ma = BKE_gpencil_material(ob, ob->actcol);
1764  }
1765  else {
1766  ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, name);
1767  if (ma == NULL) {
1768  return OPERATOR_CANCELLED;
1769  }
1770  }
1771  /* try to find slot */
1772  int idx = BKE_gpencil_object_material_index_get(ob, ma);
1773  if (idx < 0) {
1774  return OPERATOR_CANCELLED;
1775  }
1776 
1777  /* sanity checks */
1778  if (ELEM(NULL, gpd)) {
1779  return OPERATOR_CANCELLED;
1780  }
1781 
1782  const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
1783  if (ELEM(NULL, ma)) {
1784  return OPERATOR_CANCELLED;
1785  }
1786 
1787  bool changed = false;
1788  /* loop all strokes */
1789  CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
1790  bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
1791 
1792  for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
1793  if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
1794  if (gpf == NULL) {
1795  continue;
1796  }
1797 
1798  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
1799  /* only if selected */
1800  if (gps->flag & GP_STROKE_SELECT) {
1801  /* skip strokes that are invalid for current view */
1802  if (ED_gpencil_stroke_can_use(C, gps) == false) {
1803  continue;
1804  }
1805  /* check if the color is editable */
1806  if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) {
1807  continue;
1808  }
1809 
1810  /* assign new color */
1811  gps->mat_nr = idx;
1812 
1813  changed = true;
1814  }
1815  }
1816  }
1817  /* If not multi-edit, exit loop. */
1818  if (!is_multiedit) {
1819  break;
1820  }
1821  }
1822  }
1823  CTX_DATA_END;
1824 
1825  if (changed) {
1826  /* notifiers */
1829  }
1830 
1831  return OPERATOR_FINISHED;
1832 }
1833 
1835 {
1836  /* identifiers */
1837  ot->name = "Change Stroke Color";
1838  ot->idname = "GPENCIL_OT_stroke_change_color";
1839  ot->description = "Move selected strokes to active material";
1840 
1841  /* callbacks */
1844 
1845  /* flags */
1847 
1848  RNA_def_string(ot->srna, "material", NULL, MAX_ID_NAME - 2, "Material", "Name of the material");
1849 }
1850 
1851 /* ******************* Lock color of non selected Strokes colors ************************** */
1852 
1854 {
1857  short *totcol = BKE_object_material_len_p(ob);
1858 
1859  /* sanity checks */
1860  if (ELEM(NULL, gpd)) {
1861  return OPERATOR_CANCELLED;
1862  }
1863 
1864  /* first lock all colors */
1865  for (short i = 0; i < *totcol; i++) {
1866  Material *tmp_ma = BKE_object_material_get(ob, i + 1);
1867  if (tmp_ma) {
1868  tmp_ma->gp_style->flag |= GP_MATERIAL_LOCKED;
1870  }
1871  }
1872 
1873  bool changed = false;
1874  /* loop all selected strokes and unlock any color */
1875  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
1876  /* only editable and visible layers are considered */
1877  if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
1878  for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
1879  /* only if selected */
1880  if (gps->flag & GP_STROKE_SELECT) {
1881  /* skip strokes that are invalid for current view */
1882  if (ED_gpencil_stroke_can_use(C, gps) == false) {
1883  continue;
1884  }
1885  /* unlock color */
1886  Material *tmp_ma = BKE_object_material_get(ob, gps->mat_nr + 1);
1887  if (tmp_ma) {
1888  tmp_ma->gp_style->flag &= ~GP_MATERIAL_LOCKED;
1890  }
1891 
1892  changed = true;
1893  }
1894  }
1895  }
1896  }
1897 
1898  if (changed) {
1899  /* updates */
1901 
1902  /* copy on write tag is needed, or else no refresh happens */
1904 
1905  /* notifiers */
1908  }
1909 
1910  return OPERATOR_FINISHED;
1911 }
1912 
1914 {
1915  /* identifiers */
1916  ot->name = "Lock Unused Materials";
1917  ot->idname = "GPENCIL_OT_material_lock_unused";
1918  ot->description = "Lock any material not used in any selected stroke";
1919 
1920  /* api callbacks */
1923 
1924  /* flags */
1926 }
1927 
1928 /* ************************************************ */
1929 /* Drawing Brushes Operators */
1930 
1931 /* ******************* Brush resets ************************** */
1933 {
1934  Main *bmain = CTX_data_main(C);
1936  const enum eContextObjectMode mode = CTX_data_mode_enum(C);
1937  Brush *brush = NULL;
1938 
1939  switch (mode) {
1940  case CTX_MODE_PAINT_GPENCIL: {
1941  Paint *paint = &ts->gp_paint->paint;
1942  brush = paint->brush;
1943  if (brush && brush->gpencil_settings) {
1945  }
1946  break;
1947  }
1948  case CTX_MODE_SCULPT_GPENCIL: {
1949  Paint *paint = &ts->gp_sculptpaint->paint;
1950  brush = paint->brush;
1951  if (brush && brush->gpencil_settings) {
1953  }
1954  break;
1955  }
1956  case CTX_MODE_WEIGHT_GPENCIL: {
1957  Paint *paint = &ts->gp_weightpaint->paint;
1958  brush = paint->brush;
1959  if (brush && brush->gpencil_settings) {
1961  }
1962  break;
1963  }
1964  case CTX_MODE_VERTEX_GPENCIL: {
1965  Paint *paint = &ts->gp_vertexpaint->paint;
1966  brush = paint->brush;
1967  if (brush && brush->gpencil_settings) {
1969  }
1970  break;
1971  }
1972  default:
1973  break;
1974  }
1975 
1976  /* notifiers */
1978 
1979  return OPERATOR_FINISHED;
1980 }
1981 
1983 {
1984  /* identifiers */
1985  ot->name = "Reset Brush";
1986  ot->idname = "GPENCIL_OT_brush_reset";
1987  ot->description = "Reset brush to default parameters";
1988 
1989  /* api callbacks */
1991 
1992  /* flags */
1994 }
1995 
1997  Paint *UNUSED(paint),
1998  const enum eContextObjectMode mode,
1999  char tool)
2000 {
2001  Brush *brush_next = NULL;
2002  for (Brush *brush = bmain->brushes.first; brush; brush = brush_next) {
2003  brush_next = brush->id.next;
2004 
2005  if (brush->gpencil_settings == NULL) {
2006  continue;
2007  }
2008 
2009  if ((mode == CTX_MODE_PAINT_GPENCIL) && (brush->gpencil_tool == tool)) {
2010  return brush;
2011  }
2012 
2013  if ((mode == CTX_MODE_SCULPT_GPENCIL) && (brush->gpencil_sculpt_tool == tool)) {
2014  return brush;
2015  }
2016 
2017  if ((mode == CTX_MODE_WEIGHT_GPENCIL) && (brush->gpencil_weight_tool == tool)) {
2018  return brush;
2019  }
2020 
2021  if ((mode == CTX_MODE_VERTEX_GPENCIL) && (brush->gpencil_vertex_tool == tool)) {
2022  return brush;
2023  }
2024  }
2025 
2026  return NULL;
2027 }
2028 
2030  Paint *paint,
2031  const enum eContextObjectMode mode)
2032 {
2033  Brush *brush_active = paint->brush;
2034  Brush *brush_next = NULL;
2035  for (Brush *brush = bmain->brushes.first; brush; brush = brush_next) {
2036  brush_next = brush->id.next;
2037 
2038  if ((brush->gpencil_settings == NULL) && (brush->ob_mode != OB_MODE_PAINT_GPENCIL)) {
2039  continue;
2040  }
2041 
2042  short preset = (brush->gpencil_settings) ? brush->gpencil_settings->preset_type :
2044 
2045  if (preset != GP_BRUSH_PRESET_UNKNOWN) {
2046  /* Verify to delete only the brushes of the current mode. */
2047  if (mode == CTX_MODE_PAINT_GPENCIL) {
2048  if ((preset < GP_BRUSH_PRESET_AIRBRUSH) || (preset > GP_BRUSH_PRESET_TINT)) {
2049  continue;
2050  }
2051  if ((brush_active) && (brush_active->gpencil_tool != brush->gpencil_tool)) {
2052  continue;
2053  }
2054  }
2055 
2056  if (mode == CTX_MODE_SCULPT_GPENCIL) {
2057  if ((preset < GP_BRUSH_PRESET_SMOOTH_STROKE) || (preset > GP_BRUSH_PRESET_CLONE_STROKE)) {
2058  continue;
2059  }
2060  if ((brush_active) && (brush_active->gpencil_sculpt_tool != brush->gpencil_sculpt_tool)) {
2061  continue;
2062  }
2063  }
2064 
2065  if (mode == CTX_MODE_WEIGHT_GPENCIL) {
2066  if (preset != GP_BRUSH_PRESET_DRAW_WEIGHT) {
2067  continue;
2068  }
2069  if ((brush_active) && (brush_active->gpencil_weight_tool != brush->gpencil_weight_tool)) {
2070  continue;
2071  }
2072  }
2073 
2074  if (mode == CTX_MODE_VERTEX_GPENCIL) {
2075  if ((preset < GP_BRUSH_PRESET_VERTEX_DRAW) || (preset > GP_BRUSH_PRESET_VERTEX_REPLACE)) {
2076  continue;
2077  }
2078  if ((brush_active) && (brush_active->gpencil_vertex_tool != brush->gpencil_vertex_tool)) {
2079  continue;
2080  }
2081  }
2082  }
2083 
2084  /* Before delete, un-pin any material of the brush. */
2085  if ((brush->gpencil_settings) && (brush->gpencil_settings->material != NULL)) {
2086  brush->gpencil_settings->material = NULL;
2087  brush->gpencil_settings->flag &= ~GP_BRUSH_MATERIAL_PINNED;
2088  }
2089 
2090  BKE_brush_delete(bmain, brush);
2091  if (brush == brush_active) {
2092  brush_active = NULL;
2093  }
2094  }
2095 }
2096 
2098 {
2099  Main *bmain = CTX_data_main(C);
2101  const enum eContextObjectMode mode = CTX_data_mode_enum(C);
2102  Paint *paint = NULL;
2103 
2104  switch (mode) {
2105  case CTX_MODE_PAINT_GPENCIL: {
2106  paint = &ts->gp_paint->paint;
2107  break;
2108  }
2109  case CTX_MODE_SCULPT_GPENCIL: {
2110  paint = &ts->gp_sculptpaint->paint;
2111  break;
2112  }
2113  case CTX_MODE_WEIGHT_GPENCIL: {
2114  paint = &ts->gp_weightpaint->paint;
2115  break;
2116  }
2117  case CTX_MODE_VERTEX_GPENCIL: {
2118  paint = &ts->gp_vertexpaint->paint;
2119  break;
2120  }
2121  default:
2122  break;
2123  }
2124 
2125  char tool = '0';
2126  if (paint) {
2127  if (paint->brush) {
2128  Brush *brush_active = paint->brush;
2129  switch (mode) {
2130  case CTX_MODE_PAINT_GPENCIL: {
2131  tool = brush_active->gpencil_tool;
2132  break;
2133  }
2134  case CTX_MODE_SCULPT_GPENCIL: {
2135  tool = brush_active->gpencil_sculpt_tool;
2136  break;
2137  }
2138  case CTX_MODE_WEIGHT_GPENCIL: {
2139  tool = brush_active->gpencil_weight_tool;
2140  break;
2141  }
2142  case CTX_MODE_VERTEX_GPENCIL: {
2143  tool = brush_active->gpencil_vertex_tool;
2144  break;
2145  }
2146  default: {
2147  tool = brush_active->gpencil_tool;
2148  break;
2149  }
2150  }
2151  }
2152 
2153  gpencil_brush_delete_mode_brushes(bmain, paint, mode);
2154 
2155  switch (mode) {
2156  case CTX_MODE_PAINT_GPENCIL: {
2157  BKE_brush_gpencil_paint_presets(bmain, ts, true);
2158  break;
2159  }
2160  case CTX_MODE_SCULPT_GPENCIL: {
2161  BKE_brush_gpencil_sculpt_presets(bmain, ts, true);
2162  break;
2163  }
2164  case CTX_MODE_WEIGHT_GPENCIL: {
2165  BKE_brush_gpencil_weight_presets(bmain, ts, true);
2166  break;
2167  }
2168  case CTX_MODE_VERTEX_GPENCIL: {
2169  BKE_brush_gpencil_vertex_presets(bmain, ts, true);
2170  break;
2171  }
2172  default: {
2173  break;
2174  }
2175  }
2176 
2177  BKE_paint_toolslots_brush_validate(bmain, paint);
2178 
2179  /* Set Again the first brush of the mode. */
2180  Brush *deft_brush = gpencil_brush_get_first_by_mode(bmain, paint, mode, tool);
2181  if (deft_brush) {
2182  BKE_paint_brush_set(paint, deft_brush);
2183  }
2184  /* notifiers */
2185  DEG_relations_tag_update(bmain);
2187  }
2188 
2189  return OPERATOR_FINISHED;
2190 }
2191 
2193 {
2194  /* identifiers */
2195  ot->name = "Reset All Brushes";
2196  ot->idname = "GPENCIL_OT_brush_reset_all";
2197  ot->description = "Delete all mode brushes and recreate a default set";
2198 
2199  /* api callbacks */
2201 
2202  /* flags */
2204 }
2205 
2206 /*********************** Vertex Groups ***********************************/
2207 
2209 {
2211 
2212  if ((ob) && (ob->type == OB_GPENCIL)) {
2213  Main *bmain = CTX_data_main(C);
2214  const bGPdata *gpd = (const bGPdata *)ob->data;
2215  if (BKE_id_is_editable(bmain, &ob->id) && BKE_id_is_editable(bmain, ob->data) &&
2218  return true;
2219  }
2220  }
2221  }
2222 
2223  return false;
2224 }
2225 
2227 {
2229 
2230  if ((ob) && (ob->type == OB_GPENCIL)) {
2231  Main *bmain = CTX_data_main(C);
2232  const bGPdata *gpd = (const bGPdata *)ob->data;
2233  if (BKE_id_is_editable(bmain, &ob->id) && BKE_id_is_editable(bmain, ob->data) &&
2235  if (ob->mode == OB_MODE_WEIGHT_GPENCIL) {
2236  return true;
2237  }
2238  }
2239  }
2240 
2241  return false;
2242 }
2243 
2245 {
2248 
2249  /* sanity checks */
2250  if (ELEM(NULL, ts, ob, ob->data)) {
2251  return OPERATOR_CANCELLED;
2252  }
2253 
2255 
2256  /* notifiers */
2257  bGPdata *gpd = ob->data;
2260 
2261  return OPERATOR_FINISHED;
2262 }
2263 
2265 {
2266  /* identifiers */
2267  ot->name = "Assign to Vertex Group";
2268  ot->idname = "GPENCIL_OT_vertex_group_assign";
2269  ot->description = "Assign the selected vertices to the active vertex group";
2270 
2271  /* api callbacks */
2274 
2275  /* flags */
2277 }
2278 
2279 /* remove point from vertex group */
2281 {
2283 
2284  /* sanity checks */
2285  if (ELEM(NULL, ob, ob->data)) {
2286  return OPERATOR_CANCELLED;
2287  }
2288 
2290 
2291  /* notifiers */
2292  bGPdata *gpd = ob->data;
2295 
2296  return OPERATOR_FINISHED;
2297 }
2298 
2300 {
2301  /* identifiers */
2302  ot->name = "Remove from Vertex Group";
2303  ot->idname = "GPENCIL_OT_vertex_group_remove_from";
2304  ot->description = "Remove the selected vertices from active or all vertex group(s)";
2305 
2306  /* api callbacks */
2309 
2310  /* flags */
2312 }
2313 
2315 {
2317 
2318  /* sanity checks */
2319  if (ELEM(NULL, ob, ob->data)) {
2320  return OPERATOR_CANCELLED;
2321  }
2322 
2324 
2325  /* notifiers */
2326  bGPdata *gpd = ob->data;
2329 
2330  return OPERATOR_FINISHED;
2331 }
2332 
2334 {
2335  /* identifiers */
2336  ot->name = "Select Vertex Group";
2337  ot->idname = "GPENCIL_OT_vertex_group_select";
2338  ot->description = "Select all the vertices assigned to the active vertex group";
2339 
2340  /* api callbacks */
2343 
2344  /* flags */
2346 }
2347 
2349 {
2351 
2352  /* sanity checks */
2353  if (ELEM(NULL, ob, ob->data)) {
2354  return OPERATOR_CANCELLED;
2355  }
2356 
2358 
2359  /* notifiers */
2360  bGPdata *gpd = ob->data;
2363 
2364  return OPERATOR_FINISHED;
2365 }
2366 
2368 {
2369  /* identifiers */
2370  ot->name = "Deselect Vertex Group";
2371  ot->idname = "GPENCIL_OT_vertex_group_deselect";
2372  ot->description = "Deselect all selected vertices assigned to the active vertex group";
2373 
2374  /* api callbacks */
2377 
2378  /* flags */
2380 }
2381 
2382 /* invert */
2384 {
2387  bGPdata *gpd = ob->data;
2388 
2389  /* sanity checks */
2390  if (ELEM(NULL, ts, ob, ob->data)) {
2391  return OPERATOR_CANCELLED;
2392  }
2393 
2394  MDeformVert *dvert;
2395  const int def_nr = gpd->vertex_group_active_index - 1;
2396 
2397  bDeformGroup *defgroup = BLI_findlink(&gpd->vertex_group_names, def_nr);
2398  if (defgroup == NULL) {
2399  return OPERATOR_CANCELLED;
2400  }
2401  if (defgroup->flag & DG_LOCK_WEIGHT) {
2402  BKE_report(op->reports, RPT_ERROR, "Current Vertex Group is locked");
2403  return OPERATOR_CANCELLED;
2404  }
2405 
2406  CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
2407  /* Verify the strokes has something to change. */
2408  if ((gps->totpoints == 0) || (gps->dvert == NULL)) {
2409  continue;
2410  }
2411 
2412  for (int i = 0; i < gps->totpoints; i++) {
2413  dvert = &gps->dvert[i];
2414  MDeformWeight *dw = BKE_defvert_find_index(dvert, def_nr);
2415  if (dw == NULL) {
2416  BKE_defvert_add_index_notest(dvert, def_nr, 1.0f);
2417  }
2418  else if (dw->weight == 1.0f) {
2419  BKE_defvert_remove_group(dvert, dw);
2420  }
2421  else {
2422  dw->weight = 1.0f - dw->weight;
2423  }
2424  }
2425  }
2426  CTX_DATA_END;
2427 
2428  /* notifiers */
2431 
2432  return OPERATOR_FINISHED;
2433 }
2434 
2436 {
2437  /* identifiers */
2438  ot->name = "Invert Vertex Group";
2439  ot->idname = "GPENCIL_OT_vertex_group_invert";
2440  ot->description = "Invert weights to the active vertex group";
2441 
2442  /* api callbacks */
2445 
2446  /* flags */
2448 }
2449 
2450 /* smooth */
2452 {
2453  const float fac = RNA_float_get(op->ptr, "factor");
2454  const int repeat = RNA_int_get(op->ptr, "repeat");
2455 
2458  bGPdata *gpd = ob->data;
2459 
2460  /* sanity checks */
2461  if (ELEM(NULL, ts, ob, ob->data)) {
2462  return OPERATOR_CANCELLED;
2463  }
2464 
2465  const int def_nr = gpd->vertex_group_active_index - 1;
2466  bDeformGroup *defgroup = BLI_findlink(&gpd->vertex_group_names, def_nr);
2467  if (defgroup == NULL) {
2468  return OPERATOR_CANCELLED;
2469  }
2470  if (defgroup->flag & DG_LOCK_WEIGHT) {
2471  BKE_report(op->reports, RPT_ERROR, "Current Vertex Group is locked");
2472  return OPERATOR_CANCELLED;
2473  }
2474 
2475  bGPDspoint *pta, *ptb, *ptc;
2476  MDeformVert *dverta, *dvertb;
2477 
2478  CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
2479  /* Verify the strokes has something to change. */
2480  if ((gps->totpoints == 0) || (gps->dvert == NULL)) {
2481  continue;
2482  }
2483 
2484  for (int s = 0; s < repeat; s++) {
2485  for (int i = 0; i < gps->totpoints; i++) {
2486  /* previous point */
2487  if (i > 0) {
2488  pta = &gps->points[i - 1];
2489  dverta = &gps->dvert[i - 1];
2490  }
2491  else {
2492  pta = &gps->points[i];
2493  dverta = &gps->dvert[i];
2494  }
2495  /* current */
2496  ptb = &gps->points[i];
2497  dvertb = &gps->dvert[i];
2498  /* next point */
2499  if (i + 1 < gps->totpoints) {
2500  ptc = &gps->points[i + 1];
2501  }
2502  else {
2503  ptc = &gps->points[i];
2504  }
2505 
2506  float wa = BKE_defvert_find_weight(dverta, def_nr);
2507  float wb = BKE_defvert_find_weight(dvertb, def_nr);
2508 
2509  /* the optimal value is the corresponding to the interpolation of the weight
2510  * at the distance of point b
2511  */
2512  const float opfac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
2513  const float optimal = interpf(wa, wb, opfac);
2514  /* Based on influence factor, blend between original and optimal */
2515  MDeformWeight *dw = BKE_defvert_ensure_index(dvertb, def_nr);
2516  if (dw) {
2517  dw->weight = interpf(wb, optimal, fac);
2518  CLAMP(dw->weight, 0.0, 1.0f);
2519  }
2520  }
2521  }
2522  }
2523  CTX_DATA_END;
2524 
2525  /* notifiers */
2528 
2529  return OPERATOR_FINISHED;
2530 }
2531 
2533 {
2534  /* identifiers */
2535  ot->name = "Smooth Vertex Group";
2536  ot->idname = "GPENCIL_OT_vertex_group_smooth";
2537  ot->description = "Smooth weights to the active vertex group";
2538 
2539  /* api callbacks */
2542 
2543  /* flags */
2545 
2546  RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0, "Factor", "", 0.0f, 1.0f);
2547  RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
2548 }
2549 
2550 /* normalize */
2552 {
2555  bGPdata *gpd = ob->data;
2556 
2557  /* sanity checks */
2558  if (ELEM(NULL, ts, ob, ob->data)) {
2559  return OPERATOR_CANCELLED;
2560  }
2561 
2562  MDeformVert *dvert = NULL;
2563  MDeformWeight *dw = NULL;
2564  const int def_nr = gpd->vertex_group_active_index - 1;
2565  bDeformGroup *defgroup = BLI_findlink(&gpd->vertex_group_names, def_nr);
2566  if (defgroup == NULL) {
2567  return OPERATOR_CANCELLED;
2568  }
2569  if (defgroup->flag & DG_LOCK_WEIGHT) {
2570  BKE_report(op->reports, RPT_ERROR, "Current Vertex Group is locked");
2571  return OPERATOR_CANCELLED;
2572  }
2573 
2574  CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
2575  /* Verify the strokes has something to change. */
2576  if ((gps->totpoints == 0) || (gps->dvert == NULL)) {
2577  continue;
2578  }
2579 
2580  /* look for max value */
2581  float maxvalue = 0.0f;
2582  for (int i = 0; i < gps->totpoints; i++) {
2583  dvert = &gps->dvert[i];
2584  dw = BKE_defvert_find_index(dvert, def_nr);
2585  if ((dw != NULL) && (dw->weight > maxvalue)) {
2586  maxvalue = dw->weight;
2587  }
2588  }
2589 
2590  /* normalize weights */
2591  if (maxvalue > 0.0f) {
2592  for (int i = 0; i < gps->totpoints; i++) {
2593  dvert = &gps->dvert[i];
2594  dw = BKE_defvert_find_index(dvert, def_nr);
2595  if (dw != NULL) {
2596  dw->weight = dw->weight / maxvalue;
2597  }
2598  }
2599  }
2600  }
2601  CTX_DATA_END;
2602 
2603  /* notifiers */
2606 
2607  return OPERATOR_FINISHED;
2608 }
2609 
2611 {
2612  /* identifiers */
2613  ot->name = "Normalize Vertex Group";
2614  ot->idname = "GPENCIL_OT_vertex_group_normalize";
2615  ot->description = "Normalize weights to the active vertex group";
2616 
2617  /* api callbacks */
2620 
2621  /* flags */
2623 }
2624 
2625 /* normalize all */
2627 {
2630  bool lock_active = RNA_boolean_get(op->ptr, "lock_active");
2631  bGPdata *gpd = ob->data;
2632 
2633  /* sanity checks */
2634  if (ELEM(NULL, ts, ob, ob->data)) {
2635  return OPERATOR_CANCELLED;
2636  }
2637 
2638  bDeformGroup *defgroup = NULL;
2639  MDeformVert *dvert = NULL;
2640  MDeformWeight *dw = NULL;
2641  const int def_nr = gpd->vertex_group_active_index - 1;
2642  const int defbase_tot = BLI_listbase_count(&gpd->vertex_group_names);
2643  if (defbase_tot == 0) {
2644  return OPERATOR_CANCELLED;
2645  }
2646 
2647  CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
2648  /* Verify the strokes has something to change. */
2649  if ((gps->totpoints == 0) || (gps->dvert == NULL)) {
2650  continue;
2651  }
2652 
2653  /* look for tot value */
2654  float *tot_values = MEM_callocN(gps->totpoints * sizeof(float), __func__);
2655 
2656  for (int i = 0; i < gps->totpoints; i++) {
2657  dvert = &gps->dvert[i];
2658  for (int v = 0; v < defbase_tot; v++) {
2659  defgroup = BLI_findlink(&gpd->vertex_group_names, v);
2660  /* skip NULL or locked groups */
2661  if ((defgroup == NULL) || (defgroup->flag & DG_LOCK_WEIGHT)) {
2662  continue;
2663  }
2664 
2665  /* skip current */
2666  if ((lock_active) && (v == def_nr)) {
2667  continue;
2668  }
2669 
2670  dw = BKE_defvert_find_index(dvert, v);
2671  if (dw != NULL) {
2672  tot_values[i] += dw->weight;
2673  }
2674  }
2675  }
2676 
2677  /* normalize weights */
2678  for (int i = 0; i < gps->totpoints; i++) {
2679  if (tot_values[i] == 0.0f) {
2680  continue;
2681  }
2682 
2683  dvert = &gps->dvert[i];
2684  for (int v = 0; v < defbase_tot; v++) {
2685  defgroup = BLI_findlink(&gpd->vertex_group_names, v);
2686  /* skip NULL or locked groups */
2687  if ((defgroup == NULL) || (defgroup->flag & DG_LOCK_WEIGHT)) {
2688  continue;
2689  }
2690 
2691  /* skip current */
2692  if ((lock_active) && (v == def_nr)) {
2693  continue;
2694  }
2695 
2696  dw = BKE_defvert_find_index(dvert, v);
2697  if (dw != NULL) {
2698  dw->weight = dw->weight / tot_values[i];
2699  }
2700  }
2701  }
2702 
2703  /* free temp array */
2704  MEM_SAFE_FREE(tot_values);
2705  }
2706  CTX_DATA_END;
2707 
2708  /* notifiers */
2711 
2712  return OPERATOR_FINISHED;
2713 }
2714 
2716 {
2717  /* identifiers */
2718  ot->name = "Normalize All Vertex Group";
2719  ot->idname = "GPENCIL_OT_vertex_group_normalize_all";
2720  ot->description =
2721  "Normalize all weights of all vertex groups, "
2722  "so that for each vertex, the sum of all weights is 1.0";
2723 
2724  /* api callbacks */
2727 
2728  /* flags */
2730 
2731  /* props */
2733  "lock_active",
2734  true,
2735  "Lock Active",
2736  "Keep the values of the active group while normalizing others");
2737 }
2738 
2739 /****************************** Join ***********************************/
2740 
2741 /* userdata for joined_gpencil_fix_animdata_cb() */
2742 typedef struct tJoinGPencil_AdtFixData {
2745 
2748 
2753 static void gpencil_joined_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data)
2754 {
2756  ID *src_id = &afd->src_gpd->id;
2757  ID *dst_id = &afd->tar_gpd->id;
2758 
2759  GHashIterator gh_iter;
2760 
2761  /* Fix paths - If this is the target datablock, it will have some "dirty" paths */
2762  if ((id == src_id) && fcu->rna_path && strstr(fcu->rna_path, "layers[")) {
2763  GHASH_ITER (gh_iter, afd->names_map) {
2764  const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
2765  const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
2766 
2767  /* only remap if changed;
2768  * this still means there will be some waste if there aren't many drivers/keys */
2769  if (!STREQ(old_name, new_name) && strstr(fcu->rna_path, old_name)) {
2771  id, fcu->rna_path, "layers", old_name, new_name, 0, 0, false);
2772 
2773  /* We don't want to apply a second remapping on this F-Curve now,
2774  * so stop trying to fix names. */
2775  break;
2776  }
2777  }
2778  }
2779 
2780  /* Fix driver targets */
2781  if (fcu->driver) {
2782  /* Fix driver references to invalid ID's */
2783  LISTBASE_FOREACH (DriverVar *, dvar, &fcu->driver->variables) {
2784  /* Only change the used targets, since the others will need fixing manually anyway. */
2786  /* Change the ID's used. */
2787  if (dtar->id == src_id) {
2788  dtar->id = dst_id;
2789 
2790  /* Also check on the sub-target.
2791  * We duplicate the logic from #drivers_path_rename_fix() here, with our own
2792  * little twists so that we know that it isn't going to clobber the wrong data
2793  */
2794  if (dtar->rna_path && strstr(dtar->rna_path, "layers[")) {
2795  GHASH_ITER (gh_iter, afd->names_map) {
2796  const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
2797  const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
2798 
2799  /* Only remap if changed. */
2800  if (!STREQ(old_name, new_name)) {
2801  if ((dtar->rna_path) && strstr(dtar->rna_path, old_name)) {
2802  /* Fix up path */
2803  dtar->rna_path = BKE_animsys_fix_rna_path_rename(
2804  id, dtar->rna_path, "layers", old_name, new_name, 0, 0, false);
2805  break; /* no need to try any more names for layer path */
2806  }
2807  }
2808  }
2809  }
2810  }
2811  }
2813  }
2814  }
2815 }
2816 
2818 {
2819  Main *bmain = CTX_data_main(C);
2822  Object *ob_active = CTX_data_active_object(C);
2823  bool ok = false;
2824 
2825  /* Ensure we're in right mode and that the active object is correct */
2826  if (!ob_active || ob_active->type != OB_GPENCIL) {
2827  return OPERATOR_CANCELLED;
2828  }
2829 
2830  bGPdata *gpd = (bGPdata *)ob_active->data;
2831  if ((!gpd) || GPENCIL_ANY_MODE(gpd)) {
2832  return OPERATOR_CANCELLED;
2833  }
2834 
2835  /* Ensure all rotations are applied before */
2836  CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
2837  if (ob_iter->type == OB_GPENCIL) {
2838  if ((ob_iter->rot[0] != 0) || (ob_iter->rot[1] != 0) || (ob_iter->rot[2] != 0)) {
2839  BKE_report(op->reports, RPT_ERROR, "Apply all rotations before join objects");
2840  return OPERATOR_CANCELLED;
2841  }
2842  }
2843  }
2844  CTX_DATA_END;
2845 
2846  CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
2847  if (ob_iter == ob_active) {
2848  ok = true;
2849  break;
2850  }
2851  }
2852  CTX_DATA_END;
2853 
2854  /* that way the active object is always selected */
2855  if (ok == false) {
2856  BKE_report(op->reports, RPT_WARNING, "Active object is not a selected grease pencil");
2857  return OPERATOR_CANCELLED;
2858  }
2859 
2860  bGPdata *gpd_dst = ob_active->data;
2861  Object *ob_dst = ob_active;
2862 
2863  /* loop and join all data */
2864  CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
2865  if ((ob_iter->type == OB_GPENCIL) && (ob_iter != ob_active)) {
2866  /* we assume that each datablock is not already used in active object */
2867  if (ob_active->data != ob_iter->data) {
2868  Object *ob_src = ob_iter;
2869  bGPdata *gpd_src = ob_iter->data;
2870 
2871  /* Apply all GP modifiers before */
2872  LISTBASE_FOREACH (GpencilModifierData *, md, &ob_iter->greasepencil_modifiers) {
2874  if (mti->bakeModifier) {
2875  mti->bakeModifier(bmain, depsgraph, md, ob_iter);
2876  }
2877  }
2878 
2879  /* copy vertex groups to the base one's */
2880  int old_idx = 0;
2881  LISTBASE_FOREACH (bDeformGroup *, dg, &gpd_src->vertex_group_names) {
2882  bDeformGroup *vgroup = MEM_dupallocN(dg);
2883  int idx = BLI_listbase_count(&gpd_dst->vertex_group_names);
2884  BKE_object_defgroup_unique_name(vgroup, ob_active);
2885  BLI_addtail(&gpd_dst->vertex_group_names, vgroup);
2886  /* update vertex groups in strokes in original data */
2887  LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd->layers) {
2888  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_src->frames) {
2889  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
2890  MDeformVert *dvert;
2891  int i;
2892  if (gps->dvert == NULL) {
2893  continue;
2894  }
2895  for (i = 0, dvert = gps->dvert; i < gps->totpoints; i++, dvert++) {
2896  if ((dvert->dw != NULL) && (dvert->dw->def_nr == old_idx)) {
2897  dvert->dw->def_nr = idx;
2898  }
2899  }
2900  }
2901  }
2902  }
2903  old_idx++;
2904  }
2905  if (!BLI_listbase_is_empty(&gpd_dst->vertex_group_names) &&
2906  gpd_dst->vertex_group_active_index == 0) {
2907  gpd_dst->vertex_group_active_index = 1;
2908  }
2909 
2910  /* add missing materials reading source materials and checking in destination object */
2911  short *totcol = BKE_object_material_len_p(ob_src);
2912 
2913  for (short i = 0; i < *totcol; i++) {
2914  Material *tmp_ma = BKE_gpencil_material(ob_src, i + 1);
2915  BKE_gpencil_object_material_ensure(bmain, ob_dst, tmp_ma);
2916  }
2917 
2918  /* Duplicate #bGPDlayers. */
2919  tJoinGPencil_AdtFixData afd = {0};
2920  afd.src_gpd = gpd_src;
2921  afd.tar_gpd = gpd_dst;
2922  afd.names_map = BLI_ghash_str_new("joined_gp_layers_map");
2923 
2924  float imat[3][3], bmat[3][3];
2925  float offset_global[3];
2926  float offset_local[3];
2927 
2928  sub_v3_v3v3(offset_global, ob_active->loc, ob_iter->obmat[3]);
2929  copy_m3_m4(bmat, ob_active->obmat);
2930 
2931  /* Inverse transform for all selected curves in this object,
2932  * See #object_join_exec for detailed comment on why the safe version is used. */
2933  invert_m3_m3_safe_ortho(imat, bmat);
2934  mul_m3_v3(imat, offset_global);
2935  mul_v3_m3v3(offset_local, imat, offset_global);
2936 
2937  LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) {
2938  bGPDlayer *gpl_new = BKE_gpencil_layer_duplicate(gpl_src, true, true);
2939  float diff_mat[4][4];
2940  float inverse_diff_mat[4][4];
2941 
2942  /* recalculate all stroke points */
2943  BKE_gpencil_layer_transform_matrix_get(depsgraph, ob_iter, gpl_src, diff_mat);
2944  invert_m4_m4_safe_ortho(inverse_diff_mat, diff_mat);
2945 
2946  Material *ma_src = NULL;
2947  LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_new->frames) {
2948  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
2949 
2950  /* Reassign material. Look old material and try to find in destination. */
2951  ma_src = BKE_gpencil_material(ob_src, gps->mat_nr + 1);
2952  gps->mat_nr = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
2953 
2954  bGPDspoint *pt;
2955  int i;
2956  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
2957  float mpt[3];
2958  mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
2959  sub_v3_v3(mpt, offset_local);
2960  mul_v3_m4v3(&pt->x, diff_mat, mpt);
2961  }
2962  }
2963  }
2964 
2965  /* be sure name is unique in new object */
2966  BLI_uniquename(&gpd_dst->layers,
2967  gpl_new,
2968  DATA_("GP_Layer"),
2969  '.',
2970  offsetof(bGPDlayer, info),
2971  sizeof(gpl_new->info));
2972  BLI_ghash_insert(afd.names_map, BLI_strdup(gpl_src->info), gpl_new->info);
2973 
2974  /* add to destination datablock */
2975  BLI_addtail(&gpd_dst->layers, gpl_new);
2976  }
2977 
2978  /* Fix all the animation data */
2981 
2982  /* Only copy over animdata now, after all the remapping has been done,
2983  * so that we don't have to worry about ambiguities re which datablock
2984  * a layer came from!
2985  */
2986  if (ob_iter->adt) {
2987  if (ob_active->adt == NULL) {
2988  /* no animdata, so just use a copy of the whole thing */
2989  ob_active->adt = BKE_animdata_copy(bmain, ob_iter->adt, 0);
2990  }
2991  else {
2992  /* merge in data - we'll fix the drivers manually */
2994  bmain, &ob_active->id, &ob_iter->id, ADT_MERGECOPY_KEEP_DST, false);
2995  }
2996  }
2997 
2998  if (gpd_src->adt) {
2999  if (gpd_dst->adt == NULL) {
3000  /* no animdata, so just use a copy of the whole thing */
3001  gpd_dst->adt = BKE_animdata_copy(bmain, gpd_src->adt, 0);
3002  }
3003  else {
3004  /* merge in data - we'll fix the drivers manually */
3006  bmain, &gpd_dst->id, &gpd_src->id, ADT_MERGECOPY_KEEP_DST, false);
3007  }
3008  }
3009  DEG_id_tag_update(&gpd_src->id,
3011  }
3012 
3013  /* Free the old object */
3014  ED_object_base_free_and_unlink(bmain, scene, ob_iter);
3015  }
3016  }
3017  CTX_DATA_END;
3018 
3019  DEG_id_tag_update(&gpd_dst->id,
3021  DEG_relations_tag_update(bmain); /* because we removed object(s) */
3022 
3025 
3026  return OPERATOR_FINISHED;
3027 }
3028 
3029 /* Color Handle operator */
3031 {
3033  if (ob && ob->data && (ob->type == OB_GPENCIL)) {
3034  short *totcolp = BKE_object_material_len_p(ob);
3035  return *totcolp > 0;
3036  }
3037  return false;
3038 }
3039 
3040 /* **************** Lock and hide any color non used in current layer **************************
3041  */
3043 {
3046  MaterialGPencilStyle *gp_style = NULL;
3047 
3048  /* sanity checks */
3049  if (ELEM(NULL, gpd)) {
3050  return OPERATOR_CANCELLED;
3051  }
3052 
3053  /* first lock and hide all colors */
3054  Material *ma = NULL;
3055  short *totcol = BKE_object_material_len_p(ob);
3056  if (totcol == 0) {
3057  return OPERATOR_CANCELLED;
3058  }
3059 
3060  for (short i = 0; i < *totcol; i++) {
3061  ma = BKE_gpencil_material(ob, i + 1);
3062  if (ma) {
3063  gp_style = ma->gp_style;
3064  gp_style->flag |= GP_MATERIAL_LOCKED;
3065  gp_style->flag |= GP_MATERIAL_HIDE;
3067  }
3068  }
3069 
3070  /* loop all selected strokes and unlock any color used in active layer */
3071  LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
3072  /* only editable and visible layers are considered */
3073  if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL) &&
3074  (gpl->flag & GP_LAYER_ACTIVE)) {
3075  for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
3076  /* skip strokes that are invalid for current view */
3077  if (ED_gpencil_stroke_can_use(C, gps) == false) {
3078  continue;
3079  }
3080 
3081  ma = BKE_gpencil_material(ob, gps->mat_nr + 1);
3083 
3084  gp_style = ma->gp_style;
3085  /* unlock/unhide color if not unlocked before */
3086  if (gp_style != NULL) {
3087  gp_style->flag &= ~GP_MATERIAL_LOCKED;
3088  gp_style->flag &= ~GP_MATERIAL_HIDE;
3089  }
3090  }
3091  }
3092  }
3093  /* updates */
3095 
3096  /* copy on write tag is needed, or else no refresh happens */
3098 
3099  /* notifiers */
3102 
3103  return OPERATOR_FINISHED;
3104 }
3105 
3107 {
3108  /* identifiers */
3109  ot->name = "Disable Unused Layer Colors";
3110  ot->idname = "GPENCIL_OT_lock_layer";
3111  ot->description = "Lock and hide any color not used in any layer";
3112 
3113  /* api callbacks */
3116 }
3117 
3118 /* ********************** Isolate gpencil_ color **************************** */
3119 
3121 {
3124  Material *active_ma = BKE_gpencil_material(ob, ob->actcol);
3126  MaterialGPencilStyle *gp_style;
3127 
3128  int flags = GP_MATERIAL_LOCKED;
3129  bool isolate = false;
3130 
3131  if (RNA_boolean_get(op->ptr, "affect_visibility")) {
3132  flags |= GP_MATERIAL_HIDE;
3133  }
3134 
3135  if (ELEM(NULL, gpd, active_color)) {
3136  BKE_report(op->reports, RPT_ERROR, "No active color to isolate");
3137  return OPERATOR_CANCELLED;
3138  }
3139 
3140  /* Test whether to isolate or clear all flags */
3141  Material *ma = NULL;
3142  short *totcol = BKE_object_material_len_p(ob);
3143  for (short i = 0; i < *totcol; i++) {
3144  ma = BKE_gpencil_material(ob, i + 1);
3145  /* Skip if this is the active one */
3146  if (ELEM(ma, NULL, active_ma)) {
3147  continue;
3148  }
3149 
3150  /* If the flags aren't set, that means that the color is
3151  * not alone, so we have some colors to isolate still
3152  */
3153  gp_style = ma->gp_style;
3154  if ((gp_style->flag & flags) == 0) {
3155  isolate = true;
3156  break;
3157  }
3158  }
3159 
3160  /* Set/Clear flags as appropriate */
3161  if (isolate) {
3162  /* Set flags on all "other" colors */
3163  for (short i = 0; i < *totcol; i++) {
3164  ma = BKE_gpencil_material(ob, i + 1);
3165  if (ma == NULL) {
3166  continue;
3167  }
3168  gp_style = ma->gp_style;
3169  if (gp_style == active_color) {
3170  continue;
3171  }
3172  gp_style->flag |= flags;
3174  }
3175  }
3176  else {
3177  /* Clear flags - Restore everything else */
3178  for (short i = 0; i < *totcol; i++) {
3179  ma = BKE_gpencil_material(ob, i + 1);
3180  if (ma == NULL) {
3181  continue;
3182  }
3183  gp_style = ma->gp_style;
3184  gp_style->flag &= ~flags;
3186  }
3187  }
3188 
3189  /* notifiers */
3191 
3192  /* copy on write tag is needed, or else no refresh happens */
3194 
3196 
3197  return OPERATOR_FINISHED;
3198 }
3199 
3201 {
3202  /* identifiers */
3203  ot->name = "Isolate Material";
3204  ot->idname = "GPENCIL_OT_material_isolate";
3205  ot->description =
3206  "Toggle whether the active material is the only one that is editable and/or visible";
3207 
3208  /* callbacks */
3211 
3212  /* flags */
3214 
3215  /* properties */
3217  "affect_visibility",
3218  false,
3219  "Affect Visibility",
3220  "In addition to toggling "
3221  "the editability, also affect the visibility");
3222 }
3223 
3224 /* *********************** Hide colors ******************************** */
3225 
3227 {
3229  bGPdata *gpd = (bGPdata *)ob->data;
3231 
3232  bool unselected = RNA_boolean_get(op->ptr, "unselected");
3233 
3234  Material *ma = NULL;
3235  short *totcol = BKE_object_material_len_p(ob);
3236  if (totcol == 0) {
3237  return OPERATOR_CANCELLED;
3238  }
3239 
3240  if (unselected) {
3241  /* hide unselected */
3243  for (short i = 0; i < *totcol; i++) {
3244  ma = BKE_gpencil_material(ob, i + 1);
3245  if (ma) {
3246  color = ma->gp_style;
3247  if (active_color != color) {
3248  color->flag |= GP_MATERIAL_HIDE;
3250  }
3251  }
3252  }
3253  }
3254  else {
3255  /* hide selected/active */
3256  active_color->flag |= GP_MATERIAL_HIDE;
3257  }
3258 
3259  /* updates */
3261 
3262  /* copy on write tag is needed, or else no refresh happens */
3264 
3265  /* notifiers */
3267 
3268  return OPERATOR_FINISHED;
3269 }
3270 
3272 {
3273  /* identifiers */
3274  ot->name = "Hide Material(s)";
3275  ot->idname = "GPENCIL_OT_material_hide";
3276  ot->description = "Hide selected/unselected Grease Pencil materials";
3277 
3278  /* callbacks */
3280  ot->poll = gpencil_active_material_poll; /* NOTE: we need an active color to play with */
3281 
3282  /* flags */
3284 
3285  /* props */
3287  ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected colors");
3288 }
3289 
3290 /* ********************** Show All Colors ***************************** */
3291 
3293 {
3295  bGPdata *gpd = (bGPdata *)ob->data;
3296  Material *ma = NULL;
3297  short *totcol = BKE_object_material_len_p(ob);
3298 
3299  if (totcol == 0) {
3300  return OPERATOR_CANCELLED;
3301  }
3302 
3303  /* make all colors visible */
3304  MaterialGPencilStyle *gp_style = NULL;
3305 
3306  for (short i = 0; i < *totcol; i++) {
3307  ma = BKE_gpencil_material(ob, i + 1);
3308  if (ma) {
3309  gp_style = ma->gp_style;
3310  gp_style->flag &= ~GP_MATERIAL_HIDE;
3312  }
3313  }
3314 
3315  /* updates */
3317 
3318  /* copy on write tag is needed, or else no refresh happens */
3320 
3321  /* notifiers */
3323 
3324  return OPERATOR_FINISHED;
3325 }
3326 
3328 {
3329  /* identifiers */
3330  ot->name = "Show All Materials";
3331  ot->idname = "GPENCIL_OT_material_reveal";
3332  ot->description = "Unhide all hidden Grease Pencil materials";
3333 
3334  /* callbacks */
3337 
3338  /* flags */
3340 }
3341 
3342 /* ***************** Lock/Unlock All colors ************************ */
3343 
3345 {
3346 
3348  bGPdata *gpd = (bGPdata *)ob->data;
3349  Material *ma = NULL;
3350  short *totcol = BKE_object_material_len_p(ob);
3351 
3352  if (totcol == 0) {
3353  return OPERATOR_CANCELLED;
3354  }
3355 
3356  /* make all layers non-editable */
3357  MaterialGPencilStyle *gp_style = NULL;
3358 
3359  for (short i = 0; i < *totcol; i++) {
3360  ma = BKE_gpencil_material(ob, i + 1);
3361  if (ma) {
3362  gp_style = ma->gp_style;
3363  gp_style->flag |= GP_MATERIAL_LOCKED;
3365  }
3366  }
3367 
3368  /* updates */
3370 
3371  /* copy on write tag is needed, or else no refresh happens */
3373 
3374  /* notifiers */
3376 
3377  return OPERATOR_FINISHED;
3378 }
3379 
3381 {
3382  /* identifiers */
3383  ot->name = "Lock All Materials";
3384  ot->idname = "GPENCIL_OT_material_lock_all";
3385  ot->description =
3386  "Lock all Grease Pencil materials to prevent them from being accidentally modified";
3387 
3388  /* callbacks */
3391 
3392  /* flags */
3394 }
3395 
3396 /* -------------------------- */
3397 
3399 {
3401  bGPdata *gpd = (bGPdata *)ob->data;
3402  Material *ma = NULL;
3403  short *totcol = BKE_object_material_len_p(ob);
3404 
3405  if (totcol == 0) {
3406  return OPERATOR_CANCELLED;
3407  }
3408 
3409  /* Make all layers editable again. */
3410  MaterialGPencilStyle *gp_style = NULL;
3411 
3412  for (short i = 0; i < *totcol; i++) {
3413  ma = BKE_gpencil_material(ob, i + 1);
3414  if (ma) {
3415  gp_style = ma->gp_style;
3416  gp_style->flag &= ~GP_MATERIAL_LOCKED;
3418  }
3419  }
3420 
3421  /* updates */
3423 
3424  /* copy on write tag is needed, or else no refresh happens */
3426 
3427  /* notifiers */
3429 
3430  return OPERATOR_FINISHED;
3431 }
3432 
3434 {
3435  /* identifiers */
3436  ot->name = "Unlock All Materials";
3437  ot->idname = "GPENCIL_OT_material_unlock_all";
3438  ot->description = "Unlock all Grease Pencil materials so that they can be edited";
3439 
3440  /* callbacks */
3443 
3444  /* flags */
3446 }
3447 
3448 /* ***************** Select all strokes using color ************************ */
3449 
3451 {
3455  const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
3456  const bool deselected = RNA_boolean_get(op->ptr, "deselect");
3457 
3458  /* sanity checks */
3459  if (ELEM(NULL, gpd, gp_style)) {
3460  return OPERATOR_CANCELLED;
3461  }
3462 
3463  /* Read all strokes and select. */
3464  CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
3465  bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
3466 
3467  for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
3468  if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
3469 
3470  /* verify something to do */
3471  LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
3472  /* skip strokes that are invalid for current view */
3473  if (ED_gpencil_stroke_can_use(C, gps) == false) {
3474  continue;
3475  }
3476  /* check if the color is editable */
3477  if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) {
3478  continue;
3479  }
3480 
3481  /* select */
3482  if (ob->actcol == gps->mat_nr + 1) {
3483  bGPDspoint *pt;
3484  int i;
3485 
3486  if (!deselected) {
3487  gps->flag |= GP_STROKE_SELECT;
3489  }
3490  else {
3491  gps->flag &= ~GP_STROKE_SELECT;
3493  }
3494  for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
3495  if (!deselected) {
3496  pt->flag |= GP_SPOINT_SELECT;
3497  }
3498  else {
3499  pt->flag &= ~GP_SPOINT_SELECT;
3500  }
3501  }
3502  }
3503  }
3504  }
3505  /* If not multi-edit, exit loop. */
3506  if (!is_multiedit) {
3507  break;
3508  }
3509  }
3510  }
3511  CTX_DATA_END;
3512 
3513  /* copy on write tag is needed, or else no refresh happens */
3515 
3516  /* notifiers */
3518 
3519  return OPERATOR_FINISHED;
3520 }
3521 
3523 {
3524  /* identifiers */
3525  ot->name = "Select Material";
3526  ot->idname = "GPENCIL_OT_material_select";
3527  ot->description = "Select/Deselect all Grease Pencil strokes using current material";
3528 
3529  /* callbacks */
3532 
3533  /* flags */
3535 
3536  /* props */
3537  ot->prop = RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Unselect strokes");
3539 }
3540 
3541 /* ***************** Set active material ************************* */
3543 {
3545  int slot = RNA_enum_get(op->ptr, "slot");
3546 
3547  /* Try to get material */
3548  if ((slot < 1) || (slot > ob->totcol)) {
3549  BKE_reportf(
3550  op->reports, RPT_ERROR, "Cannot change to non-existent material (index = %d)", slot);
3551  return OPERATOR_CANCELLED;
3552  }
3553 
3554  /* Set active material. */
3555  ob->actcol = slot;
3556 
3557  /* updates */
3560 
3561  return OPERATOR_FINISHED;
3562 }
3563 
3565 {
3566  /* identifiers */
3567  ot->name = "Set Material";
3568  ot->idname = "GPENCIL_OT_material_set";
3569  ot->description = "Set active material";
3570 
3571  /* callbacks */
3574 
3575  /* flags */
3577 
3578  /* Material to use (dynamic enum) */
3579  ot->prop = RNA_def_enum(ot->srna, "slot", DummyRNA_DEFAULT_items, 0, "Material Slot", "");
3581 }
3582 
3583 /* ***************** Set selected stroke material the active material ************************ */
3584 
3586 {
3589 
3590  /* Sanity checks. */
3591  if (gpd == NULL) {
3592  BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
3593  return OPERATOR_CANCELLED;
3594  }
3595 
3596  bool changed = false;
3597  /* Loop all selected strokes. */
3598  GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
3599  if (gps->flag & GP_STROKE_SELECT) {
3600  /* Change Active material. */
3601  ob->actcol = gps->mat_nr + 1;
3602  changed = true;
3603  break;
3604  }
3605  }
3606  GP_EDITABLE_STROKES_END(gpstroke_iter);
3607 
3608  /* notifiers */
3609  if (changed) {
3611  }
3612 
3613  return OPERATOR_FINISHED;
3614 }
3615 
3617 {
3618  /* identifiers */
3619  ot->name = "Set active material";
3620  ot->idname = "GPENCIL_OT_set_active_material";
3621  ot->description = "Set the selected stroke material as the active material";
3622 
3623  /* callbacks */
3626 
3627  /* flags */
3629 }
3630 
3631 /* ********************* Append Materials in a new object ************************** */
3633 {
3635  if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
3636  return false;
3637  }
3638  short *totcolp = BKE_object_material_len_p(ob);
3639  if (*totcolp == 0) {
3640  return false;
3641  }
3642 
3643  return true;
3644 }
3645 
3647 {
3648  Main *bmain = CTX_data_main(C);
3649  const bool only_active = RNA_boolean_get(op->ptr, "only_active");
3650  Object *ob_src = CTX_data_active_object(C);
3651  Material *ma_active = BKE_gpencil_material(ob_src, ob_src->actcol);
3652 
3653  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
3654  if ((ob == ob_src) || (ob->type != OB_GPENCIL)) {
3655  continue;
3656  }
3657  /* Duplicate materials. */
3658  for (int i = 0; i < ob_src->totcol; i++) {
3659  Material *ma_src = BKE_object_material_get(ob_src, i + 1);
3660  if (only_active && ma_src != ma_active) {
3661  continue;
3662  }
3663 
3664  if (ma_src != NULL) {
3665  BKE_gpencil_object_material_ensure(bmain, ob, ma_src);
3666  }
3667  }
3668 
3669  /* notifiers */
3671  }
3672  CTX_DATA_END;
3673 
3674  /* notifiers */
3676 
3677  return OPERATOR_FINISHED;
3678 }
3679 
3681 {
3682  PropertyRNA *prop;
3683 
3684  /* identifiers */
3685  ot->name = "Copy Materials to Selected Object";
3686  ot->idname = "GPENCIL_OT_materials_copy_to_object";
3687  ot->description = "Append Materials of the active Grease Pencil to other object";
3688 
3689  /* callbacks */
3692 
3693  /* flags */
3695 
3696  prop = RNA_def_boolean(ot->srna,
3697  "only_active",
3698  true,
3699  "Only Active",
3700  "Append only active material, uncheck to append all materials");
3702 }
3703 
3705  ReportList *reports,
3706  Object *ob,
3707  Object *ob_latt)
3708 {
3709  Main *bmain = CTX_data_main(C);
3711 
3712  if (ob == NULL) {
3713  return false;
3714  }
3715 
3716  /* if no lattice modifier, add a new one */
3718  if (md == NULL) {
3720  reports, bmain, scene, ob, "Lattice", eGpencilModifierType_Lattice);
3721  if (md == NULL) {
3722  BKE_report(reports, RPT_ERROR, "Unable to add a new Lattice modifier to object");
3723  return false;
3724  }
3726  }
3727 
3728  /* verify lattice */
3730  if (mmd->object == NULL) {
3731  mmd->object = ob_latt;
3732  }
3733  else {
3734  if (ob_latt != mmd->object) {
3735  BKE_report(reports,
3736  RPT_ERROR,
3737  "The existing Lattice modifier is already using a different Lattice object");
3738  return false;
3739  }
3740  }
3741 
3742  return true;
3743 }
3744 
3745 /* Masking operators */
3747 {
3749  if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
3750  return OPERATOR_CANCELLED;
3751  }
3752 
3753  bGPdata *gpd = (bGPdata *)ob->data;
3754  bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd);
3755  if (gpl_active == NULL) {
3756  return OPERATOR_CANCELLED;
3757  }
3758  char name[128];
3759  RNA_string_get(op->ptr, "name", name);
3760  bGPDlayer *gpl = BKE_gpencil_layer_named_get(gpd, name);
3761 
3762  if (gpl == NULL) {
3763  BKE_report(op->reports, RPT_ERROR, "Unable to find layer to add");
3764  return OPERATOR_CANCELLED;
3765  }
3766 
3767  if (gpl == gpl_active) {
3768  BKE_report(op->reports, RPT_ERROR, "Cannot add active layer as mask");
3769  return OPERATOR_CANCELLED;
3770  }
3771 
3772  if (BKE_gpencil_layer_mask_named_get(gpl_active, name)) {
3773  BKE_report(op->reports, RPT_ERROR, "Layer already added");
3774  return OPERATOR_CANCELLED;
3775  }
3776 
3777  if (gpl_active->act_mask == 256) {
3778  BKE_report(op->reports, RPT_ERROR, "Maximum number of masking layers reached");
3779  return OPERATOR_CANCELLED;
3780  }
3781 
3782  BKE_gpencil_layer_mask_add(gpl_active, name);
3783 
3784  /* Reorder masking. */
3785  BKE_gpencil_layer_mask_sort(gpd, gpl_active);
3786 
3787  /* notifiers */
3788  if (gpd) {
3789  DEG_id_tag_update(&gpd->id,
3791  }
3793 
3794  return OPERATOR_FINISHED;
3795 }
3796 
3798 {
3799  /* identifiers */
3800  ot->name = "Add New Mask Layer";
3801  ot->idname = "GPENCIL_OT_layer_mask_add";
3802  ot->description = "Add new layer as masking";
3803 
3805 
3806  /* callbacks */
3809 
3810  /* properties */
3811  RNA_def_string(ot->srna, "name", NULL, 128, "Layer", "Name of the layer");
3812 }
3813 
3815 {
3817  if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
3818  return OPERATOR_CANCELLED;
3819  }
3820 
3821  bGPdata *gpd = (bGPdata *)ob->data;
3823  if (gpl == NULL) {
3824  return OPERATOR_CANCELLED;
3825  }
3826  if (gpl->act_mask > 0) {
3827  bGPDlayer_Mask *mask = BLI_findlink(&gpl->mask_layers, gpl->act_mask - 1);
3828  if (mask != NULL) {
3830  if ((gpl->mask_layers.first != NULL) && (gpl->act_mask == 0)) {
3831  gpl->act_mask = 1;
3832  }
3833  }
3834  }
3835 
3836  /* Reorder masking. */
3837  BKE_gpencil_layer_mask_sort(gpd, gpl);
3838 
3839  /* notifiers */
3842 
3843  return OPERATOR_FINISHED;
3844 }
3845 
3847 {
3848  /* identifiers */
3849  ot->name = "Remove Mask Layer";
3850  ot->idname = "GPENCIL_OT_layer_mask_remove";
3851  ot->description = "Remove Layer Mask";
3852 
3854 
3855  /* callbacks */
3858 }
3859 
3861 {
3864  const int direction = RNA_enum_get(op->ptr, "type");
3865 
3866  /* sanity checks */
3867  if (ELEM(NULL, gpd, gpl)) {
3868  return OPERATOR_CANCELLED;
3869  }
3870  if (gpl->act_mask > 0) {
3871  bGPDlayer_Mask *mask = BLI_findlink(&gpl->mask_layers, gpl->act_mask - 1);
3872  if (mask != NULL) {
3873  BLI_assert(ELEM(direction, -1, 0, 1)); /* we use value below */
3874  if (BLI_listbase_link_move(&gpl->mask_layers, mask, direction)) {
3875  gpl->act_mask += direction;
3878  }
3879  }
3880  }
3881 
3882  return OPERATOR_FINISHED;
3883 }
3884 
3886 {
3887  static const EnumPropertyItem slot_move[] = {
3888  {GP_LAYER_MOVE_UP, "UP", 0, "Up", ""},
3889  {GP_LAYER_MOVE_DOWN, "DOWN", 0, "Down", ""},
3890  {0, NULL, 0, NULL, NULL},
3891  };
3892 
3893  /* identifiers */
3894  ot->name = "Move Grease Pencil Layer Mask";
3895  ot->idname = "GPENCIL_OT_layer_mask_move";
3896  ot->description = "Move the active Grease Pencil mask layer up/down in the list";
3897 
3898  /* api callbacks */
3901 
3902  /* flags */
3904 
3905  ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
3906 }
typedef float(TangentPoint)[2]
@ ADT_MERGECOPY_KEEP_DST
struct AnimData * BKE_animdata_copy(struct Main *bmain, struct AnimData *adt, int flag)
Definition: anim_data.c:275
void BKE_animdata_merge_copy(struct Main *bmain, struct ID *dst_id, struct ID *src_id, eAnimData_MergeCopy_Modes action_mode, bool fix_drivers)
Definition: anim_data.c:387
void BKE_fcurves_main_cb(struct Main *bmain, ID_FCurve_Edit_Callback func, void *user_data)
Definition: anim_data.c:1166
char * BKE_animsys_fix_rna_path_rename(struct ID *owner_id, char *old_path, const char *prefix, const char *oldName, const char *newName, int oldSubscript, int newSubscript, bool verify_paths)
Definition: anim_data.c:860
bool BKE_brush_delete(struct Main *bmain, struct Brush *brush)
Definition: brush.cc:575
void BKE_brush_gpencil_paint_presets(struct Main *bmain, struct ToolSettings *ts, bool reset)
Definition: brush.cc:1308
void BKE_gpencil_brush_preset_set(struct Main *bmain, struct Brush *brush, short type)
Definition: brush.cc:669
void BKE_brush_gpencil_weight_presets(struct Main *bmain, struct ToolSettings *ts, bool reset)
Definition: brush.cc:1529
void BKE_brush_gpencil_sculpt_presets(struct Main *bmain, struct ToolSettings *ts, bool reset)
Definition: brush.cc:1455
void BKE_brush_gpencil_vertex_presets(struct Main *bmain, struct ToolSettings *ts, bool reset)
Definition: brush.cc:1409
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:269
eContextObjectMode
Definition: BKE_context.h:103
@ CTX_MODE_WEIGHT_GPENCIL
Definition: BKE_context.h:122
@ CTX_MODE_VERTEX_GPENCIL
Definition: BKE_context.h:123
@ CTX_MODE_SCULPT_GPENCIL
Definition: BKE_context.h:121
@ CTX_MODE_PAINT_GPENCIL
Definition: BKE_context.h:119
struct bGPdata * CTX_data_gpencil_data(const bContext *C)
Definition: context.c:1445
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct ToolSettings * CTX_data_tool_settings(const bContext *C)
Definition: context.c:1282
#define CTX_DATA_END
Definition: BKE_context.h:278
enum eContextObjectMode CTX_data_mode_enum(const bContext *C)
Definition: context.c:1228
support for deformation groups and hooks.
struct MDeformWeight * BKE_defvert_find_index(const struct MDeformVert *dv, int defgroup)
struct MDeformWeight * BKE_defvert_ensure_index(struct MDeformVert *dv, int defgroup)
Definition: deform.c:748
void BKE_object_defgroup_unique_name(struct bDeformGroup *dg, struct Object *ob)
Definition: deform.c:692
void BKE_defvert_remove_group(struct MDeformVert *dvert, struct MDeformWeight *dw)
Definition: deform.c:804
float BKE_defvert_find_weight(const struct MDeformVert *dvert, int defgroup)
Definition: deform.c:704
void BKE_defvert_add_index_notest(struct MDeformVert *dv, int defgroup, float weight)
Definition: deform.c:779
#define DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar)
#define DRIVER_TARGETS_LOOPER_END
void BKE_gpencil_stroke_select_index_set(struct bGPdata *gpd, struct bGPDstroke *gps)
Definition: gpencil.c:1155
struct bGPDframe * BKE_gpencil_frame_addnew(struct bGPDlayer *gpl, int cframe)
Definition: gpencil.c:514
void BKE_gpencil_layer_active_set(struct bGPdata *gpd, struct bGPDlayer *active)
Definition: gpencil.c:1601
struct bGPDlayer_Mask * BKE_gpencil_layer_mask_named_get(struct bGPDlayer *gpl, const char *name)
Definition: gpencil.c:1427
void BKE_gpencil_free_data(struct bGPdata *gpd, bool free_all)
Definition: gpencil.c:479
void BKE_gpencil_layer_mask_sort(struct bGPdata *gpd, struct bGPDlayer *gpl)
Definition: gpencil.c:1484
struct bGPDstroke * BKE_gpencil_stroke_duplicate(struct bGPDstroke *gps_src, bool dup_points, bool dup_curve)
Definition: gpencil.c:855
struct bGPDlayer * BKE_gpencil_layer_active_get(struct bGPdata *gpd)
Definition: gpencil.c:1558
struct bGPDframe * BKE_gpencil_frame_addcopy(struct bGPDlayer *gpl, int cframe)
Definition: gpencil.c:567
void BKE_gpencil_free_stroke_weights(struct bGPDstroke *gps)
Definition: gpencil.c:361
int BKE_gpencil_object_material_ensure(struct Main *bmain, struct Object *ob, struct Material *material)
Definition: gpencil.c:1720
void BKE_gpencil_layer_mask_sort_all(struct bGPdata *gpd)
Definition: gpencil.c:1499
struct bGPDlayer * BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src, bool dup_frames, bool dup_strokes)
void BKE_gpencil_stroke_select_index_reset(struct bGPDstroke *gps)
Definition: gpencil.c:1161
void BKE_gpencil_layer_mask_remove(struct bGPDlayer *gpl, struct bGPDlayer_Mask *mask)
Definition: gpencil.c:1446
struct bGPDlayer_Mask * BKE_gpencil_layer_mask_add(struct bGPDlayer *gpl, const char *name)
Definition: gpencil.c:1435
struct bGPDlayer * BKE_gpencil_layer_addnew(struct bGPdata *gpd, const char *name, bool setactive, bool add_to_header)
Definition: gpencil.c:621
bool BKE_gpencil_layer_is_editable(const struct bGPDlayer *gpl)
bool BKE_gpencil_layer_frame_delete(struct bGPDlayer *gpl, struct bGPDframe *gpf)
Definition: gpencil.c:1396
int BKE_gpencil_object_material_index_get(struct Object *ob, struct Material *ma)
Definition: gpencil.c:2199
void BKE_gpencil_layer_mask_cleanup(struct bGPdata *gpd, struct bGPDlayer *gpl)
Definition: gpencil.c:1516
struct bGPDlayer * BKE_gpencil_layer_named_get(struct bGPdata *gpd, const char *name)
Definition: gpencil.c:1419
struct bGPDframe * BKE_gpencil_layer_frame_get(struct bGPDlayer *gpl, int cframe, eGP_GetFrame_Mode addnew)
Definition: gpencil.c:1232
struct bGPdata * BKE_gpencil_data_addnew(struct Main *bmain, const char name[])
Definition: gpencil.c:705
void BKE_gpencil_layer_transform_matrix_get(const struct Depsgraph *depsgraph, struct Object *obact, struct bGPDlayer *gpl, float diff_mat[4][4])
void BKE_gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl)
Definition: gpencil.c:1653
@ GP_GETFRAME_ADD_NEW
Definition: BKE_gpencil.h:341
struct GpencilModifierData * BKE_gpencil_modifiers_findby_type(struct Object *ob, GpencilModifierType type)
const GpencilModifierTypeInfo * BKE_gpencil_modifier_get_info(GpencilModifierType type)
bool BKE_id_is_editable(const struct Main *bmain, const struct ID *id)
void id_us_min(struct ID *id)
Definition: lib_id.c:313
struct ID * BKE_libblock_find_name(struct Main *bmain, short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: lib_id.c:1297
void BKE_id_free_us(struct Main *bmain, void *idv) ATTR_NONNULL()
General operations, lookup, etc. for materials.
struct MaterialGPencilStyle * BKE_gpencil_material_settings(struct Object *ob, short act)
Definition: material.c:805
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:687
struct Material * BKE_gpencil_material(struct Object *ob, short act)
Definition: material.c:795
short * BKE_object_material_len_p(struct Object *ob)
Definition: material.c:344
General operations, lookup, etc. for blender objects.
void BKE_paint_brush_set(struct Paint *paint, struct Brush *br)
Definition: paint.c:617
void BKE_paint_toolslots_brush_validate(struct Main *bmain, struct Paint *paint)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
#define BLI_assert(a)
Definition: BLI_assert.h:46
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:298
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:302
GHash * BLI_ghash_str_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
#define GHASH_ITER(gh_iter_, ghash_)
Definition: BLI_ghash.h:321
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:710
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:863
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:60
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:239
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
Definition: BLI_listbase.h:348
struct LinkData * BLI_genericNodeN(void *data)
Definition: listbase.c:842
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:301
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
#define LISTBASE_FOREACH_BACKWARD_MUTABLE(type, var, list)
Definition: BLI_listbase.h:362
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
void void void bool BLI_listbase_link_move(ListBase *listbase, void *vlink, int step) ATTR_NONNULL()
Definition: listbase.c:405
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:340
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float interpf(float a, float b, float t)
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:3254
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:926
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
void invert_m4_m4_safe_ortho(float Ainv[4][4], const float A[4][4])
Definition: math_matrix.c:3188
void unit_m4(float m[4][4])
Definition: rct.c:1090
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void invert_m3_m3_safe_ortho(float Ainv[3][3], const float A[3][3])
Definition: math_matrix.c:3199
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:897
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE bool equals_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void zero_v3(float r[3])
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
bool BLI_uniquename(struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_len)
Definition: string_utils.c:309
#define UNUSED(x)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define STREQ(a, b)
#define DATA_(msgid)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:771
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:834
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
#define MAX_ID_NAME
Definition: DNA_ID.h:337
@ ID_MA
Definition: DNA_ID_enums.h:51
@ GP_BRUSH_MATERIAL_PINNED
@ GP_BRUSH_PRESET_DRAW_WEIGHT
@ GP_BRUSH_PRESET_VERTEX_DRAW
@ GP_BRUSH_PRESET_VERTEX_REPLACE
@ GP_BRUSH_PRESET_SMOOTH_STROKE
@ GP_BRUSH_PRESET_AIRBRUSH
@ GP_BRUSH_PRESET_TINT
@ GP_BRUSH_PRESET_CLONE_STROKE
@ GP_BRUSH_PRESET_UNKNOWN
@ eGpencilModifierType_Lattice
@ GP_STROKE_NOFILL
@ GP_STROKE_SELECT
#define GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)
@ GP_LAYER_LOCKED
@ GP_LAYER_ACTIVE
@ GP_LAYER_HIDE
@ GP_LAYER_USE_LIGHTS
@ GP_LAYER_ONIONSKIN
@ GP_FRAME_SELECT
@ GP_DATA_ANNOTATIONS
@ GP_DATA_STROKE_EDITMODE
#define GPENCIL_ANY_MODE(gpd)
@ eGplBlendMode_Regular
@ GP_SPOINT_SELECT
@ GP_MATERIAL_LOCKED
@ GP_MATERIAL_HIDE
@ OB_MODE_EDIT_GPENCIL
@ OB_MODE_WEIGHT_GPENCIL
@ OB_MODE_SCULPT_GPENCIL
@ OB_MODE_PAINT_GPENCIL
Object is a sort of wrapper for general info.
@ OB_GPENCIL
#define DG_LOCK_WEIGHT
@ OPERATOR_CANCELLED
@ OPERATOR_INTERFACE
@ OPERATOR_FINISHED
struct GpencilModifierData * ED_object_gpencil_modifier_add(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob, const char *name, int type)
void ED_object_base_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *ob)
Definition: object_add.cc:2190
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
@ PROP_HIDDEN
Definition: RNA_types.h:216
#define C
Definition: RandGen.cpp:25
struct uiLayout * UI_popup_menu_layout(uiPopupMenu *pup)
void uiItemsEnumO(uiLayout *layout, const char *opname, const char *propname)
void UI_popup_menu_end(struct bContext *C, struct uiPopupMenu *pup)
uiPopupMenu * UI_popup_menu_begin(struct bContext *C, const char *title, int icon) ATTR_NONNULL()
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_BRUSH
Definition: WM_types.h:335
#define ND_OB_ACTIVE
Definition: WM_types.h:388
#define ND_DATA
Definition: WM_types.h:456
#define ND_SPACE_PROPERTIES
Definition: WM_types.h:472
#define NC_SCENE
Definition: WM_types.h:328
#define ND_LAYER_CONTENT
Definition: WM_types.h:402
#define NA_EDITED
Definition: WM_types.h:523
#define NC_GPENCIL
Definition: WM_types.h:349
#define NA_SELECTED
Definition: WM_types.h:528
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: avxb.h:154
ATTR_WARN_UNUSED_RESULT const BMVert * v
Scene scene
const Depsgraph * depsgraph
void * user_data
int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
static void gpencil_joined_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data)
void GPENCIL_OT_layer_change(wmOperatorType *ot)
void GPENCIL_OT_stroke_arrange(wmOperatorType *ot)
static int gpencil_layer_mask_remove_exec(bContext *C, wmOperator *UNUSED(op))
static int gpencil_layer_add_exec(bContext *C, wmOperator *op)
Definition: gpencil_data.c:195
void GPENCIL_OT_vertex_group_smooth(wmOperatorType *ot)
@ GP_LAYER_MOVE_DOWN
Definition: gpencil_data.c:372
@ GP_LAYER_MOVE_UP
Definition: gpencil_data.c:371
static int gpencil_material_select_exec(bContext *C, wmOperator *op)
static bool gpencil_frame_is_equal(const bGPDframe *gpf_a, const bGPDframe *gpf_b)
Definition: gpencil_data.c:870
static int gpencil_material_set_exec(bContext *C, wmOperator *op)
static bool gpencil_active_layer_annotation_poll(bContext *C)
Definition: gpencil_data.c:347
void GPENCIL_OT_layer_remove(wmOperatorType *ot)
Definition: gpencil_data.c:333
struct tJoinGPencil_AdtFixData tJoinGPencil_AdtFixData
void GPENCIL_OT_vertex_group_invert(wmOperatorType *ot)
static int gpencil_isolate_layer_exec(bContext *C, wmOperator *op)
@ GP_LAYER_COPY_OBJECT_ACT_FRAME
Definition: gpencil_data.c:518
@ GP_LAYER_COPY_OBJECT_ALL_FRAME
Definition: gpencil_data.c:517
void GPENCIL_OT_layer_annotation_move(wmOperatorType *ot)
Definition: gpencil_data.c:425
static int gpencil_frame_clean_loose_exec(bContext *C, wmOperator *op)
Definition: gpencil_data.c:786
static int gpencil_hide_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_material_reveal(wmOperatorType *ot)
void GPENCIL_OT_layer_annotation_remove(wmOperatorType *ot)
Definition: gpencil_data.c:355
void GPENCIL_OT_frame_duplicate(wmOperatorType *ot)
Definition: gpencil_data.c:677
void GPENCIL_OT_layer_isolate(wmOperatorType *ot)
static int gpencil_materials_copy_to_object_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_lock_all(wmOperatorType *ot)
static int gpencil_frame_clean_duplicate_exec(bContext *C, wmOperator *op)
Definition: gpencil_data.c:953
static int gpencil_brush_reset_all_exec(bContext *C, wmOperator *UNUSED(op))
@ GP_LAYER_MERGE_ALL
@ GP_LAYER_MERGE_ACTIVE
static int gpencil_layer_change_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
static int gpencil_material_hide_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_layer_mask_remove(wmOperatorType *ot)
static bool gpencil_materials_copy_to_object_poll(bContext *C)
#define SELECTED
void GPENCIL_OT_stroke_change_color(wmOperatorType *ot)
static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
void GPENCIL_OT_material_set(wmOperatorType *ot)
static bool gpencil_data_unlink_poll(bContext *C)
Definition: gpencil_data.c:140
static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_vertex_group_normalize_all(wmOperatorType *ot)
@ GP_FRAME_DUP_ALL
Definition: gpencil_data.c:644
@ GP_FRAME_DUP_ACTIVE
Definition: gpencil_data.c:643
static bool gpencil_data_add_poll(bContext *C)
Definition: gpencil_data.c:78
static int gpencil_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
static bool gpencil_add_annotation_poll(bContext *C)
Definition: gpencil_data.c:259
void GPENCIL_OT_material_lock_unused(wmOperatorType *ot)
void GPENCIL_OT_material_select(wmOperatorType *ot)
static int gpencil_brush_reset_exec(bContext *C, wmOperator *UNUSED(op))
void GPENCIL_OT_frame_clean_fill(wmOperatorType *ot)
Definition: gpencil_data.c:762
static int gpencil_vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
static int gpencil_layer_duplicate_object_exec(bContext *C, wmOperator *op)
Definition: gpencil_data.c:538
void GPENCIL_OT_brush_reset_all(wmOperatorType *ot)
void GPENCIL_OT_annotation_add(wmOperatorType *ot)
Definition: gpencil_data.c:124
static int gpencil_material_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
static bool gpencil_active_material_poll(bContext *C)
static int gpencil_layer_move_exec(bContext *C, wmOperator *op)
Definition: gpencil_data.c:375
static int gpencil_merge_layer_exec(bContext *C, wmOperator *op)
static void gpencil_reveal_select_frame(bContext *C, bGPDframe *frame, bool select)
void GPENCIL_OT_vertex_group_normalize(wmOperatorType *ot)
void GPENCIL_OT_layer_add(wmOperatorType *ot)
Definition: gpencil_data.c:245
void GPENCIL_OT_layer_mask_move(wmOperatorType *ot)
static int gpencil_data_unlink_exec(bContext *C, wmOperator *op)
Definition: gpencil_data.c:156
static int gpencil_material_reveal_exec(bContext *C, wmOperator *UNUSED(op))
void GPENCIL_OT_materials_copy_to_object(wmOperatorType *ot)
static int gpencil_vertex_group_normalize_exec(bContext *C, wmOperator *op)
@ GP_STROKE_MOVE_TOP
@ GP_STROKE_MOVE_BOTTOM
@ GP_STROKE_MOVE_UP
@ GP_STROKE_MOVE_DOWN
void GPENCIL_OT_layer_mask_add(wmOperatorType *ot)
void GPENCIL_OT_reveal(wmOperatorType *ot)
void GPENCIL_OT_layer_duplicate(wmOperatorType *ot)
Definition: gpencil_data.c:492
void GPENCIL_OT_vertex_group_assign(wmOperatorType *ot)
static int gpencil_frame_clean_fill_exec(bContext *C, wmOperator *op)
Definition: gpencil_data.c:706
static int gpencil_frame_duplicate_exec(bContext *C, wmOperator *op)
Definition: gpencil_data.c:647
void GPENCIL_OT_layer_merge(wmOperatorType *ot)
static bool gpencil_vertex_group_weight_poll(bContext *C)
static int gpencil_vertex_group_smooth_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_unlock_all(wmOperatorType *ot)
void GPENCIL_OT_material_lock_all(wmOperatorType *ot)
static int gpencil_stroke_change_color_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_data_unlink(wmOperatorType *ot)
Definition: gpencil_data.c:176
static int gpencil_material_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
static int gpencil_layer_copy_exec(bContext *C, wmOperator *op)
Definition: gpencil_data.c:453
void GPENCIL_OT_brush_reset(wmOperatorType *ot)
static int gpencil_layer_remove_exec(bContext *C, wmOperator *op)
Definition: gpencil_data.c:279
void GPENCIL_OT_set_active_material(wmOperatorType *ot)
@ GP_FRAME_CLEAN_FILL_ALL
Definition: gpencil_data.c:703
@ GP_FRAME_CLEAN_FILL_ACTIVE
Definition: gpencil_data.c:702
static int gpencil_layer_active_exec(bContext *C, wmOperator *op)
static int gpencil_set_active_material_exec(bContext *C, wmOperator *op)
static int gpencil_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
static int gpencil_layer_mask_move_exec(bContext *C, wmOperator *op)
static int gpencil_material_lock_unsused_exec(bContext *C, wmOperator *UNUSED(op))
static int gpencil_layer_mask_add_exec(bContext *C, wmOperator *op)
static int gpencil_vertex_group_normalize_all_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_frame_clean_loose(wmOperatorType *ot)
Definition: gpencil_data.c:844
void GPENCIL_OT_hide(wmOperatorType *ot)
void GPENCIL_OT_material_isolate(wmOperatorType *ot)
static int gpencil_vertex_group_remove_from_exec(bContext *C, wmOperator *UNUSED(op))
void GPENCIL_OT_vertex_group_select(wmOperatorType *ot)
static int gpencil_vertex_group_assign_exec(bContext *C, wmOperator *UNUSED(op))
static bool gpencil_layer_duplicate_object_poll(bContext *C)
Definition: gpencil_data.c:521
static int gpencil_data_add_exec(bContext *C, wmOperator *op)
Definition: gpencil_data.c:86
void GPENCIL_OT_vertex_group_deselect(wmOperatorType *ot)
void GPENCIL_OT_material_hide(wmOperatorType *ot)
static int gpencil_vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
void GPENCIL_OT_layer_duplicate_object(wmOperatorType *ot)
Definition: gpencil_data.c:609
static Brush * gpencil_brush_get_first_by_mode(Main *bmain, Paint *UNUSED(paint), const enum eContextObjectMode mode, char tool)
void GPENCIL_OT_layer_annotation_add(wmOperatorType *ot)
Definition: gpencil_data.c:264
void GPENCIL_OT_layer_move(wmOperatorType *ot)
Definition: gpencil_data.c:402
static int gpencil_vertex_group_invert_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_material_unlock_all(wmOperatorType *ot)
static int gpencil_layer_change_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_lock_layer(wmOperatorType *ot)
@ GP_LAYER_DUPLICATE_ALL
Definition: gpencil_data.c:449
@ GP_LAYER_DUPLICATE_EMPTY
Definition: gpencil_data.c:450
bool ED_gpencil_add_lattice_modifier(const bContext *C, ReportList *reports, Object *ob, Object *ob_latt)
static bool gpencil_reveal_poll(bContext *C)
static void gpencil_brush_delete_mode_brushes(Main *bmain, Paint *paint, const enum eContextObjectMode mode)
static int gpencil_material_isolate_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_vertex_group_remove_from(wmOperatorType *ot)
void GPENCIL_OT_frame_clean_duplicate(wmOperatorType *ot)
Definition: gpencil_data.c:994
static bool gpencil_vertex_group_poll(bContext *C)
static void apply_layer_settings(bGPDlayer *gpl)
void GPENCIL_OT_layer_active(wmOperatorType *ot)
static int gpencil_reveal_exec(bContext *C, wmOperator *op)
const struct EnumPropertyItem * ED_gpencil_material_enum_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free)
#define GP_EDITABLE_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
const struct EnumPropertyItem * ED_gpencil_layers_with_new_enum_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free)
bool gpencil_active_layer_poll(struct bContext *C)
#define GP_EDITABLE_STROKES_END(gpstroke_iter)
bool gpencil_add_poll(struct bContext *C)
void ED_gpencil_vgroup_deselect(bContext *C, Object *ob)
bool ED_gpencil_stroke_material_editable(Object *ob, const bGPDlayer *gpl, const bGPDstroke *gps)
void ED_gpencil_vgroup_select(bContext *C, Object *ob)
void ED_gpencil_vgroup_remove(bContext *C, Object *ob)
bGPdata * ED_annotation_data_get_active(const bContext *C)
void ED_gpencil_layer_merge(bGPdata *gpd, bGPDlayer *gpl_src, bGPDlayer *gpl_dst, const bool reverse)
bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps)
bGPdata * ED_gpencil_data_get_active(const bContext *C)
bGPdata ** ED_annotation_data_get_pointers(const bContext *C, PointerRNA *r_ptr)
void ED_gpencil_vgroup_assign(bContext *C, Object *ob, float weight)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
Definition: rna_access.c:5116
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4957
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3836
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3687
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3597
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3830
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3783
const EnumPropertyItem DummyRNA_DEFAULT_items[]
Definition: rna_rna.c:31
char gpencil_weight_tool
char gpencil_vertex_tool
struct BrushGpencilSettings * gpencil_settings
char gpencil_sculpt_tool
char gpencil_tool
ListBase variables
char * rna_path
ChannelDriver * driver
void(* bakeModifier)(struct Main *bmain, struct Depsgraph *depsgraph, struct GpencilModifierData *md, struct Object *ob)
Definition: DNA_ID.h:368
void * next
Definition: DNA_ID.h:369
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
struct MDeformWeight * dw
unsigned int def_nr
Definition: BKE_main.h:121
ListBase brushes
Definition: BKE_main.h:193
struct MaterialGPencilStyle * gp_style
float loc[3]
float obmat[4][4]
struct AnimData * adt
void * data
struct Brush * brush
struct RenderData r
GpWeightPaint * gp_weightpaint
GpPaint * gp_paint
GpSculptPaint * gp_sculptpaint
GpVertexPaint * gp_vertexpaint
struct bGPDframe * next
ListBase strokes
char info[128]
float tintcolor[4]
struct bGPDlayer * next
bGPDframe * actframe
float layer_mat[4][4]
float layer_invmat[4][4]
ListBase frames
ListBase mask_layers
float rotation[3]
float scale[3]
float location[3]
struct bGPDlayer * prev
float vert_color[4]
struct bGPDstroke * prev
bGPDspoint * points
float uv_translation[2]
float aspect_ratio[2]
float vert_color_fill[4]
struct bGPDstroke * next
ListBase vertex_group_names
ListBase layers
int vertex_group_active_index
struct AnimData * adt
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct ReportList * reports
struct wmOperatorType * type
struct PointerRNA * ptr
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3479