Cycles: Fix debug compilation after tile stealing commit
[blender.git] / source / blender / editors / object / object_gpencil_modifier.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2018 Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edobj
22  */
23
24 #include <math.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "MEM_guardedalloc.h"
30
31 #include "DNA_gpencil_modifier_types.h"
32 #include "DNA_gpencil_types.h"
33 #include "DNA_object_types.h"
34 #include "DNA_scene_types.h"
35
36 #include "BLI_listbase.h"
37 #include "BLI_string_utf8.h"
38 #include "BLI_utildefines.h"
39
40 #include "BKE_context.h"
41 #include "BKE_gpencil.h"
42 #include "BKE_gpencil_modifier.h"
43 #include "BKE_main.h"
44 #include "BKE_object.h"
45 #include "BKE_report.h"
46
47 #include "DEG_depsgraph.h"
48 #include "DEG_depsgraph_build.h"
49 #include "DEG_depsgraph_query.h"
50
51 #include "RNA_access.h"
52 #include "RNA_define.h"
53 #include "RNA_enum_types.h"
54
55 #include "ED_object.h"
56 #include "ED_screen.h"
57
58 #include "UI_interface.h"
59
60 #include "WM_api.h"
61 #include "WM_types.h"
62
63 #include "object_intern.h"
64
65 /******************************** API ****************************/
66
67 GpencilModifierData *ED_object_gpencil_modifier_add(
68     ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type)
69 {
70   GpencilModifierData *new_md = NULL;
71   const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(type);
72
73   if (ob->type != OB_GPENCIL) {
74     BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2);
75     return NULL;
76   }
77
78   if (mti->flags & eGpencilModifierTypeFlag_Single) {
79     if (BKE_gpencil_modifiers_findby_type(ob, type)) {
80       BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
81       return NULL;
82     }
83   }
84
85   /* get new modifier data to add */
86   new_md = BKE_gpencil_modifier_new(type);
87
88   BLI_addtail(&ob->greasepencil_modifiers, new_md);
89
90   if (name) {
91     BLI_strncpy_utf8(new_md->name, name, sizeof(new_md->name));
92   }
93
94   /* make sure modifier data has unique name */
95   BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, new_md);
96
97   /* Enable edit mode visible by default. */
98   if (mti->flags & eGpencilModifierTypeFlag_SupportsEditmode) {
99     new_md->mode |= eGpencilModifierMode_Editmode;
100   }
101
102   bGPdata *gpd = ob->data;
103   DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
104
105   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
106   DEG_relations_tag_update(bmain);
107
108   return new_md;
109 }
110
111 static bool gpencil_object_modifier_remove(Main *bmain,
112                                            Object *ob,
113                                            GpencilModifierData *md,
114                                            bool *UNUSED(r_sort_depsgraph))
115 {
116   /* It seems on rapid delete it is possible to
117    * get called twice on same modifier, so make
118    * sure it is in list. */
119   if (BLI_findindex(&ob->greasepencil_modifiers, md) == -1) {
120     return false;
121   }
122
123   DEG_relations_tag_update(bmain);
124
125   BLI_remlink(&ob->greasepencil_modifiers, md);
126   BKE_gpencil_modifier_free(md);
127   BKE_object_free_derived_caches(ob);
128
129   return true;
130 }
131
132 bool ED_object_gpencil_modifier_remove(ReportList *reports,
133                                        Main *bmain,
134                                        Object *ob,
135                                        GpencilModifierData *md)
136 {
137   bool sort_depsgraph = false;
138   bool ok;
139
140   ok = gpencil_object_modifier_remove(bmain, ob, md, &sort_depsgraph);
141
142   if (!ok) {
143     BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", md->name, ob->id.name);
144     return false;
145   }
146
147   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
148   DEG_relations_tag_update(bmain);
149
150   return true;
151 }
152
153 void ED_object_gpencil_modifier_clear(Main *bmain, Object *ob)
154 {
155   GpencilModifierData *md = ob->greasepencil_modifiers.first;
156   bool sort_depsgraph = false;
157
158   if (!md) {
159     return;
160   }
161
162   while (md) {
163     GpencilModifierData *next_md;
164
165     next_md = md->next;
166
167     gpencil_object_modifier_remove(bmain, ob, md, &sort_depsgraph);
168
169     md = next_md;
170   }
171
172   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
173   DEG_relations_tag_update(bmain);
174 }
175
176 int ED_object_gpencil_modifier_move_up(ReportList *UNUSED(reports),
177                                        Object *ob,
178                                        GpencilModifierData *md)
179 {
180   if (md->prev) {
181     BLI_remlink(&ob->greasepencil_modifiers, md);
182     BLI_insertlinkbefore(&ob->greasepencil_modifiers, md->prev, md);
183   }
184
185   return 1;
186 }
187
188 int ED_object_gpencil_modifier_move_down(ReportList *UNUSED(reports),
189                                          Object *ob,
190                                          GpencilModifierData *md)
191 {
192   if (md->next) {
193     BLI_remlink(&ob->greasepencil_modifiers, md);
194     BLI_insertlinkafter(&ob->greasepencil_modifiers, md->next, md);
195   }
196
197   return 1;
198 }
199
200 bool ED_object_gpencil_modifier_move_to_index(ReportList *reports,
201                                               Object *ob,
202                                               GpencilModifierData *md,
203                                               const int index)
204 {
205   BLI_assert(md != NULL);
206   BLI_assert(index >= 0);
207   if (index >= BLI_listbase_count(&ob->greasepencil_modifiers)) {
208     BKE_report(reports, RPT_WARNING, "Cannot move modifier beyond the end of the stack");
209     return false;
210   }
211
212   int md_index = BLI_findindex(&ob->greasepencil_modifiers, md);
213   BLI_assert(md_index != -1);
214   if (md_index < index) {
215     /* Move modifier down in list. */
216     for (; md_index < index; md_index++) {
217       if (!ED_object_gpencil_modifier_move_down(reports, ob, md)) {
218         break;
219       }
220     }
221   }
222   else {
223     /* Move modifier up in list. */
224     for (; md_index > index; md_index--) {
225       if (!ED_object_gpencil_modifier_move_up(reports, ob, md)) {
226         break;
227       }
228     }
229   }
230
231   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
232   WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
233
234   return true;
235 }
236
237 static int gpencil_modifier_apply_obdata(
238     ReportList *reports, Main *bmain, Depsgraph *depsgraph, Object *ob, GpencilModifierData *md)
239 {
240   const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type);
241
242   if (mti->isDisabled && mti->isDisabled(md, 0)) {
243     BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
244     return 0;
245   }
246
247   if (ob->type == OB_GPENCIL) {
248     if (ELEM(NULL, ob, ob->data)) {
249       return 0;
250     }
251     if (mti->bakeModifier == NULL) {
252       BKE_report(reports, RPT_ERROR, "Not implemented");
253       return 0;
254     }
255     mti->bakeModifier(bmain, depsgraph, md, ob);
256     DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
257   }
258   else {
259     BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
260     return 0;
261   }
262
263   return 1;
264 }
265
266 int ED_object_gpencil_modifier_apply(Main *bmain,
267                                      ReportList *reports,
268                                      Depsgraph *depsgraph,
269                                      Object *ob,
270                                      GpencilModifierData *md,
271                                      int UNUSED(mode))
272 {
273
274   if (ob->type == OB_GPENCIL) {
275     if (ob->mode != OB_MODE_OBJECT) {
276       BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in paint, sculpt or edit mode");
277       return 0;
278     }
279
280     if (((ID *)ob->data)->us > 1) {
281       BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
282       return 0;
283     }
284   }
285   else if (((ID *)ob->data)->us > 1) {
286     BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
287     return 0;
288   }
289
290   if (md != ob->greasepencil_modifiers.first) {
291     BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
292   }
293
294   if (!gpencil_modifier_apply_obdata(reports, bmain, depsgraph, ob, md)) {
295     return 0;
296   }
297
298   BLI_remlink(&ob->greasepencil_modifiers, md);
299   BKE_gpencil_modifier_free(md);
300
301   return 1;
302 }
303
304 int ED_object_gpencil_modifier_copy(ReportList *reports, Object *ob, GpencilModifierData *md)
305 {
306   GpencilModifierData *nmd;
307   const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type);
308   GpencilModifierType type = md->type;
309
310   if (mti->flags & eGpencilModifierTypeFlag_Single) {
311     if (BKE_gpencil_modifiers_findby_type(ob, type)) {
312       BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed");
313       return 0;
314     }
315   }
316
317   nmd = BKE_gpencil_modifier_new(md->type);
318   BKE_gpencil_modifier_copydata(md, nmd);
319   BLI_insertlinkafter(&ob->greasepencil_modifiers, md, nmd);
320   BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, nmd);
321
322   return 1;
323 }
324
325 void ED_object_gpencil_modifier_copy_to_object(Object *ob_dst, GpencilModifierData *md)
326 {
327   BKE_object_copy_gpencil_modifier(ob_dst, md);
328   WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob_dst);
329   DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
330 }
331
332 /************************ add modifier operator *********************/
333
334 static int gpencil_modifier_add_exec(bContext *C, wmOperator *op)
335 {
336   Main *bmain = CTX_data_main(C);
337   Scene *scene = CTX_data_scene(C);
338   Object *ob = ED_object_active_context(C);
339   int type = RNA_enum_get(op->ptr, "type");
340
341   if (!ED_object_gpencil_modifier_add(op->reports, bmain, scene, ob, NULL, type)) {
342     return OPERATOR_CANCELLED;
343   }
344
345   WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
346
347   return OPERATOR_FINISHED;
348 }
349
350 static const EnumPropertyItem *gpencil_modifier_add_itemf(bContext *C,
351                                                           PointerRNA *UNUSED(ptr),
352                                                           PropertyRNA *UNUSED(prop),
353                                                           bool *r_free)
354 {
355   Object *ob = ED_object_active_context(C);
356   EnumPropertyItem *item = NULL;
357   const EnumPropertyItem *md_item, *group_item = NULL;
358   const GpencilModifierTypeInfo *mti;
359   int totitem = 0, a;
360
361   if (!ob) {
362     return rna_enum_object_greasepencil_modifier_type_items;
363   }
364
365   for (a = 0; rna_enum_object_greasepencil_modifier_type_items[a].identifier; a++) {
366     md_item = &rna_enum_object_greasepencil_modifier_type_items[a];
367     if (md_item->identifier[0]) {
368       mti = BKE_gpencil_modifier_get_info(md_item->value);
369
370       if (mti->flags & eGpencilModifierTypeFlag_NoUserAdd) {
371         continue;
372       }
373     }
374     else {
375       group_item = md_item;
376       md_item = NULL;
377
378       continue;
379     }
380
381     if (group_item) {
382       RNA_enum_item_add(&item, &totitem, group_item);
383       group_item = NULL;
384     }
385
386     RNA_enum_item_add(&item, &totitem, md_item);
387   }
388
389   RNA_enum_item_end(&item, &totitem);
390   *r_free = true;
391
392   return item;
393 }
394
395 void OBJECT_OT_gpencil_modifier_add(wmOperatorType *ot)
396 {
397   PropertyRNA *prop;
398
399   /* identifiers */
400   ot->name = "Add Modifier";
401   ot->description = "Add a procedural operation/effect to the active grease pencil object";
402   ot->idname = "OBJECT_OT_gpencil_modifier_add";
403
404   /* api callbacks */
405   ot->invoke = WM_menu_invoke;
406   ot->exec = gpencil_modifier_add_exec;
407   ot->poll = ED_operator_object_active_editable;
408
409   /* flags */
410   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
411
412   /* properties */
413   prop = RNA_def_enum(ot->srna,
414                       "type",
415                       rna_enum_object_modifier_type_items,
416                       eGpencilModifierType_Thick,
417                       "Type",
418                       "");
419   RNA_def_enum_funcs(prop, gpencil_modifier_add_itemf);
420   ot->prop = prop;
421 }
422
423 /********** generic functions for operators using mod names and data context *********************/
424
425 static bool gpencil_edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
426 {
427   PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
428   Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
429   GpencilModifierData *mod = ptr.data; /* May be NULL. */
430
431   if (!ob || ID_IS_LINKED(ob)) {
432     return false;
433   }
434   if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) {
435     return false;
436   }
437   if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) {
438     return false;
439   }
440
441   if (ID_IS_OVERRIDE_LIBRARY(ob)) {
442     if ((mod == NULL) || (mod->flag & eGpencilModifierFlag_OverrideLibrary_Local) == 0) {
443       CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from library override");
444       return false;
445     }
446   }
447
448   return true;
449 }
450
451 static bool gpencil_edit_modifier_poll(bContext *C)
452 {
453   return gpencil_edit_modifier_poll_generic(C, &RNA_GpencilModifier, 0);
454 }
455
456 static void gpencil_edit_modifier_properties(wmOperatorType *ot)
457 {
458   PropertyRNA *prop = RNA_def_string(
459       ot->srna, "modifier", NULL, MAX_NAME, "Modifier", "Name of the modifier to edit");
460   RNA_def_property_flag(prop, PROP_HIDDEN);
461 }
462
463 static void gpencil_edit_modifier_report_property(wmOperatorType *ot)
464 {
465   PropertyRNA *prop = RNA_def_boolean(
466       ot->srna, "report", false, "Report", "Create a notification after the operation");
467   RNA_def_property_flag(prop, PROP_HIDDEN);
468 }
469
470 /**
471  * \param event: If this isn't NULL, the operator will also look for panels underneath
472  * the cursor with customdata set to a modifier.
473  * \param r_retval: This should be used if #event is used in order to to return
474  * #OPERATOR_PASS_THROUGH to check other operators with the same key set.
475  */
476 static bool gpencil_edit_modifier_invoke_properties(bContext *C,
477                                                     wmOperator *op,
478                                                     const wmEvent *event,
479                                                     int *r_retval)
480 {
481   if (RNA_struct_property_is_set(op->ptr, "modifier")) {
482     return true;
483   }
484
485   PointerRNA ctx_ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_GpencilModifier);
486   if (ctx_ptr.data != NULL) {
487     GpencilModifierData *md = ctx_ptr.data;
488     RNA_string_set(op->ptr, "modifier", md->name);
489     return true;
490   }
491
492   /* Check the custom data of panels under the mouse for a modifier. */
493   if (event != NULL) {
494     PointerRNA *panel_ptr = UI_region_panel_custom_data_under_cursor(C, event);
495
496     if (!(panel_ptr == NULL || RNA_pointer_is_null(panel_ptr))) {
497       if (RNA_struct_is_a(panel_ptr->type, &RNA_GpencilModifier)) {
498         GpencilModifierData *md = panel_ptr->data;
499         RNA_string_set(op->ptr, "modifier", md->name);
500         return true;
501       }
502
503       BLI_assert(r_retval != NULL); /* We need the return value in this case. */
504       if (r_retval != NULL) {
505         *r_retval = (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED);
506       }
507       return false;
508     }
509   }
510
511   if (r_retval != NULL) {
512     *r_retval = OPERATOR_CANCELLED;
513   }
514   return false;
515 }
516
517 static GpencilModifierData *gpencil_edit_modifier_property_get(wmOperator *op,
518                                                                Object *ob,
519                                                                int type)
520 {
521   char modifier_name[MAX_NAME];
522   GpencilModifierData *md;
523   RNA_string_get(op->ptr, "modifier", modifier_name);
524
525   md = BKE_gpencil_modifiers_findby_name(ob, modifier_name);
526
527   if (md && type != 0 && md->type != type) {
528     md = NULL;
529   }
530
531   return md;
532 }
533
534 /************************ remove modifier operator *********************/
535
536 static int gpencil_modifier_remove_exec(bContext *C, wmOperator *op)
537 {
538   Main *bmain = CTX_data_main(C);
539   Object *ob = ED_object_active_context(C);
540   GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
541
542   if (md == NULL) {
543     return OPERATOR_CANCELLED;
544   }
545
546   /* Store name temporarily for report. */
547   char name[MAX_NAME];
548   strcpy(name, md->name);
549
550   if (!ED_object_gpencil_modifier_remove(op->reports, bmain, ob, md)) {
551     return OPERATOR_CANCELLED;
552   }
553
554   WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
555
556   if (RNA_boolean_get(op->ptr, "report")) {
557     BKE_reportf(op->reports, RPT_INFO, "Removed modifier: %s", name);
558   }
559
560   return OPERATOR_FINISHED;
561 }
562
563 static int gpencil_modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
564 {
565   int retval;
566   if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) {
567     return gpencil_modifier_remove_exec(C, op);
568   }
569   return retval;
570 }
571
572 void OBJECT_OT_gpencil_modifier_remove(wmOperatorType *ot)
573 {
574   ot->name = "Remove Grease Pencil Modifier";
575   ot->description = "Remove a modifier from the active grease pencil object";
576   ot->idname = "OBJECT_OT_gpencil_modifier_remove";
577
578   ot->invoke = gpencil_modifier_remove_invoke;
579   ot->exec = gpencil_modifier_remove_exec;
580   ot->poll = gpencil_edit_modifier_poll;
581
582   /* flags */
583   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
584   gpencil_edit_modifier_properties(ot);
585   gpencil_edit_modifier_report_property(ot);
586 }
587
588 /************************ move up modifier operator *********************/
589
590 static int gpencil_modifier_move_up_exec(bContext *C, wmOperator *op)
591 {
592   Object *ob = ED_object_active_context(C);
593   GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
594
595   if (!md || !ED_object_gpencil_modifier_move_up(op->reports, ob, md)) {
596     return OPERATOR_CANCELLED;
597   }
598
599   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
600   WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
601
602   return OPERATOR_FINISHED;
603 }
604
605 static int gpencil_modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *event)
606 {
607   int retval;
608   if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) {
609     return gpencil_modifier_move_up_exec(C, op);
610   }
611   return retval;
612 }
613
614 void OBJECT_OT_gpencil_modifier_move_up(wmOperatorType *ot)
615 {
616   ot->name = "Move Up Modifier";
617   ot->description = "Move modifier up in the stack";
618   ot->idname = "OBJECT_OT_gpencil_modifier_move_up";
619
620   ot->invoke = gpencil_modifier_move_up_invoke;
621   ot->exec = gpencil_modifier_move_up_exec;
622   ot->poll = gpencil_edit_modifier_poll;
623
624   /* flags */
625   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
626   gpencil_edit_modifier_properties(ot);
627 }
628
629 /************************ move down modifier operator *********************/
630
631 static int gpencil_modifier_move_down_exec(bContext *C, wmOperator *op)
632 {
633   Object *ob = ED_object_active_context(C);
634   GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
635
636   if (!md || !ED_object_gpencil_modifier_move_down(op->reports, ob, md)) {
637     return OPERATOR_CANCELLED;
638   }
639
640   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
641   WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
642
643   return OPERATOR_FINISHED;
644 }
645
646 static int gpencil_modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *event)
647 {
648   int retval;
649   if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) {
650     return gpencil_modifier_move_down_exec(C, op);
651   }
652   return retval;
653 }
654
655 void OBJECT_OT_gpencil_modifier_move_down(wmOperatorType *ot)
656 {
657   ot->name = "Move Down Modifier";
658   ot->description = "Move modifier down in the stack";
659   ot->idname = "OBJECT_OT_gpencil_modifier_move_down";
660
661   ot->invoke = gpencil_modifier_move_down_invoke;
662   ot->exec = gpencil_modifier_move_down_exec;
663   ot->poll = gpencil_edit_modifier_poll;
664
665   /* flags */
666   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
667   gpencil_edit_modifier_properties(ot);
668 }
669
670 /* ************************* Move to Index Gpencil Modifier Operator ************************* */
671
672 static bool gpencil_modifier_move_to_index_poll(bContext *C)
673 {
674   return gpencil_edit_modifier_poll(C);
675 }
676
677 static int gpencil_modifier_move_to_index_exec(bContext *C, wmOperator *op)
678 {
679   Object *ob = ED_object_active_context(C);
680   GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
681   int index = RNA_int_get(op->ptr, "index");
682
683   if (!ED_object_gpencil_modifier_move_to_index(op->reports, ob, md, index)) {
684     return OPERATOR_CANCELLED;
685   }
686
687   return OPERATOR_FINISHED;
688 }
689
690 static int gpencil_modifier_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *event)
691 {
692   int retval;
693   if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) {
694     return gpencil_modifier_move_to_index_exec(C, op);
695   }
696   return retval;
697 }
698
699 void OBJECT_OT_gpencil_modifier_move_to_index(wmOperatorType *ot)
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
707   ot->invoke = gpencil_modifier_move_to_index_invoke;
708   ot->exec = gpencil_modifier_move_to_index_exec;
709   ot->poll = gpencil_modifier_move_to_index_poll;
710
711   /* flags */
712   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
713   edit_modifier_properties(ot);
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
720 static int gpencil_modifier_apply_exec(bContext *C, wmOperator *op)
721 {
722   Main *bmain = CTX_data_main(C);
723   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
724   Object *ob = ED_object_active_context(C);
725   GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
726   int apply_as = RNA_enum_get(op->ptr, "apply_as");
727
728   if (md == NULL) {
729     return OPERATOR_CANCELLED;
730   }
731
732   /* Store name temporarily for report. */
733   char name[MAX_NAME];
734   strcpy(name, md->name);
735
736   if (!ED_object_gpencil_modifier_apply(bmain, op->reports, depsgraph, ob, md, apply_as)) {
737     return OPERATOR_CANCELLED;
738   }
739
740   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
741   WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
742
743   if (RNA_boolean_get(op->ptr, "report")) {
744     BKE_reportf(op->reports, RPT_INFO, "Applied modifier: %s", name);
745   }
746
747   return OPERATOR_FINISHED;
748 }
749
750 static int gpencil_modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *event)
751 {
752   int retval;
753   if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) {
754     return gpencil_modifier_apply_exec(C, op);
755   }
756   return retval;
757 }
758
759 static const EnumPropertyItem gpencil_modifier_apply_as_items[] = {
760     {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
761     {MODIFIER_APPLY_SHAPE,
762      "SHAPE",
763      0,
764      "New Shape",
765      "Apply deform-only modifier to a new shape on this object"},
766     {0, NULL, 0, NULL, NULL},
767 };
768
769 void OBJECT_OT_gpencil_modifier_apply(wmOperatorType *ot)
770 {
771   ot->name = "Apply Modifier";
772   ot->description = "Apply modifier and remove from the stack";
773   ot->idname = "OBJECT_OT_gpencil_modifier_apply";
774
775   ot->invoke = gpencil_modifier_apply_invoke;
776   ot->exec = gpencil_modifier_apply_exec;
777   ot->poll = gpencil_edit_modifier_poll;
778
779   /* flags */
780   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
781
782   RNA_def_enum(ot->srna,
783                "apply_as",
784                gpencil_modifier_apply_as_items,
785                MODIFIER_APPLY_DATA,
786                "Apply as",
787                "How to apply the modifier to the geometry");
788   gpencil_edit_modifier_properties(ot);
789   gpencil_edit_modifier_report_property(ot);
790 }
791
792 /************************ copy modifier operator *********************/
793
794 static int gpencil_modifier_copy_exec(bContext *C, wmOperator *op)
795 {
796   Object *ob = ED_object_active_context(C);
797   GpencilModifierData *md = gpencil_edit_modifier_property_get(op, ob, 0);
798
799   if (!md || !ED_object_gpencil_modifier_copy(op->reports, ob, md)) {
800     return OPERATOR_CANCELLED;
801   }
802
803   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
804   WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
805
806   return OPERATOR_FINISHED;
807 }
808
809 static int gpencil_modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *event)
810 {
811   int retval;
812   if (gpencil_edit_modifier_invoke_properties(C, op, event, &retval)) {
813     return gpencil_modifier_copy_exec(C, op);
814   }
815   return retval;
816 }
817
818 void OBJECT_OT_gpencil_modifier_copy(wmOperatorType *ot)
819 {
820   ot->name = "Copy Modifier";
821   ot->description = "Duplicate modifier at the same position in the stack";
822   ot->idname = "OBJECT_OT_gpencil_modifier_copy";
823
824   ot->invoke = gpencil_modifier_copy_invoke;
825   ot->exec = gpencil_modifier_copy_exec;
826   ot->poll = gpencil_edit_modifier_poll;
827
828   /* flags */
829   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
830   gpencil_edit_modifier_properties(ot);
831 }