Blender  V3.3
object_gpencil_modifier.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2018 Blender Foundation. All rights reserved. */
3 
8 #include <math.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #include "MEM_guardedalloc.h"
14 
15 #include "DNA_defaults.h"
17 #include "DNA_gpencil_types.h"
18 #include "DNA_object_types.h"
19 #include "DNA_scene_types.h"
20 
21 #include "BLI_listbase.h"
22 #include "BLI_string_utf8.h"
23 #include "BLI_string_utils.h"
24 #include "BLI_utildefines.h"
25 
26 #include "BKE_context.h"
27 #include "BKE_gpencil.h"
28 #include "BKE_gpencil_modifier.h"
29 #include "BKE_lib_id.h"
30 #include "BKE_main.h"
31 #include "BKE_object.h"
32 #include "BKE_report.h"
33 
34 #include "DEG_depsgraph.h"
35 #include "DEG_depsgraph_build.h"
36 #include "DEG_depsgraph_query.h"
37 
38 #include "RNA_access.h"
39 #include "RNA_define.h"
40 #include "RNA_enum_types.h"
41 #include "RNA_prototypes.h"
42 
43 #include "ED_object.h"
44 #include "ED_screen.h"
45 
46 #include "BLT_translation.h"
47 
48 #include "UI_interface.h"
49 
50 #include "WM_api.h"
51 #include "WM_types.h"
52 
53 #include "object_intern.h"
54 
55 /******************************** API ****************************/
56 
58  ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type)
59 {
60  GpencilModifierData *new_md = NULL;
62 
63  if (ob->type != OB_GPENCIL) {
64  BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
65  return NULL;
66  }
67 
70  BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
71  return NULL;
72  }
73  }
74 
75  /* get new modifier data to add */
77 
78  BLI_addtail(&ob->greasepencil_modifiers, new_md);
79 
80  if (name) {
81  BLI_strncpy_utf8(new_md->name, name, sizeof(new_md->name));
82  }
83 
84  /* make sure modifier data has unique name */
86 
87  /* Enable edit mode visible by default. */
90  }
91 
92  bGPdata *gpd = ob->data;
94 
97 
98  return new_md;
99 }
100 
102  Object *ob,
104  bool *UNUSED(r_sort_depsgraph))
105 {
106  /* It seems on rapid delete it is possible to
107  * get called twice on same modifier, so make
108  * sure it is in list. */
109  if (BLI_findindex(&ob->greasepencil_modifiers, md) == -1) {
110  return false;
111  }
112 
114 
118 
119  return true;
120 }
121 
123  Main *bmain,
124  Object *ob,
126 {
127  bool sort_depsgraph = false;
128  bool ok;
129 
130  ok = gpencil_object_modifier_remove(bmain, ob, md, &sort_depsgraph);
131 
132  if (!ok) {
133  BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name);
134  return false;
135  }
136 
139 
140  return true;
141 }
142 
144 {
146  bool sort_depsgraph = false;
147 
148  if (!md) {
149  return;
150  }
151 
152  while (md) {
153  GpencilModifierData *next_md;
154 
155  next_md = md->next;
156 
157  gpencil_object_modifier_remove(bmain, ob, md, &sort_depsgraph);
158 
159  md = next_md;
160  }
161 
164 }
165 
167  Object *ob,
169 {
170  if (md->prev) {
173  }
174 
175  return true;
176 }
177 
179  Object *ob,
181 {
182  if (md->next) {
185  }
186 
187  return true;
188 }
189 
191  Object *ob,
193  const int index)
194 {
195  BLI_assert(md != NULL);
196  BLI_assert(index >= 0);
197  if (index >= BLI_listbase_count(&ob->greasepencil_modifiers)) {
198  BKE_report(reports, RPT_WARNING, "Cannot move modifier beyond the end of the stack");
199  return false;
200  }
201 
202  int md_index = BLI_findindex(&ob->greasepencil_modifiers, md);
203  BLI_assert(md_index != -1);
204  if (md_index < index) {
205  /* Move modifier down in list. */
206  for (; md_index < index; md_index++) {
207  if (!ED_object_gpencil_modifier_move_down(reports, ob, md)) {
208  break;
209  }
210  }
211  }
212  else {
213  /* Move modifier up in list. */
214  for (; md_index > index; md_index--) {
215  if (!ED_object_gpencil_modifier_move_up(reports, ob, md)) {
216  break;
217  }
218  }
219  }
220 
223 
224  return true;
225 }
226 
228  ReportList *reports, Main *bmain, Depsgraph *depsgraph, Object *ob, GpencilModifierData *md)
229 {
231 
232  if (mti->isDisabled && mti->isDisabled(md, 0)) {
233  BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
234  return false;
235  }
236 
237  if (ob->type == OB_GPENCIL) {
238  if (ELEM(NULL, ob, ob->data)) {
239  return false;
240  }
241  if (mti->bakeModifier == NULL) {
242  BKE_report(reports, RPT_ERROR, "Not implemented");
243  return false;
244  }
245  mti->bakeModifier(bmain, depsgraph, md, ob);
247  }
248  else {
249  BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
250  return false;
251  }
252 
253  return true;
254 }
255 
257  ReportList *reports,
259  Object *ob,
261  int UNUSED(mode))
262 {
263 
264  if (ob->type == OB_GPENCIL) {
265  if (ob->mode != OB_MODE_OBJECT) {
266  BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in paint, sculpt or edit mode");
267  return false;
268  }
269 
270  if (((ID *)ob->data)->us > 1) {
271  BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
272  return false;
273  }
274  }
275  else if (((ID *)ob->data)->us > 1) {
276  BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
277  return false;
278  }
279 
280  if (md != ob->greasepencil_modifiers.first) {
281  BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
282  }
283 
284  if (!gpencil_modifier_apply_obdata(reports, bmain, depsgraph, ob, md)) {
285  return false;
286  }
287 
290 
291  return true;
292 }
293 
295 {
296  GpencilModifierData *nmd;
299 
302  BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
303  return false;
304  }
305  }
306 
307  nmd = BKE_gpencil_modifier_new(md->type);
311 
313 
314  return true;
315 }
316 
318 {
322 }
323 
324 /************************ add modifier operator *********************/
325 
327 {
328  Main *bmain = CTX_data_main(C);
331  int type = RNA_enum_get(op->ptr, "type");
332 
333  if (!ED_object_gpencil_modifier_add(op->reports, bmain, scene, ob, NULL, type)) {
334  return OPERATOR_CANCELLED;
335  }
336 
338 
339  return OPERATOR_FINISHED;
340 }
341 
344  PropertyRNA *UNUSED(prop),
345  bool *r_free)
346 {
348  EnumPropertyItem *item = NULL;
349  const EnumPropertyItem *md_item, *group_item = NULL;
350  const GpencilModifierTypeInfo *mti;
351  int totitem = 0, a;
352 
353  if (!ob) {
355  }
356 
359  if (md_item->identifier[0]) {
360  mti = BKE_gpencil_modifier_get_info(md_item->value);
361 
363  continue;
364  }
365  }
366  else {
367  group_item = md_item;
368  md_item = NULL;
369 
370  continue;
371  }
372 
373  if (group_item) {
374  RNA_enum_item_add(&item, &totitem, group_item);
375  group_item = NULL;
376  }
377 
378  RNA_enum_item_add(&item, &totitem, md_item);
379  }
380 
381  RNA_enum_item_end(&item, &totitem);
382  *r_free = true;
383 
384  return item;
385 }
386 
388 {
389  PropertyRNA *prop;
390 
391  /* identifiers */
392  ot->name = "Add Modifier";
393  ot->description = "Add a procedural operation/effect to the active grease pencil object";
394  ot->idname = "OBJECT_OT_gpencil_modifier_add";
395 
396  /* api callbacks */
400 
401  /* flags */
403 
404  /* properties */
405  prop = RNA_def_enum(ot->srna,
406  "type",
409  "Type",
410  "");
412  ot->prop = prop;
413 }
414 
415 /********** generic functions for operators using mod names and data context *********************/
416 
418  StructRNA *rna_type,
419  int obtype_flag,
420  const bool is_liboverride_allowed)
421 {
422  Main *bmain = CTX_data_main(C);
423  PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
425  GpencilModifierData *mod = ptr.data; /* May be NULL. */
426 
427  if (!ob || !BKE_id_is_editable(bmain, &ob->id)) {
428  return false;
429  }
430  if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) {
431  return false;
432  }
433  if (ptr.owner_id && !BKE_id_is_editable(bmain, ptr.owner_id)) {
434  return false;
435  }
436 
439  C, "Cannot edit modifiers coming from linked data in a library override");
440  return false;
441  }
442 
443  return true;
444 }
445 
447 {
448  return gpencil_edit_modifier_poll_generic(C, &RNA_GpencilModifier, 0, false);
449 }
450 
451 /* Used by operators performing actions allowed also on modifiers from the overridden linked object
452  * (not only from added 'local' ones). */
454 {
455  return gpencil_edit_modifier_poll_generic(C, &RNA_GpencilModifier, 0, true);
456 }
457 
459 {
460  PropertyRNA *prop = RNA_def_string(
461  ot->srna, "modifier", NULL, MAX_NAME, "Modifier", "Name of the modifier to edit");
463 }
464 
466 {
468  ot->srna, "report", false, "Report", "Create a notification after the operation");
470 }
471 
479  wmOperator *op,
480  const wmEvent *event,
481  int *r_retval)
482 {
483  if (RNA_struct_property_is_set(op->ptr, "modifier")) {
484  return true;
485  }
486 
487  PointerRNA ctx_ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_GpencilModifier);
488  if (ctx_ptr.data != NULL) {
489  GpencilModifierData *md = ctx_ptr.data;
490  RNA_string_set(op->ptr, "modifier", md->name);
491  return true;
492  }
493 
494  /* Check the custom data of panels under the mouse for a modifier. */
495  if (event != NULL) {
497 
498  if (!(panel_ptr == NULL || RNA_pointer_is_null(panel_ptr))) {
499  if (RNA_struct_is_a(panel_ptr->type, &RNA_GpencilModifier)) {
500  GpencilModifierData *md = panel_ptr->data;
501  RNA_string_set(op->ptr, "modifier", md->name);
502  return true;
503  }
504 
505  BLI_assert(r_retval != NULL); /* We need the return value in this case. */
506  if (r_retval != NULL) {
508  }
509  return false;
510  }
511  }
512 
513  if (r_retval != NULL) {
514  *r_retval = OPERATOR_CANCELLED;
515  }
516  return false;
517 }
518 
520  Object *ob,
521  int type)
522 {
523  if (ob == NULL) {
524  return NULL;
525  }
526 
527  char modifier_name[MAX_NAME];
529  RNA_string_get(op->ptr, "modifier", modifier_name);
530 
532 
533  if (md && type != 0 && md->type != type) {
534  md = NULL;
535  }
536 
537  return md;
538 }
539 
540 /************************ remove modifier operator *********************/
541 
543 {
544  Main *bmain = CTX_data_main(C);
547 
548  if (md == NULL) {
549  return OPERATOR_CANCELLED;
550  }
551 
552  /* Store name temporarily for report. */
553  char name[MAX_NAME];
554  strcpy(name, md->name);
555 
556  if (!ED_object_gpencil_modifier_remove(op->reports, bmain, ob, md)) {
557  return OPERATOR_CANCELLED;
558  }
559 
561 
562  if (RNA_boolean_get(op->ptr, "report")) {
563  BKE_reportf(op->reports, RPT_INFO, "Removed modifier: %s", name);
564  }
565 
566  return OPERATOR_FINISHED;
567 }
568 
570 {
571  int retval;
572  if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) {
573  return gpencil_modifier_remove_exec(C, op);
574  }
575  return retval;
576 }
577 
579 {
580  ot->name = "Remove Grease Pencil Modifier";
581  ot->description = "Remove a modifier from the active grease pencil object";
582  ot->idname = "OBJECT_OT_gpencil_modifier_remove";
583 
587 
588  /* flags */
592 }
593 
594 /************************ move up modifier operator *********************/
595 
597 {
600 
601  if (!md || !ED_object_gpencil_modifier_move_up(op->reports, ob, md)) {
602  return OPERATOR_CANCELLED;
603  }
604 
607 
608  return OPERATOR_FINISHED;
609 }
610 
612 {
613  int retval;
614  if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) {
615  return gpencil_modifier_move_up_exec(C, op);
616  }
617  return retval;
618 }
619 
621 {
622  ot->name = "Move Up Modifier";
623  ot->description = "Move modifier up in the stack";
624  ot->idname = "OBJECT_OT_gpencil_modifier_move_up";
625 
629 
630  /* flags */
633 }
634 
635 /************************ move down modifier operator *********************/
636 
638 {
641 
642  if (!md || !ED_object_gpencil_modifier_move_down(op->reports, ob, md)) {
643  return OPERATOR_CANCELLED;
644  }
645 
648 
649  return OPERATOR_FINISHED;
650 }
651 
653 {
654  int retval;
655  if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) {
657  }
658  return retval;
659 }
660 
662 {
663  ot->name = "Move Down Modifier";
664  ot->description = "Move modifier down in the stack";
665  ot->idname = "OBJECT_OT_gpencil_modifier_move_down";
666 
670 
671  /* flags */
674 }
675 
676 /* ************************* Move to Index Gpencil Modifier Operator ************************* */
677 
679 {
682  int index = RNA_int_get(op->ptr, "index");
683  if (!(md && ED_object_gpencil_modifier_move_to_index(op->reports, ob, md, index))) {
684  return OPERATOR_CANCELLED;
685  }
686 
687  return OPERATOR_FINISHED;
688 }
689 
691 {
692  int retval;
693  if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) {
695  }
696  return retval;
697 }
698 
700 {
701  ot->name = "Move Active Modifier to Index";
702  ot->idname = "OBJECT_OT_gpencil_modifier_move_to_index";
703  ot->description =
704  "Change the modifier's position in the list so it evaluates after the set number of "
705  "others";
706 
710 
711  /* flags */
714  RNA_def_int(
715  ot->srna, "index", 0, 0, INT_MAX, "Index", "The index to move the modifier to", 0, INT_MAX);
716 }
717 
718 /************************ apply modifier operator *********************/
719 
721 {
722  Main *bmain = CTX_data_main(C);
726  int apply_as = RNA_enum_get(op->ptr, "apply_as");
727  const bool do_report = RNA_boolean_get(op->ptr, "report");
728 
729  if (md == NULL) {
730  return OPERATOR_CANCELLED;
731  }
732 
733  int reports_len;
734  char name[MAX_NAME];
735  if (do_report) {
736  reports_len = BLI_listbase_count(&op->reports->list);
737  strcpy(name, md->name); /* Store name temporarily since the modifier is removed. */
738  }
739 
740  if (!ED_object_gpencil_modifier_apply(bmain, op->reports, depsgraph, ob, md, apply_as)) {
741  return OPERATOR_CANCELLED;
742  }
743 
746 
747  if (do_report) {
748  /* Only add this report if the operator didn't cause another one. The purpose here is
749  * to alert that something happened, and the previous report will do that anyway. */
750  if (BLI_listbase_count(&op->reports->list) == reports_len) {
751  BKE_reportf(op->reports, RPT_INFO, "Applied modifier: %s", name);
752  }
753  }
754 
755  return OPERATOR_FINISHED;
756 }
757 
759 {
760  int retval;
761  if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) {
762  return gpencil_modifier_apply_exec(C, op);
763  }
764  return retval;
765 }
766 
768  {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
770  "SHAPE",
771  0,
772  "New Shape",
773  "Apply deform-only modifier to a new shape on this object"},
774  {0, NULL, 0, NULL, NULL},
775 };
776 
778 {
779  ot->name = "Apply Modifier";
780  ot->description = "Apply modifier and remove from the stack";
781  ot->idname = "OBJECT_OT_gpencil_modifier_apply";
782 
786 
787  /* flags */
789 
791  "apply_as",
794  "Apply As",
795  "How to apply the modifier to the geometry");
798 }
799 
800 /************************ copy modifier operator *********************/
801 
803 {
806 
807  if (!md || !ED_object_gpencil_modifier_copy(op->reports, ob, md)) {
808  return OPERATOR_CANCELLED;
809  }
810 
813 
814  return OPERATOR_FINISHED;
815 }
816 
818 {
819  int retval;
820  if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) {
821  return gpencil_modifier_copy_exec(C, op);
822  }
823  return retval;
824 }
825 
827 {
828  ot->name = "Copy Modifier";
829  ot->description = "Duplicate modifier at the same position in the stack";
830  ot->idname = "OBJECT_OT_gpencil_modifier_copy";
831 
835 
836  /* flags */
839 }
840 
841 /************************ Copy Modifier to Selected Operator *********************/
842 
844 {
847 
848  if (!md) {
849  return OPERATOR_CANCELLED;
850  }
851 
852  if (obact->type != OB_GPENCIL) {
853  BKE_reportf(op->reports,
854  RPT_ERROR,
855  "Source object '%s' is not a grease pencil object",
856  obact->id.name + 2);
857  return OPERATOR_CANCELLED;
858  }
859 
860  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
861  if (ob == obact) {
862  continue;
863  }
864 
865  if (ob->type != OB_GPENCIL) {
866  BKE_reportf(op->reports,
867  RPT_WARNING,
868  "Destination object '%s' is not a grease pencil object",
869  ob->id.name + 2);
870  continue;
871  }
872 
873  /* This always returns true right now. */
875 
878  }
879  CTX_DATA_END;
880 
881  return OPERATOR_FINISHED;
882 }
883 
885  wmOperator *op,
886  const wmEvent *event)
887 {
888  int retval;
889  if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) {
891  }
892  return retval;
893 }
894 
896 {
898 
899  /* This could have a performance impact in the worst case, where there are many objects selected
900  * and none of them pass the check. But that should be uncommon, and this operator is only
901  * exposed in a drop-down menu anyway. */
902  bool found_supported_objects = false;
903  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
904  if (ob == obact) {
905  continue;
906  }
907 
908  if (ob->type == OB_GPENCIL) {
909  found_supported_objects = true;
910  break;
911  }
912  }
913  CTX_DATA_END;
914 
915  if (!found_supported_objects) {
916  CTX_wm_operator_poll_msg_set(C, "No supported objects were selected");
917  return false;
918  }
919  return true;
920 }
921 
923 {
924  ot->name = "Copy Modifier to Selected";
925  ot->description = "Copy the modifier from the active object to all selected objects";
926  ot->idname = "OBJECT_OT_gpencil_modifier_copy_to_selected";
927 
931 
932  /* flags */
935 }
936 
937 /************************* Dash Modifier *******************************/
938 
940 {
941  return gpencil_edit_modifier_poll_generic(C, &RNA_DashGpencilModifierData, 0, false);
942 }
943 
944 static bool dash_segment_name_exists_fn(void *arg, const char *name)
945 {
946  const DashGpencilModifierData *dmd = (const DashGpencilModifierData *)arg;
947  for (int i = 0; i < dmd->segments_len; i++) {
948  if (STREQ(dmd->segments[i].name, name)) {
949  return true;
950  }
951  }
952  return false;
953 }
954 
956 {
959  op, ob, eGpencilModifierType_Dash);
960 
961  if (dmd == NULL) {
962  return OPERATOR_CANCELLED;
963  }
964  const int new_active_index = dmd->segment_active_index + 1;
966  dmd->segments_len + 1, sizeof(DashGpencilModifierSegment), __func__);
967 
968  if (dmd->segments_len != 0) {
969  /* Copy the segments before the new segment. */
970  memcpy(new_segments, dmd->segments, sizeof(DashGpencilModifierSegment) * new_active_index);
971  /* Copy the segments after the new segment. */
972  memcpy(new_segments + new_active_index + 1,
973  dmd->segments + new_active_index,
974  sizeof(DashGpencilModifierSegment) * (dmd->segments_len - new_active_index));
975  }
976 
977  /* Create the new segment. */
978  DashGpencilModifierSegment *ds = &new_segments[new_active_index];
979  memcpy(
982  dash_segment_name_exists_fn, dmd, DATA_("Segment"), '.', ds->name, sizeof(ds->name));
983  ds->dmd = dmd;
984 
985  MEM_SAFE_FREE(dmd->segments);
986  dmd->segments = new_segments;
987  dmd->segments_len++;
988  dmd->segment_active_index++;
989 
992 
993  return OPERATOR_FINISHED;
994 }
995 
996 static int dash_segment_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
997 {
999  return dash_segment_add_exec(C, op);
1000  }
1001  return OPERATOR_CANCELLED;
1002 }
1003 
1005 {
1006  /* identifiers */
1007  ot->name = "Add Segment";
1008  ot->description = "Add a segment to the dash modifier";
1009  ot->idname = "GPENCIL_OT_segment_add";
1010 
1011  /* api callbacks */
1015 
1016  /* flags */
1019 }
1020 
1022 {
1024 
1026  op, ob, eGpencilModifierType_Dash);
1027 
1028  if (dmd == NULL) {
1029  return OPERATOR_CANCELLED;
1030  }
1031 
1032  if (dmd->segment_active_index < 0 || dmd->segment_active_index >= dmd->segments_len) {
1033  return OPERATOR_CANCELLED;
1034  }
1035 
1036  if (dmd->segments_len == 1) {
1037  MEM_SAFE_FREE(dmd->segments);
1038  dmd->segment_active_index = -1;
1039  }
1040  else {
1042  dmd->segments_len, sizeof(DashGpencilModifierSegment), __func__);
1043 
1044  /* Copy the segments before the deleted segment. */
1045  memcpy(new_segments,
1046  dmd->segments,
1048 
1049  /* Copy the segments after the deleted segment. */
1050  memcpy(new_segments + dmd->segment_active_index,
1051  dmd->segments + dmd->segment_active_index + 1,
1052  sizeof(DashGpencilModifierSegment) *
1053  (dmd->segments_len - dmd->segment_active_index - 1));
1054 
1055  MEM_freeN(dmd->segments);
1056  dmd->segments = new_segments;
1057  dmd->segment_active_index = MAX2(dmd->segment_active_index - 1, 0);
1058  }
1059 
1060  dmd->segments_len--;
1061 
1064 
1065  return OPERATOR_FINISHED;
1066 }
1067 
1069 {
1071  return dash_segment_remove_exec(C, op);
1072  }
1073  return OPERATOR_CANCELLED;
1074 }
1075 
1077 {
1078  /* identifiers */
1079  ot->name = "Remove Dash Segment";
1080  ot->description = "Remove the active segment from the dash modifier";
1081  ot->idname = "GPENCIL_OT_segment_remove";
1082 
1083  /* api callbacks */
1087 
1088  /* flags */
1091 
1092  RNA_def_int(
1093  ot->srna, "index", 0, 0, INT_MAX, "Index", "Index of the segment to remove", 0, INT_MAX);
1094 }
1095 
1096 enum {
1099 };
1100 
1102 {
1104 
1106  op, ob, eGpencilModifierType_Dash);
1107 
1108  if (dmd == NULL) {
1109  return OPERATOR_CANCELLED;
1110  }
1111 
1112  if (dmd->segments_len < 2) {
1113  return OPERATOR_CANCELLED;
1114  }
1115 
1116  const int direction = RNA_enum_get(op->ptr, "type");
1117  if (direction == GP_SEGEMENT_MOVE_UP) {
1118  if (dmd->segment_active_index == 0) {
1119  return OPERATOR_CANCELLED;
1120  }
1121 
1123  dmd->segments[dmd->segment_active_index],
1124  dmd->segments[dmd->segment_active_index - 1]);
1125 
1126  dmd->segment_active_index--;
1127  }
1128  else if (direction == GP_SEGEMENT_MOVE_DOWN) {
1129  if (dmd->segment_active_index == dmd->segments_len - 1) {
1130  return OPERATOR_CANCELLED;
1131  }
1132 
1134  dmd->segments[dmd->segment_active_index],
1135  dmd->segments[dmd->segment_active_index + 1]);
1136 
1137  dmd->segment_active_index++;
1138  }
1139  else {
1140  return OPERATOR_CANCELLED;
1141  }
1142 
1145 
1146  return OPERATOR_FINISHED;
1147 }
1148 
1150 {
1152  return dash_segment_move_exec(C, op);
1153  }
1154  return OPERATOR_CANCELLED;
1155 }
1156 
1158 {
1159  static const EnumPropertyItem segment_move[] = {
1160  {GP_SEGEMENT_MOVE_UP, "UP", 0, "Up", ""},
1161  {GP_SEGEMENT_MOVE_DOWN, "DOWN", 0, "Down", ""},
1162  {0, NULL, 0, NULL, NULL},
1163  };
1164 
1165  /* identifiers */
1166  ot->name = "Move Dash Segment";
1167  ot->description = "Move the active dash segment up or down";
1168  ot->idname = "GPENCIL_OT_segment_move";
1169 
1170  /* api callbacks */
1174 
1175  /* flags */
1178 
1179  ot->prop = RNA_def_enum(ot->srna, "type", segment_move, 0, "Type", "");
1180 }
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
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
Definition: context.c:473
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
void CTX_wm_operator_poll_msg_set(struct bContext *C, const char *msg)
Definition: context.c:1042
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
#define CTX_DATA_END
Definition: BKE_context.h:278
void BKE_gpencil_modifier_free(struct GpencilModifierData *md)
bool BKE_gpencil_modifier_unique_name(struct ListBase *modifiers, struct GpencilModifierData *gmd)
@ eGpencilModifierTypeFlag_Single
@ eGpencilModifierTypeFlag_SupportsEditmode
@ eGpencilModifierTypeFlag_NoUserAdd
struct GpencilModifierData * BKE_gpencil_modifiers_findby_name(struct Object *ob, const char *name)
bool BKE_gpencil_modifier_is_nonlocal_in_liboverride(const struct Object *ob, const struct GpencilModifierData *gmd)
struct GpencilModifierData * BKE_gpencil_modifiers_findby_type(struct Object *ob, GpencilModifierType type)
void BKE_gpencil_modifier_copydata(struct GpencilModifierData *md, struct GpencilModifierData *target)
const GpencilModifierTypeInfo * BKE_gpencil_modifier_get_info(GpencilModifierType type)
struct GpencilModifierData * BKE_gpencil_modifier_new(int type)
bool BKE_id_is_editable(const struct Main *bmain, const struct ID *id)
General operations, lookup, etc. for blender objects.
bool BKE_object_copy_gpencil_modifier(struct Object *ob_dst, struct GpencilModifierData *gmd_src)
Definition: object.cc:1581
void BKE_object_free_derived_caches(struct Object *ob)
Definition: object.cc:1774
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
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:301
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
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
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
char * BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL(1
bool BLI_uniquename_cb(UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_len)
Definition: string_utils.c:233
#define SWAP(type, a, b)
#define UNUSED(x)
#define MAX2(a, b)
#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_ANIMATION
Definition: DNA_ID.h:794
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
#define MAX_NAME
Definition: DNA_defs.h:48
@ eGpencilModifierMode_Editmode
@ eGpencilModifierFlag_OverrideLibrary_Local
@ eGpencilModifierType_Dash
@ eGpencilModifierType_Thick
@ OB_MODE_OBJECT
Object is a sort of wrapper for general info.
@ OB_GPENCIL
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_PASS_THROUGH
@ MODIFIER_APPLY_DATA
Definition: ED_object.h:506
@ MODIFIER_APPLY_SHAPE
Definition: ED_object.h:507
struct Object * ED_object_active_context(const struct bContext *C)
bool ED_operator_object_active_editable(struct bContext *C)
Definition: screen_ops.c:396
_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)
@ PROP_HIDDEN
Definition: RNA_types.h:216
#define C
Definition: RandGen.cpp:25
struct PointerRNA * UI_region_panel_custom_data_under_cursor(const struct bContext *C, const struct wmEvent *event)
@ OPTYPE_INTERNAL
Definition: WM_types.h:168
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define ND_MODIFIER
Definition: WM_types.h:411
#define NC_OBJECT
Definition: WM_types.h:329
Scene scene
const Depsgraph * depsgraph
static const char * modifier_name[LS_MODIFIER_NUM]
Definition: linestyle.c:763
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
static unsigned a[3]
Definition: RandGen.cpp:78
void OBJECT_OT_gpencil_modifier_copy(wmOperatorType *ot)
void ED_object_gpencil_modifier_copy_to_object(Object *ob_dst, GpencilModifierData *md)
void OBJECT_OT_gpencil_modifier_add(wmOperatorType *ot)
static int gpencil_modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void OBJECT_OT_gpencil_modifier_move_up(wmOperatorType *ot)
void OBJECT_OT_gpencil_modifier_move_down(wmOperatorType *ot)
static int dash_segment_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
static bool gpencil_modifier_apply_obdata(ReportList *reports, Main *bmain, Depsgraph *depsgraph, Object *ob, GpencilModifierData *md)
static bool dash_segment_name_exists_fn(void *arg, const char *name)
static int gpencil_modifier_copy_to_selected_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int gpencil_modifier_move_to_index_exec(bContext *C, wmOperator *op)
GpencilModifierData * ED_object_gpencil_modifier_add(ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type)
static const EnumPropertyItem gpencil_modifier_apply_as_items[]
static int dash_segment_add_exec(bContext *C, wmOperator *op)
static int gpencil_modifier_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void gpencil_edit_modifier_report_property(wmOperatorType *ot)
static int dash_segment_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
void ED_object_gpencil_modifier_clear(Main *bmain, Object *ob)
static int gpencil_modifier_apply_exec(bContext *C, wmOperator *op)
bool ED_object_gpencil_modifier_remove(ReportList *reports, Main *bmain, Object *ob, GpencilModifierData *md)
bool ED_object_gpencil_modifier_move_to_index(ReportList *reports, Object *ob, GpencilModifierData *md, const int index)
static int dash_segment_move_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_segment_move(wmOperatorType *ot)
static int gpencil_modifier_add_exec(bContext *C, wmOperator *op)
static int gpencil_modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void OBJECT_OT_gpencil_modifier_copy_to_selected(wmOperatorType *ot)
static GpencilModifierData * gpencil_edit_modifier_property_get(wmOperator *op, Object *ob, int type)
static void gpencil_edit_modifier_properties(wmOperatorType *ot)
static int gpencil_modifier_move_up_exec(bContext *C, wmOperator *op)
static int gpencil_modifier_copy_exec(bContext *C, wmOperator *op)
static int gpencil_modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int gpencil_modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static bool dash_segment_poll(bContext *C)
void OBJECT_OT_gpencil_modifier_move_to_index(wmOperatorType *ot)
bool ED_object_gpencil_modifier_move_down(ReportList *UNUSED(reports), Object *ob, GpencilModifierData *md)
static int gpencil_modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int gpencil_modifier_move_down_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem * gpencil_modifier_add_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
static bool gpencil_edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag, const bool is_liboverride_allowed)
void GPENCIL_OT_segment_add(wmOperatorType *ot)
static bool gpencil_edit_modifier_liboverride_allowed_poll(bContext *C)
static int dash_segment_move_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
bool ED_object_gpencil_modifier_copy(ReportList *reports, Object *ob, GpencilModifierData *md)
static int dash_segment_remove_exec(bContext *C, wmOperator *op)
static bool gpencil_edit_modifier_invoke_properties(bContext *C, wmOperator *op, const wmEvent *event, int *r_retval)
@ GP_SEGEMENT_MOVE_DOWN
@ GP_SEGEMENT_MOVE_UP
void OBJECT_OT_gpencil_modifier_remove(wmOperatorType *ot)
bool ED_object_gpencil_modifier_apply(Main *bmain, ReportList *reports, Depsgraph *depsgraph, Object *ob, GpencilModifierData *md, int UNUSED(mode))
static bool gpencil_modifier_copy_to_selected_poll(bContext *C)
static bool gpencil_object_modifier_remove(Main *bmain, Object *ob, GpencilModifierData *md, bool *UNUSED(r_sort_depsgraph))
void GPENCIL_OT_segment_remove(wmOperatorType *ot)
static int gpencil_modifier_copy_to_selected_exec(bContext *C, wmOperator *op)
void OBJECT_OT_gpencil_modifier_apply(wmOperatorType *ot)
static int gpencil_modifier_remove_exec(bContext *C, wmOperator *op)
bool ED_object_gpencil_modifier_move_up(ReportList *UNUSED(reports), Object *ob, GpencilModifierData *md)
static bool gpencil_edit_modifier_poll(bContext *C)
void edit_modifier_properties(struct wmOperatorType *ot)
bool is_liboverride_allowed
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
Definition: rna_access.c:695
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
Definition: rna_access.c:5155
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
bool RNA_pointer_is_null(const PointerRNA *ptr)
Definition: rna_access.c:164
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:5301
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_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
Definition: rna_define.c:4487
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
Definition: rna_define.c:4436
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 rna_enum_object_greasepencil_modifier_type_items[]
DashGpencilModifierSegment * segments
struct DashGpencilModifierData * dmd
const char * identifier
Definition: RNA_types.h:461
struct GpencilModifierData * next
struct GpencilModifierData * prev
void(* bakeModifier)(struct Main *bmain, struct Depsgraph *depsgraph, struct GpencilModifierData *md, struct Object *ob)
GpencilModifierTypeFlag flags
bool(* isDisabled)(struct GpencilModifierData *md, int userRenderParams)
Definition: DNA_ID.h:368
char name[66]
Definition: DNA_ID.h:378
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase greasepencil_modifiers
void * data
struct StructRNA * type
Definition: RNA_types.h:37
void * data
Definition: RNA_types.h:38
struct ID * owner_id
Definition: RNA_types.h:36
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 PointerRNA * ptr
ccl_device_inline int mod(int x, int m)
Definition: util/math.h:490
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))