Cleanup: BKE_gpencil naming
[blender.git] / source / blender / editors / gpencil / gpencil_data.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) 2008, Blender Foundation
17  * This is a new part of Blender
18  * Operators for dealing with GP datablocks and layers
19  */
20
21 /** \file
22  * \ingroup edgpencil
23  */
24
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <stddef.h>
30 #include <math.h>
31
32 #include "MEM_guardedalloc.h"
33
34 #include "BLI_blenlib.h"
35 #include "BLI_utildefines.h"
36 #include "BLI_ghash.h"
37 #include "BLI_math.h"
38 #include "BLI_string_utils.h"
39
40 #include "BLT_translation.h"
41
42 #include "DNA_anim_types.h"
43 #include "DNA_brush_types.h"
44 #include "DNA_gpencil_types.h"
45 #include "DNA_meshdata_types.h"
46 #include "DNA_modifier_types.h"
47 #include "DNA_object_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_screen_types.h"
50 #include "DNA_space_types.h"
51 #include "DNA_view3d_types.h"
52
53 #include "BKE_animsys.h"
54 #include "BKE_brush.h"
55 #include "BKE_context.h"
56 #include "BKE_deform.h"
57 #include "BKE_fcurve.h"
58 #include "BKE_gpencil.h"
59 #include "BKE_gpencil_modifier.h"
60 #include "BKE_library.h"
61 #include "BKE_main.h"
62 #include "BKE_material.h"
63 #include "BKE_modifier.h"
64 #include "BKE_object.h"
65 #include "BKE_paint.h"
66 #include "BKE_report.h"
67 #include "BKE_scene.h"
68
69 #include "UI_interface.h"
70 #include "UI_resources.h"
71
72 #include "WM_api.h"
73 #include "WM_types.h"
74
75 #include "RNA_access.h"
76 #include "RNA_define.h"
77 #include "RNA_enum_types.h"
78
79 #include "ED_object.h"
80 #include "ED_gpencil.h"
81
82 #include "DEG_depsgraph.h"
83 #include "DEG_depsgraph_build.h"
84 #include "DEG_depsgraph_query.h"
85
86 #include "gpencil_intern.h"
87
88 /* ************************************************ */
89 /* Datablock Operators */
90
91 /* ******************* Add New Data ************************ */
92 static bool gp_data_add_poll(bContext *C)
93 {
94         Object *obact = CTX_data_active_object(C);
95         if (obact && obact->type == OB_GPENCIL) {
96                 if (obact->mode != OB_MODE_OBJECT) {
97                         return false;
98                 }
99         }
100
101         /* the base line we have is that we have somewhere to add Grease Pencil data */
102         return ED_gpencil_data_get_pointers(C, NULL) != NULL;
103 }
104
105 /* add new datablock - wrapper around API */
106 static int gp_data_add_exec(bContext *C, wmOperator *op)
107 {
108         PointerRNA gpd_owner = {{NULL}};
109         bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, &gpd_owner);
110         bool is_annotation = ED_gpencil_data_owner_is_annotation(&gpd_owner);
111
112         if (gpd_ptr == NULL) {
113                 BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
114                 return OPERATOR_CANCELLED;
115         }
116         else {
117                 /* decrement user count and add new datablock */
118                 /* TODO: if a datablock exists,
119                  * we should make a copy of it instead of starting fresh (as in other areas) */
120                 Main *bmain = CTX_data_main(C);
121
122                 /* decrement user count of old GP datablock */
123                 if (*gpd_ptr) {
124                         bGPdata *gpd = (*gpd_ptr);
125                         id_us_min(&gpd->id);
126                 }
127
128                 /* add new datablock, with a single layer ready to use (so users don't have to perform an extra step) */
129                 if (is_annotation) {
130                         bGPdata *gpd = BKE_gpencil_data_addnew(bmain, DATA_("Annotations"));
131                         *gpd_ptr = gpd;
132
133                         /* tag for annotations */
134                         gpd->flag |= GP_DATA_ANNOTATIONS;
135
136                         /* add new layer (i.e. a "note") */
137                         BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true);
138                 }
139                 else {
140                         /* GP Object Case - This shouldn't happen! */
141                         *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
142
143                         /* add default sets of colors and brushes */
144                         Object *ob = CTX_data_active_object(C);
145                         ED_gpencil_add_defaults(C, ob);
146
147                         /* add new layer */
148                         BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), true);
149                 }
150         }
151
152         /* notifiers */
153         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
154
155         return OPERATOR_FINISHED;
156 }
157
158 void GPENCIL_OT_data_add(wmOperatorType *ot)
159 {
160         /* identifiers */
161         ot->name = "Grease Pencil Add New";
162         ot->idname = "GPENCIL_OT_data_add";
163         ot->description = "Add new Grease Pencil data-block";
164         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
165
166         /* callbacks */
167         ot->exec = gp_data_add_exec;
168         ot->poll = gp_data_add_poll;
169 }
170
171 /* ******************* Unlink Data ************************ */
172
173 /* poll callback for adding data/layers - special */
174 static bool gp_data_unlink_poll(bContext *C)
175 {
176         bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
177
178         /* only unlink annotation datablocks */
179         if ((gpd_ptr != NULL) && (*gpd_ptr != NULL)) {
180                 bGPdata *gpd = (*gpd_ptr);
181                 if ((gpd->flag & GP_DATA_ANNOTATIONS) == 0) {
182                         return false;
183                 }
184         }
185         /* if we have access to some active data, make sure there's a datablock before enabling this */
186         return (gpd_ptr && *gpd_ptr);
187 }
188
189
190 /* unlink datablock - wrapper around API */
191 static int gp_data_unlink_exec(bContext *C, wmOperator *op)
192 {
193         bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
194
195         if (gpd_ptr == NULL) {
196                 BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
197                 return OPERATOR_CANCELLED;
198         }
199         else {
200                 /* just unlink datablock now, decreasing its user count */
201                 bGPdata *gpd = (*gpd_ptr);
202
203                 id_us_min(&gpd->id);
204                 *gpd_ptr = NULL;
205         }
206
207         /* notifiers */
208         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
209
210         return OPERATOR_FINISHED;
211 }
212
213 void GPENCIL_OT_data_unlink(wmOperatorType *ot)
214 {
215         /* identifiers */
216         ot->name = "Annotation Unlink";
217         ot->idname = "GPENCIL_OT_data_unlink";
218         ot->description = "Unlink active Annotation data-block";
219         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
220
221         /* callbacks */
222         ot->exec = gp_data_unlink_exec;
223         ot->poll = gp_data_unlink_poll;
224 }
225
226
227 /* ************************************************ */
228 /* Layer Operators */
229
230 /* ******************* Add New Layer ************************ */
231
232 /* add new layer - wrapper around API */
233 static int gp_layer_add_exec(bContext *C, wmOperator *op)
234 {
235         PointerRNA gpd_owner = {{NULL}};
236         bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, &gpd_owner);
237         bool is_annotation = ED_gpencil_data_owner_is_annotation(&gpd_owner);
238
239         /* if there's no existing Grease-Pencil data there, add some */
240         if (gpd_ptr == NULL) {
241                 BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
242                 return OPERATOR_CANCELLED;
243         }
244
245         if (*gpd_ptr == NULL) {
246                 Main *bmain = CTX_data_main(C);
247                 if (is_annotation) {
248                         /* Annotations */
249                         *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("Annotations"));
250
251                         /* mark as annotation */
252                         (*gpd_ptr)->flag |= GP_DATA_ANNOTATIONS;
253                 }
254                 else {
255                         /* GP Object */
256                         /* NOTE: This shouldn't actually happen in practice */
257                         *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
258
259                         /* add default sets of colors and brushes */
260                         Object *ob = CTX_data_active_object(C);
261                         ED_gpencil_add_defaults(C, ob);
262                 }
263         }
264
265         /* add new layer now */
266         if (is_annotation) {
267                 BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true);
268         }
269         else {
270                 BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), true);
271         }
272
273         /* notifiers */
274         bGPdata *gpd = *gpd_ptr;
275         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
276         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
277
278         return OPERATOR_FINISHED;
279 }
280
281 void GPENCIL_OT_layer_add(wmOperatorType *ot)
282 {
283         /* identifiers */
284         ot->name = "Add New Layer";
285         ot->idname = "GPENCIL_OT_layer_add";
286         ot->description = "Add new layer or note for the active data-block";
287
288         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
289
290         /* callbacks */
291         ot->exec = gp_layer_add_exec;
292         ot->poll = gp_add_poll;
293 }
294
295 /* ******************* Remove Active Layer ************************* */
296
297 static int gp_layer_remove_exec(bContext *C, wmOperator *op)
298 {
299         bGPdata *gpd = ED_gpencil_data_get_active(C);
300         bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
301
302         /* sanity checks */
303         if (ELEM(NULL, gpd, gpl))
304                 return OPERATOR_CANCELLED;
305
306         if (gpl->flag & GP_LAYER_LOCKED) {
307                 BKE_report(op->reports, RPT_ERROR, "Cannot delete locked layers");
308                 return OPERATOR_CANCELLED;
309         }
310
311         /* make the layer before this the new active layer
312          * - use the one after if this is the first
313          * - if this is the only layer, this naturally becomes NULL
314          */
315         if (gpl->prev)
316                 BKE_gpencil_layer_setactive(gpd, gpl->prev);
317         else
318                 BKE_gpencil_layer_setactive(gpd, gpl->next);
319
320         /* delete the layer now... */
321         BKE_gpencil_layer_delete(gpd, gpl);
322
323         /* notifiers */
324         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
325         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
326
327         return OPERATOR_FINISHED;
328 }
329
330 void GPENCIL_OT_layer_remove(wmOperatorType *ot)
331 {
332         /* identifiers */
333         ot->name = "Remove Layer";
334         ot->idname = "GPENCIL_OT_layer_remove";
335         ot->description = "Remove active Grease Pencil layer";
336
337         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
338
339         /* callbacks */
340         ot->exec = gp_layer_remove_exec;
341         ot->poll = gp_active_layer_poll;
342 }
343
344 /* ******************* Move Layer Up/Down ************************** */
345
346 enum {
347         GP_LAYER_MOVE_UP   = -1,
348         GP_LAYER_MOVE_DOWN = 1,
349 };
350
351 static int gp_layer_move_exec(bContext *C, wmOperator *op)
352 {
353         bGPdata *gpd = ED_gpencil_data_get_active(C);
354         bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
355
356         const int direction = RNA_enum_get(op->ptr, "type") * -1;
357
358         /* sanity checks */
359         if (ELEM(NULL, gpd, gpl))
360                 return OPERATOR_CANCELLED;
361
362         BLI_assert(ELEM(direction, -1, 0, 1)); /* we use value below */
363         if (BLI_listbase_link_move(&gpd->layers, gpl, direction)) {
364                 DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
365                 WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
366         }
367
368         return OPERATOR_FINISHED;
369 }
370
371 void GPENCIL_OT_layer_move(wmOperatorType *ot)
372 {
373         static const EnumPropertyItem slot_move[] = {
374                 {GP_LAYER_MOVE_UP, "UP", 0, "Up", ""},
375                 {GP_LAYER_MOVE_DOWN, "DOWN", 0, "Down", ""},
376                 {0, NULL, 0, NULL, NULL},
377         };
378
379         /* identifiers */
380         ot->name = "Move Grease Pencil Layer";
381         ot->idname = "GPENCIL_OT_layer_move";
382         ot->description = "Move the active Grease Pencil layer up/down in the list";
383
384         /* api callbacks */
385         ot->exec = gp_layer_move_exec;
386         ot->poll = gp_active_layer_poll;
387
388         /* flags */
389         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
390
391         ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
392 }
393
394 /* ********************* Duplicate Layer ************************** */
395
396 static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op))
397 {
398         bGPdata *gpd = ED_gpencil_data_get_active(C);
399         bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
400         bGPDlayer *new_layer;
401
402         /* sanity checks */
403         if (ELEM(NULL, gpd, gpl))
404                 return OPERATOR_CANCELLED;
405
406         /* make copy of layer, and add it immediately after the existing layer */
407         new_layer = BKE_gpencil_layer_duplicate(gpl);
408         BLI_insertlinkafter(&gpd->layers, gpl, new_layer);
409
410         /* ensure new layer has a unique name, and is now the active layer */
411         BLI_uniquename(&gpd->layers, new_layer, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(new_layer->info));
412         BKE_gpencil_layer_setactive(gpd, new_layer);
413
414         /* notifiers */
415         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
416         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
417
418         return OPERATOR_FINISHED;
419 }
420
421 void GPENCIL_OT_layer_duplicate(wmOperatorType *ot)
422 {
423         /* identifiers */
424         ot->name = "Duplicate Layer";
425         ot->idname = "GPENCIL_OT_layer_duplicate";
426         ot->description = "Make a copy of the active Grease Pencil layer";
427
428         /* callbacks */
429         ot->exec = gp_layer_copy_exec;
430         ot->poll = gp_active_layer_poll;
431
432         /* flags */
433         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
434 }
435
436 /* ********************* Duplicate Layer in a new object ************************** */
437 enum {
438         GP_LAYER_COPY_OBJECT_ALL_FRAME = 0,
439         GP_LAYER_COPY_OBJECT_ACT_FRAME = 1,
440 };
441
442 static bool gp_layer_duplicate_object_poll(bContext *C)
443 {
444         ViewLayer *view_layer = CTX_data_view_layer(C);
445         Object *ob = CTX_data_active_object(C);
446         if ((ob == NULL) || (ob->type != OB_GPENCIL))
447                 return false;
448
449         bGPdata *gpd = (bGPdata *)ob->data;
450         bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
451
452         if (gpl == NULL)
453                 return false;
454
455         /* check there are more grease pencil objects */
456         for (Base *base = view_layer->object_bases.first; base; base = base->next) {
457                 if ((base->object != ob) && (base->object->type == OB_GPENCIL))
458                         return true;
459         }
460
461         return false;
462 }
463
464 static int gp_layer_duplicate_object_exec(bContext *C, wmOperator *op)
465 {
466         Main *bmain = CTX_data_main(C);
467         Scene *scene = CTX_data_scene(C);
468         char name[MAX_ID_NAME - 2];
469         RNA_string_get(op->ptr, "object", name);
470
471         if (name[0] == '\0') {
472                 return OPERATOR_CANCELLED;
473         }
474
475         Object *ob_dst = (Object *)BKE_scene_object_find_by_name(scene, name);
476
477         int mode = RNA_enum_get(op->ptr, "mode");
478
479         Object *ob_src = CTX_data_active_object(C);
480         bGPdata *gpd_src = (bGPdata *)ob_src->data;
481         bGPDlayer *gpl_src = BKE_gpencil_layer_getactive(gpd_src);
482
483         /* sanity checks */
484         if (ELEM(NULL, gpd_src, gpl_src, ob_dst)) {
485                 return OPERATOR_CANCELLED;
486         }
487         /* cannot copy itself and check destination type */
488         if ((ob_src == ob_dst) || (ob_dst->type != OB_GPENCIL)) {
489                 return OPERATOR_CANCELLED;
490         }
491
492         bGPdata *gpd_dst = (bGPdata *)ob_dst->data;
493
494         /* make copy of layer */
495         bGPDlayer *gpl_dst = MEM_dupallocN(gpl_src);
496         gpl_dst->prev = gpl_dst->next = NULL;
497         BLI_addtail(&gpd_dst->layers, gpl_dst);
498         BLI_uniquename(&gpd_dst->layers, gpl_dst, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(gpl_dst->info));
499
500         /* copy frames */
501         BLI_listbase_clear(&gpl_dst->frames);
502         for (bGPDframe *gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) {
503
504                 if ((mode == GP_LAYER_COPY_OBJECT_ACT_FRAME) && (gpf_src != gpl_src->actframe)) {
505                         continue;
506                 }
507
508                 /* make a copy of source frame */
509                 bGPDframe *gpf_dst = MEM_dupallocN(gpf_src);
510                 gpf_dst->prev = gpf_dst->next = NULL;
511                 BLI_addtail(&gpl_dst->frames, gpf_dst);
512
513                 /* copy strokes */
514                 BLI_listbase_clear(&gpf_dst->strokes);
515                 for (bGPDstroke *gps_src = gpf_src->strokes.first; gps_src; gps_src = gps_src->next) {
516
517                         /* make copy of source stroke */
518                         bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
519
520                         /* check if material is in destination object,
521                          * otherwise add the slot with the material
522                          */
523                         Material *ma_src = give_current_material(ob_src, gps_src->mat_nr + 1);
524                         int idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
525
526                         /* reasign the stroke material to the right slot in destination object */
527                         gps_dst->mat_nr = idx;
528
529                         /* add new stroke to frame */
530                         BLI_addtail(&gpf_dst->strokes, gps_dst);
531                 }
532         }
533
534         /* notifiers */
535         DEG_id_tag_update(&gpd_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
536         DEG_id_tag_update(&ob_dst->id, ID_RECALC_COPY_ON_WRITE);
537         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
538
539         return OPERATOR_FINISHED;
540 }
541
542 void GPENCIL_OT_layer_duplicate_object(wmOperatorType *ot)
543 {
544         static const EnumPropertyItem copy_mode[] = {
545                 {GP_LAYER_COPY_OBJECT_ALL_FRAME, "ALL", 0, "All Frames", ""},
546                 {GP_LAYER_COPY_OBJECT_ACT_FRAME, "ACTIVE", 0, "Active Frame", ""},
547                 {0, NULL, 0, NULL, NULL},
548         };
549
550         /* identifiers */
551         ot->name = "Duplicate Layer to new Object";
552         ot->idname = "GPENCIL_OT_layer_duplicate_object";
553         ot->description = "Make a copy of the active Grease Pencil layer to new object";
554
555         /* callbacks */
556         ot->exec = gp_layer_duplicate_object_exec;
557         ot->poll = gp_layer_duplicate_object_poll;
558
559         /* flags */
560         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
561
562         ot->prop = RNA_def_string(ot->srna, "object", NULL, MAX_ID_NAME - 2, "Object", "Name of the destination object");
563         RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
564
565         RNA_def_enum(ot->srna, "mode", copy_mode, GP_LAYER_COPY_OBJECT_ALL_FRAME, "Mode", "");
566 }
567
568 /* ********************* Duplicate Frame ************************** */
569 enum {
570         GP_FRAME_DUP_ACTIVE = 0,
571         GP_FRAME_DUP_ALL = 1,
572 };
573
574 static int gp_frame_duplicate_exec(bContext *C, wmOperator *op)
575 {
576         bGPdata *gpd = ED_gpencil_data_get_active(C);
577         bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
578         Depsgraph *depsgraph = CTX_data_depsgraph(C);
579         int cfra_eval = (int)DEG_get_ctime(depsgraph);
580
581         int mode = RNA_enum_get(op->ptr, "mode");
582
583         /* sanity checks */
584         if (ELEM(NULL, gpd, gpl))
585                 return OPERATOR_CANCELLED;
586
587         if (mode == 0) {
588                 BKE_gpencil_frame_addcopy(gpl, cfra_eval);
589         }
590         else {
591                 for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
592                         if ((gpl->flag & GP_LAYER_LOCKED) == 0) {
593                                 BKE_gpencil_frame_addcopy(gpl, cfra_eval);
594                         }
595                 }
596
597         }
598         /* notifiers */
599         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
600         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
601
602         return OPERATOR_FINISHED;
603 }
604
605 void GPENCIL_OT_frame_duplicate(wmOperatorType *ot)
606 {
607         static const EnumPropertyItem duplicate_mode[] = {
608                 {GP_FRAME_DUP_ACTIVE, "ACTIVE", 0, "Active", "Duplicate frame in active layer only"},
609                 {GP_FRAME_DUP_ALL, "ALL", 0, "All", "Duplicate active frames in all layers"},
610                 {0, NULL, 0, NULL, NULL},
611         };
612
613         /* identifiers */
614         ot->name = "Duplicate Frame";
615         ot->idname = "GPENCIL_OT_frame_duplicate";
616         ot->description = "Make a copy of the active Grease Pencil Frame";
617
618         /* callbacks */
619         ot->exec = gp_frame_duplicate_exec;
620         ot->poll = gp_active_layer_poll;
621
622         /* flags */
623         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
624
625         ot->prop = RNA_def_enum(ot->srna, "mode", duplicate_mode, GP_FRAME_DUP_ACTIVE, "Mode", "");
626 }
627
628 /* ********************* Clean Fill Boundaries on Frame ************************** */
629 enum {
630         GP_FRAME_CLEAN_FILL_ACTIVE = 0,
631         GP_FRAME_CLEAN_FILL_ALL = 1,
632 };
633
634 static int gp_frame_clean_fill_exec(bContext *C, wmOperator *op)
635 {
636         bool changed = false;
637         bGPdata *gpd = ED_gpencil_data_get_active(C);
638         int mode = RNA_enum_get(op->ptr, "mode");
639
640         CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
641         {
642                 bGPDframe *init_gpf = gpl->actframe;
643                 if (mode == GP_FRAME_CLEAN_FILL_ALL) {
644                         init_gpf = gpl->frames.first;
645                 }
646
647                 for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
648                         if ((gpf == gpl->actframe) || (mode == GP_FRAME_CLEAN_FILL_ALL)) {
649                                 bGPDstroke *gps, *gpsn;
650
651                                 if (gpf == NULL)
652                                         continue;
653
654                                 /* simply delete strokes which are no fill */
655                                 for (gps = gpf->strokes.first; gps; gps = gpsn) {
656                                         gpsn = gps->next;
657
658                                         /* skip strokes that are invalid for current view */
659                                         if (ED_gpencil_stroke_can_use(C, gps) == false)
660                                                 continue;
661
662                                         /* free stroke */
663                                         if (gps->flag & GP_STROKE_NOFILL) {
664                                                 /* free stroke memory arrays, then stroke itself */
665                                                 if (gps->points) {
666                                                         MEM_freeN(gps->points);
667                                                 }
668                                                 if (gps->dvert) {
669                                                         BKE_gpencil_free_stroke_weights(gps);
670                                                         MEM_freeN(gps->dvert);
671                                                 }
672                                                 MEM_SAFE_FREE(gps->triangles);
673                                                 BLI_freelinkN(&gpf->strokes, gps);
674
675                                                 changed = true;
676                                         }
677                                 }
678                         }
679                 }
680         }
681         CTX_DATA_END;
682
683         /* notifiers */
684         if (changed) {
685                 DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
686                 WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
687         }
688
689         return OPERATOR_FINISHED;
690 }
691
692 void GPENCIL_OT_frame_clean_fill(wmOperatorType *ot)
693 {
694         static const EnumPropertyItem duplicate_mode[] = {
695                 {GP_FRAME_CLEAN_FILL_ACTIVE, "ACTIVE", 0, "Active Frame Only", "Clean active frame only"},
696                 {GP_FRAME_CLEAN_FILL_ALL, "ALL", 0, "All Frames", "Clean all frames in all layers"},
697                 {0, NULL, 0, NULL, NULL},
698         };
699
700         /* identifiers */
701         ot->name = "Clean Fill Boundaries";
702         ot->idname = "GPENCIL_OT_frame_clean_fill";
703         ot->description = "Remove 'no fill' boundary strokes";
704
705         /* callbacks */
706         ot->exec = gp_frame_clean_fill_exec;
707         ot->poll = gp_active_layer_poll;
708
709         /* flags */
710         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
711
712         ot->prop = RNA_def_enum(ot->srna, "mode", duplicate_mode, GP_FRAME_DUP_ACTIVE, "Mode", "");
713 }
714
715 /* ********************* Clean Loose Boundaries on Frame ************************** */
716 static int gp_frame_clean_loose_exec(bContext *C, wmOperator *op)
717 {
718         bool changed = false;
719         bGPdata *gpd = ED_gpencil_data_get_active(C);
720         int limit = RNA_int_get(op->ptr, "limit");
721         const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
722
723         CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
724         {
725                 bGPDframe *init_gpf = gpl->actframe;
726                 bGPDstroke *gps = NULL;
727                 bGPDstroke *gpsn = NULL;
728                 if (is_multiedit) {
729                         init_gpf = gpl->frames.first;
730                 }
731
732                 for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
733                         if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
734                                 if (gpf == NULL)
735                                         continue;
736
737                                 /* simply delete strokes which are no loose */
738                                 for (gps = gpf->strokes.first; gps; gps = gpsn) {
739                                         gpsn = gps->next;
740
741                                         /* skip strokes that are invalid for current view */
742                                         if (ED_gpencil_stroke_can_use(C, gps) == false)
743                                                 continue;
744
745                                         /* free stroke */
746                                         if (gps->totpoints <= limit) {
747                                                 /* free stroke memory arrays, then stroke itself */
748                                                 if (gps->points) {
749                                                         MEM_freeN(gps->points);
750                                                 }
751                                                 if (gps->dvert) {
752                                                         BKE_gpencil_free_stroke_weights(gps);
753                                                         MEM_freeN(gps->dvert);
754                                                 }
755                                                 MEM_SAFE_FREE(gps->triangles);
756                                                 BLI_freelinkN(&gpf->strokes, gps);
757
758                                                 changed = true;
759                                         }
760                                 }
761                         }
762
763                         /* if not multiedit, exit loop*/
764                         if (!is_multiedit) {
765                                 break;
766                         }
767                 }
768         }
769         CTX_DATA_END;
770
771         /* notifiers */
772         if (changed) {
773                 DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
774                 WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
775         }
776
777         return OPERATOR_FINISHED;
778 }
779
780 void GPENCIL_OT_frame_clean_loose(wmOperatorType *ot)
781 {
782         /* identifiers */
783         ot->name = "Clean Loose points";
784         ot->idname = "GPENCIL_OT_frame_clean_loose";
785         ot->description = "Remove loose points";
786
787         /* callbacks */
788         ot->exec = gp_frame_clean_loose_exec;
789         ot->poll = gp_active_layer_poll;
790
791         /* flags */
792         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
793
794         RNA_def_int(ot->srna, "limit", 1, 1, INT_MAX, "Limit", "Number of points to consider stroke as loose", 1, INT_MAX);
795 }
796
797 /* *********************** Hide Layers ******************************** */
798
799 static int gp_hide_exec(bContext *C, wmOperator *op)
800 {
801         bGPdata *gpd = ED_gpencil_data_get_active(C);
802         bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd);
803         bool unselected = RNA_boolean_get(op->ptr, "unselected");
804
805         /* sanity checks */
806         if (ELEM(NULL, gpd, layer))
807                 return OPERATOR_CANCELLED;
808
809         if (unselected) {
810                 bGPDlayer *gpl;
811
812                 /* hide unselected */
813                 for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
814                         if (gpl != layer) {
815                                 gpl->flag |= GP_LAYER_HIDE;
816                         }
817                 }
818         }
819         else {
820                 /* hide selected/active */
821                 layer->flag |= GP_LAYER_HIDE;
822         }
823
824         /* notifiers */
825         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
826         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
827
828         return OPERATOR_FINISHED;
829 }
830
831 void GPENCIL_OT_hide(wmOperatorType *ot)
832 {
833         /* identifiers */
834         ot->name = "Hide Layer(s)";
835         ot->idname = "GPENCIL_OT_hide";
836         ot->description = "Hide selected/unselected Grease Pencil layers";
837
838         /* callbacks */
839         ot->exec = gp_hide_exec;
840         ot->poll = gp_active_layer_poll; /* NOTE: we need an active layer to play with */
841
842         /* flags */
843         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
844
845         /* props */
846         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers");
847 }
848
849 /* ********************** Show All Layers ***************************** */
850
851 /* poll callback for showing layers */
852 static bool gp_reveal_poll(bContext *C)
853 {
854         return ED_gpencil_data_get_active(C) != NULL;
855 }
856
857 static void gp_reveal_select_frame(bContext *C, bGPDframe *frame, bool select)
858 {
859         bGPDstroke *gps;
860         for (gps = frame->strokes.first; gps; gps = gps->next) {
861
862                 /* only deselect strokes that are valid in this view */
863                 if (ED_gpencil_stroke_can_use(C, gps)) {
864
865                         /* (de)select points */
866                         int i;
867                         bGPDspoint *pt;
868                         for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
869                                 SET_FLAG_FROM_TEST(pt->flag, select, GP_SPOINT_SELECT);
870                         }
871
872                         /* (de)select stroke */
873                         SET_FLAG_FROM_TEST(gps->flag, select, GP_STROKE_SELECT);
874                 }
875         }
876 }
877
878 static int gp_reveal_exec(bContext *C, wmOperator *op)
879 {
880         bGPdata *gpd = ED_gpencil_data_get_active(C);
881         bGPDlayer *gpl;
882         const bool select = RNA_boolean_get(op->ptr, "select");
883
884         /* sanity checks */
885         if (gpd == NULL)
886                 return OPERATOR_CANCELLED;
887
888         for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
889
890                 if (gpl->flag & GP_LAYER_HIDE) {
891                         gpl->flag &= ~GP_LAYER_HIDE;
892
893                         /* select or deselect if requested, only on hidden layers */
894                         if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
895                                 if (select) {
896                                         /* select all strokes on active frame only (same as select all operator) */
897                                         if (gpl->actframe) {
898                                                 gp_reveal_select_frame(C, gpl->actframe, true);
899                                         }
900                                 }
901                                 else {
902                                         /* deselect strokes on all frames (same as deselect all operator) */
903                                         bGPDframe *gpf;
904                                         for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
905                                                 gp_reveal_select_frame(C, gpf, false);
906                                         }
907                                 }
908                         }
909                 }
910         }
911
912         /* notifiers */
913         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
914         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
915
916         return OPERATOR_FINISHED;
917 }
918
919 void GPENCIL_OT_reveal(wmOperatorType *ot)
920 {
921         /* identifiers */
922         ot->name = "Show All Layers";
923         ot->idname = "GPENCIL_OT_reveal";
924         ot->description = "Show all Grease Pencil layers";
925
926         /* callbacks */
927         ot->exec = gp_reveal_exec;
928         ot->poll = gp_reveal_poll;
929
930         /* flags */
931         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
932
933         /* props */
934         RNA_def_boolean(ot->srna, "select", true, "Select", "");
935 }
936
937 /* ***************** Lock/Unlock All Layers ************************ */
938
939 static int gp_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
940 {
941         bGPdata *gpd = ED_gpencil_data_get_active(C);
942         bGPDlayer *gpl;
943
944         /* sanity checks */
945         if (gpd == NULL)
946                 return OPERATOR_CANCELLED;
947
948         /* make all layers non-editable */
949         for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
950                 gpl->flag |= GP_LAYER_LOCKED;
951         }
952
953         /* notifiers */
954         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
955         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
956
957         return OPERATOR_FINISHED;
958 }
959
960 void GPENCIL_OT_lock_all(wmOperatorType *ot)
961 {
962         /* identifiers */
963         ot->name = "Lock All Layers";
964         ot->idname = "GPENCIL_OT_lock_all";
965         ot->description = "Lock all Grease Pencil layers to prevent them from being accidentally modified";
966
967         /* callbacks */
968         ot->exec = gp_lock_all_exec;
969         ot->poll = gp_reveal_poll; /* XXX: could use dedicated poll later */
970
971         /* flags */
972         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
973 }
974
975 /* -------------------------- */
976
977 static int gp_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
978 {
979         bGPdata *gpd = ED_gpencil_data_get_active(C);
980         bGPDlayer *gpl;
981
982         /* sanity checks */
983         if (gpd == NULL)
984                 return OPERATOR_CANCELLED;
985
986         /* make all layers editable again */
987         for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
988                 gpl->flag &= ~GP_LAYER_LOCKED;
989         }
990
991         /* notifiers */
992         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
993         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
994
995         return OPERATOR_FINISHED;
996 }
997
998 void GPENCIL_OT_unlock_all(wmOperatorType *ot)
999 {
1000         /* identifiers */
1001         ot->name = "Unlock All Layers";
1002         ot->idname = "GPENCIL_OT_unlock_all";
1003         ot->description = "Unlock all Grease Pencil layers so that they can be edited";
1004
1005         /* callbacks */
1006         ot->exec = gp_unlock_all_exec;
1007         ot->poll = gp_reveal_poll; /* XXX: could use dedicated poll later */
1008
1009         /* flags */
1010         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1011 }
1012
1013 /* ********************** Isolate Layer **************************** */
1014
1015 static int gp_isolate_layer_exec(bContext *C, wmOperator *op)
1016 {
1017         bGPdata *gpd = ED_gpencil_data_get_active(C);
1018         bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd);
1019         bGPDlayer *gpl;
1020         int flags = GP_LAYER_LOCKED;
1021         bool isolate = false;
1022
1023         if (RNA_boolean_get(op->ptr, "affect_visibility"))
1024                 flags |= GP_LAYER_HIDE;
1025
1026         if (ELEM(NULL, gpd, layer)) {
1027                 BKE_report(op->reports, RPT_ERROR, "No active layer to isolate");
1028                 return OPERATOR_CANCELLED;
1029         }
1030
1031         /* Test whether to isolate or clear all flags */
1032         for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1033                 /* Skip if this is the active layer */
1034                 if (gpl == layer)
1035                         continue;
1036
1037                 /* If the flags aren't set, that means that the layer is
1038                  * not alone, so we have some layers to isolate still
1039                  */
1040                 if ((gpl->flag & flags) == 0) {
1041                         isolate = true;
1042                         break;
1043                 }
1044         }
1045
1046         /* Set/Clear flags as appropriate */
1047         /* TODO: Include onionskinning on this list? */
1048         if (isolate) {
1049                 /* Set flags on all "other" layers */
1050                 for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1051                         if (gpl == layer)
1052                                 continue;
1053                         else
1054                                 gpl->flag |= flags;
1055                 }
1056         }
1057         else {
1058                 /* Clear flags - Restore everything else */
1059                 for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1060                         gpl->flag &= ~flags;
1061                 }
1062         }
1063
1064         /* notifiers */
1065         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1066         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
1067
1068         return OPERATOR_FINISHED;
1069 }
1070
1071 void GPENCIL_OT_layer_isolate(wmOperatorType *ot)
1072 {
1073         /* identifiers */
1074         ot->name = "Isolate Layer";
1075         ot->idname = "GPENCIL_OT_layer_isolate";
1076         ot->description = "Toggle whether the active layer is the only one that can be edited and/or visible";
1077
1078         /* callbacks */
1079         ot->exec = gp_isolate_layer_exec;
1080         ot->poll = gp_active_layer_poll;
1081
1082         /* flags */
1083         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1084
1085         /* properties */
1086         RNA_def_boolean(ot->srna, "affect_visibility", false, "Affect Visibility",
1087                         "In addition to toggling the editability, also affect the visibility");
1088 }
1089
1090 /* ********************** Merge Layer with the next layer **************************** */
1091
1092 static int gp_merge_layer_exec(bContext *C, wmOperator *op)
1093 {
1094         bGPdata *gpd = ED_gpencil_data_get_active(C);
1095         bGPDlayer *gpl_next = BKE_gpencil_layer_getactive(gpd);
1096         bGPDlayer *gpl_current = gpl_next->prev;
1097
1098         if (ELEM(NULL, gpd, gpl_current, gpl_next)) {
1099                 BKE_report(op->reports, RPT_ERROR, "No layers to merge");
1100                 return OPERATOR_CANCELLED;
1101         }
1102
1103         /* Collect frames of gpl_current in hash table to avoid O(n^2) lookups */
1104         GHash *gh_frames_cur = BLI_ghash_int_new_ex(__func__, 64);
1105         for (bGPDframe *gpf = gpl_current->frames.first; gpf; gpf = gpf->next) {
1106                 BLI_ghash_insert(gh_frames_cur, POINTER_FROM_INT(gpf->framenum), gpf);
1107         }
1108
1109         /* read all frames from next layer and add any missing in current layer */
1110         for (bGPDframe *gpf = gpl_next->frames.first; gpf; gpf = gpf->next) {
1111                 /* try to find frame in current layer */
1112                 bGPDframe *frame = BLI_ghash_lookup(gh_frames_cur, POINTER_FROM_INT(gpf->framenum));
1113                 if (!frame) {
1114                         bGPDframe *actframe = BKE_gpencil_layer_getframe(gpl_current, gpf->framenum, GP_GETFRAME_USE_PREV);
1115                         frame = BKE_gpencil_frame_addnew(gpl_current, gpf->framenum);
1116                         /* duplicate strokes of current active frame */
1117                         if (actframe) {
1118                                 BKE_gpencil_frame_copy_strokes(actframe, frame);
1119                         }
1120                 }
1121                 /* add to tail all strokes */
1122                 BLI_movelisttolist(&frame->strokes, &gpf->strokes);
1123         }
1124
1125         /* Now delete next layer */
1126         BKE_gpencil_layer_delete(gpd, gpl_next);
1127         BLI_ghash_free(gh_frames_cur, NULL, NULL);
1128
1129         /* notifiers */
1130         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1131         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
1132
1133         return OPERATOR_FINISHED;
1134 }
1135
1136 void GPENCIL_OT_layer_merge(wmOperatorType *ot)
1137 {
1138         /* identifiers */
1139         ot->name = "Merge Down";
1140         ot->idname = "GPENCIL_OT_layer_merge";
1141         ot->description = "Merge the current layer with the layer below";
1142
1143         /* callbacks */
1144         ot->exec = gp_merge_layer_exec;
1145         ot->poll = gp_active_layer_poll;
1146
1147         /* flags */
1148         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1149 }
1150
1151 /* ********************** Change Layer ***************************** */
1152
1153 static int gp_layer_change_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(evt))
1154 {
1155         uiPopupMenu *pup;
1156         uiLayout *layout;
1157
1158         /* call the menu, which will call this operator again, hence the canceled */
1159         pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
1160         layout = UI_popup_menu_layout(pup);
1161         uiItemsEnumO(layout, "GPENCIL_OT_layer_change", "layer");
1162         UI_popup_menu_end(C, pup);
1163
1164         return OPERATOR_INTERFACE;
1165 }
1166
1167 static int gp_layer_change_exec(bContext *C, wmOperator *op)
1168 {
1169         bGPdata *gpd = CTX_data_gpencil_data(C);
1170         bGPDlayer *gpl = NULL;
1171         int layer_num = RNA_enum_get(op->ptr, "layer");
1172
1173         /* Get layer or create new one */
1174         if (layer_num == -1) {
1175                 /* Create layer */
1176                 gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
1177         }
1178         else {
1179                 /* Try to get layer */
1180                 gpl = BLI_findlink(&gpd->layers, layer_num);
1181
1182                 if (gpl == NULL) {
1183                         BKE_reportf(op->reports, RPT_ERROR, "Cannot change to non-existent layer (index = %d)", layer_num);
1184                         return OPERATOR_CANCELLED;
1185                 }
1186         }
1187
1188         /* Set active layer */
1189         BKE_gpencil_layer_setactive(gpd, gpl);
1190
1191         /* updates */
1192         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1193         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
1194
1195         return OPERATOR_FINISHED;
1196 }
1197
1198 void GPENCIL_OT_layer_change(wmOperatorType *ot)
1199 {
1200         /* identifiers */
1201         ot->name = "Change Layer";
1202         ot->idname = "GPENCIL_OT_layer_change";
1203         ot->description = "Change active Grease Pencil layer";
1204
1205         /* callbacks */
1206         ot->invoke = gp_layer_change_invoke;
1207         ot->exec = gp_layer_change_exec;
1208         ot->poll = gp_active_layer_poll;
1209
1210         /* flags */
1211         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1212
1213         /* gp layer to use (dynamic enum) */
1214         ot->prop = RNA_def_enum(ot->srna, "layer", DummyRNA_DEFAULT_items, 0, "Grease Pencil Layer", "");
1215         RNA_def_enum_funcs(ot->prop, ED_gpencil_layers_with_new_enum_itemf);
1216 }
1217
1218 /* ************************************************ */
1219
1220 /* ******************* Arrange Stroke Up/Down in drawing order ************************** */
1221
1222 enum {
1223         GP_STROKE_MOVE_UP = -1,
1224         GP_STROKE_MOVE_DOWN = 1,
1225         GP_STROKE_MOVE_TOP = 2,
1226         GP_STROKE_MOVE_BOTTOM = 3,
1227 };
1228
1229 static int gp_stroke_arrange_exec(bContext *C, wmOperator *op)
1230 {
1231         Object *ob = CTX_data_active_object(C);
1232         bGPdata *gpd = ED_gpencil_data_get_active(C);
1233         bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
1234         bGPDstroke *gps;
1235
1236         /* sanity checks */
1237         if (ELEM(NULL, gpd, gpl, gpl->actframe)) {
1238                 return OPERATOR_CANCELLED;
1239         }
1240
1241         const int direction = RNA_enum_get(op->ptr, "direction");
1242
1243         for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1244                 /* temp listbase to store selected strokes by layer */
1245                 ListBase selected = { NULL };
1246                 bGPDframe *gpf = gpl->actframe;
1247                 if (gpl->flag & GP_LAYER_LOCKED) {
1248                         continue;
1249                 }
1250
1251                 if (gpf == NULL) {
1252                         continue;
1253                 }
1254                 bool gpf_lock = false;
1255                 /* verify if any selected stroke is in the extreme of the stack and select to move */
1256                 for (gps = gpf->strokes.first; gps; gps = gps->next) {
1257                         /* only if selected */
1258                         if (gps->flag & GP_STROKE_SELECT) {
1259                                 /* skip strokes that are invalid for current view */
1260                                 if (ED_gpencil_stroke_can_use(C, gps) == false) {
1261                                         continue;
1262                                 }
1263                                 /* check if the color is editable */
1264                                 if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
1265                                         continue;
1266                                 }
1267                                 /* some stroke is already at front*/
1268                                 if ((direction == GP_STROKE_MOVE_TOP) || (direction == GP_STROKE_MOVE_UP)) {
1269                                         if (gps == gpf->strokes.last) {
1270                                                 gpf_lock = true;
1271                                                 continue;
1272                                         }
1273                                 }
1274                                 /* some stroke is already at botom */
1275                                 if ((direction == GP_STROKE_MOVE_BOTTOM) || (direction == GP_STROKE_MOVE_DOWN)) {
1276                                         if (gps == gpf->strokes.first) {
1277                                                 gpf_lock = true;
1278                                                 continue;
1279                                         }
1280                                 }
1281                                 /* add to list (if not locked) */
1282                                 if (!gpf_lock) {
1283                                         BLI_addtail(&selected, BLI_genericNodeN(gps));
1284                                 }
1285                         }
1286                 }
1287                 /* Now do the movement of the stroke */
1288                 if (!gpf_lock) {
1289                         switch (direction) {
1290                                 /* Bring to Front */
1291                                 case GP_STROKE_MOVE_TOP:
1292                                         for (LinkData *link = selected.first; link; link = link->next) {
1293                                                 gps = link->data;
1294                                                 BLI_remlink(&gpf->strokes, gps);
1295                                                 BLI_addtail(&gpf->strokes, gps);
1296                                         }
1297                                         break;
1298                                 /* Bring Forward */
1299                                 case GP_STROKE_MOVE_UP:
1300                                         for (LinkData *link = selected.last; link; link = link->prev) {
1301                                                 gps = link->data;
1302                                                 BLI_listbase_link_move(&gpf->strokes, gps, 1);
1303                                         }
1304                                         break;
1305                                 /* Send Backward */
1306                                 case GP_STROKE_MOVE_DOWN:
1307                                         for (LinkData *link = selected.first; link; link = link->next) {
1308                                                 gps = link->data;
1309                                                 BLI_listbase_link_move(&gpf->strokes, gps, -1);
1310                                         }
1311                                         break;
1312                                 /* Send to Back */
1313                                 case GP_STROKE_MOVE_BOTTOM:
1314                                         for (LinkData *link = selected.last; link; link = link->prev) {
1315                                                 gps = link->data;
1316                                                 BLI_remlink(&gpf->strokes, gps);
1317                                                 BLI_addhead(&gpf->strokes, gps);
1318                                         }
1319                                         break;
1320                                 default:
1321                                         BLI_assert(0);
1322                                         break;
1323                         }
1324                 }
1325                 BLI_freelistN(&selected);
1326         }
1327
1328         /* notifiers */
1329         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1330         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
1331
1332         return OPERATOR_FINISHED;
1333 }
1334
1335 void GPENCIL_OT_stroke_arrange(wmOperatorType *ot)
1336 {
1337         static const EnumPropertyItem slot_move[] = {
1338                 {GP_STROKE_MOVE_UP, "UP", 0, "Bring Forward", ""},
1339                 {GP_STROKE_MOVE_DOWN, "DOWN", 0, "Send Backward", ""},
1340                 {GP_STROKE_MOVE_TOP, "TOP", 0, "Bring to Front", ""},
1341                 {GP_STROKE_MOVE_BOTTOM, "BOTTOM", 0, "Send to Back", ""},
1342                 {0, NULL, 0, NULL, NULL }
1343         };
1344
1345         /* identifiers */
1346         ot->name = "Arrange Stroke";
1347         ot->idname = "GPENCIL_OT_stroke_arrange";
1348         ot->description = "Arrange selected strokes up/down in the drawing order of the active layer";
1349
1350         /* callbacks */
1351         ot->exec = gp_stroke_arrange_exec;
1352         ot->poll = gp_active_layer_poll;
1353
1354         /* flags */
1355         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1356
1357         /* properties */
1358         ot->prop = RNA_def_enum(ot->srna, "direction", slot_move, GP_STROKE_MOVE_UP, "Direction", "");
1359 }
1360
1361 /* ******************* Move Stroke to new color ************************** */
1362
1363 static int gp_stroke_change_color_exec(bContext *C, wmOperator *op)
1364 {
1365         Main *bmain = CTX_data_main(C);
1366         Material *ma = NULL;
1367         char name[MAX_ID_NAME - 2];
1368         RNA_string_get(op->ptr, "material", name);
1369
1370         bGPdata *gpd = ED_gpencil_data_get_active(C);
1371         Object *ob = CTX_data_active_object(C);
1372         if (name[0] == '\0') {
1373                 ma = give_current_material(ob, ob->actcol);
1374         }
1375         else {
1376                 ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, name);
1377                 if (ma == NULL) {
1378                         return OPERATOR_CANCELLED;
1379                 }
1380         }
1381         /* try to find slot */
1382         int idx = BKE_gpencil_object_material_get_index(ob, ma);
1383         if (idx < 0) {
1384                 return OPERATOR_CANCELLED;
1385         }
1386
1387         /* sanity checks */
1388         if (ELEM(NULL, gpd)) {
1389                 return OPERATOR_CANCELLED;
1390         }
1391
1392         const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
1393         if (ELEM(NULL, ma)) {
1394                 return OPERATOR_CANCELLED;
1395         }
1396
1397         /* loop all strokes */
1398         CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
1399         {
1400                 bGPDframe *init_gpf = gpl->actframe;
1401                 if (is_multiedit) {
1402                         init_gpf = gpl->frames.first;
1403                 }
1404
1405                 for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
1406                         if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
1407                                 if (gpf == NULL)
1408                                         continue;
1409
1410                                 for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
1411                                         /* only if selected */
1412                                         if (gps->flag & GP_STROKE_SELECT) {
1413                                                 /* skip strokes that are invalid for current view */
1414                                                 if (ED_gpencil_stroke_can_use(C, gps) == false)
1415                                                         continue;
1416                                                 /* check if the color is editable */
1417                                                 if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false)
1418                                                         continue;
1419
1420                                                 /* assign new color */
1421                                                 gps->mat_nr = idx;
1422                                         }
1423                                 }
1424                         }
1425                         /* if not multiedit, exit loop*/
1426                         if (!is_multiedit) {
1427                                 break;
1428                         }
1429
1430                 }
1431         }
1432         CTX_DATA_END;
1433
1434         /* notifiers */
1435         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1436         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
1437
1438         return OPERATOR_FINISHED;
1439 }
1440
1441 void GPENCIL_OT_stroke_change_color(wmOperatorType *ot)
1442 {
1443         /* identifiers */
1444         ot->name = "Change Stroke Color";
1445         ot->idname = "GPENCIL_OT_stroke_change_color";
1446         ot->description = "Move selected strokes to active material";
1447
1448         /* callbacks */
1449         ot->exec = gp_stroke_change_color_exec;
1450         ot->poll = gp_active_layer_poll;
1451
1452         /* flags */
1453         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1454
1455         RNA_def_string(ot->srna, "material", NULL, MAX_ID_NAME - 2, "Material", "Name of the material");
1456
1457 }
1458
1459 /* ******************* Lock color of non selected Strokes colors ************************** */
1460
1461 static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op))
1462 {
1463         bGPdata *gpd = ED_gpencil_data_get_active(C);
1464
1465         Object *ob = CTX_data_active_object(C);
1466
1467         short *totcol = give_totcolp(ob);
1468
1469         /* sanity checks */
1470         if (ELEM(NULL, gpd))
1471                 return OPERATOR_CANCELLED;
1472
1473         /* first lock all colors */
1474         for (short i = 0; i < *totcol; i++) {
1475                 Material *tmp_ma = give_current_material(ob, i + 1);
1476                 tmp_ma->gp_style->flag |= GP_STYLE_COLOR_LOCKED;
1477                 DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
1478         }
1479
1480         /* loop all selected strokes and unlock any color */
1481         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1482                 /* only editable and visible layers are considered */
1483                 if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) {
1484                         for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
1485                                 /* only if selected */
1486                                 if (gps->flag & GP_STROKE_SELECT) {
1487                                         /* skip strokes that are invalid for current view */
1488                                         if (ED_gpencil_stroke_can_use(C, gps) == false) {
1489                                                 continue;
1490                                         }
1491                                         /* unlock color */
1492                                         Material *tmp_ma = give_current_material(ob, gps->mat_nr + 1);
1493
1494                                         tmp_ma->gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
1495                                         DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
1496                                 }
1497                         }
1498                 }
1499         }
1500         /* updates */
1501         DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
1502
1503         /* copy on write tag is needed, or else no refresh happens */
1504         DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
1505
1506         /* notifiers */
1507         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1508         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
1509
1510         return OPERATOR_FINISHED;
1511 }
1512
1513 void GPENCIL_OT_stroke_lock_color(wmOperatorType *ot)
1514 {
1515         /* identifiers */
1516         ot->name = "Lock Unused Colors";
1517         ot->idname = "GPENCIL_OT_stroke_lock_color";
1518         ot->description = "Lock any color not used in any selected stroke";
1519
1520         /* api callbacks */
1521         ot->exec = gp_stroke_lock_color_exec;
1522         ot->poll = gp_active_layer_poll;
1523
1524         /* flags */
1525         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1526 }
1527
1528 /* ************************************************ */
1529 /* Drawing Brushes Operators */
1530
1531 /* ******************* Brush create presets ************************** */
1532 static int gp_brush_presets_create_exec(bContext *C, wmOperator *UNUSED(op))
1533 {
1534         BKE_brush_gpencil_presets(C);
1535
1536         /* notifiers */
1537         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
1538
1539         return OPERATOR_FINISHED;
1540 }
1541
1542 void GPENCIL_OT_brush_presets_create(wmOperatorType *ot)
1543 {
1544         /* identifiers */
1545         ot->name = "Create Preset Brushes";
1546         ot->idname = "GPENCIL_OT_brush_presets_create";
1547         ot->description = "Create a set of predefined Grease Pencil drawing brushes";
1548
1549         /* api callbacks */
1550         ot->exec = gp_brush_presets_create_exec;
1551
1552         /* flags */
1553         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1554
1555 }
1556
1557 /*********************** Vertex Groups ***********************************/
1558
1559 static bool gpencil_vertex_group_poll(bContext *C)
1560 {
1561         Object *ob = CTX_data_active_object(C);
1562
1563         if ((ob) && (ob->type == OB_GPENCIL)) {
1564                 if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && ob->defbase.first) {
1565                         if (ELEM(ob->mode,
1566                                  OB_MODE_EDIT_GPENCIL,
1567                                  OB_MODE_SCULPT_GPENCIL))
1568                         {
1569                                 return true;
1570                         }
1571                 }
1572         }
1573
1574         return false;
1575 }
1576
1577 static bool gpencil_vertex_group_weight_poll(bContext *C)
1578 {
1579         Object *ob = CTX_data_active_object(C);
1580
1581         if ((ob) && (ob->type == OB_GPENCIL)) {
1582                 if (!ID_IS_LINKED(ob) && !ID_IS_LINKED(ob->data) && ob->defbase.first) {
1583                         if (ob->mode == OB_MODE_WEIGHT_GPENCIL) {
1584                                 return true;
1585                         }
1586                 }
1587         }
1588
1589         return false;
1590 }
1591
1592 static int gpencil_vertex_group_assign_exec(bContext *C, wmOperator *UNUSED(op))
1593 {
1594         ToolSettings *ts = CTX_data_tool_settings(C);
1595         Object *ob = CTX_data_active_object(C);
1596
1597         /* sanity checks */
1598         if (ELEM(NULL, ts, ob, ob->data))
1599                 return OPERATOR_CANCELLED;
1600
1601         ED_gpencil_vgroup_assign(C, ob, ts->vgroup_weight);
1602
1603         /* notifiers */
1604         bGPdata *gpd = ob->data;
1605         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1606         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
1607
1608         return OPERATOR_FINISHED;
1609 }
1610
1611 void GPENCIL_OT_vertex_group_assign(wmOperatorType *ot)
1612 {
1613         /* identifiers */
1614         ot->name = "Assign to Vertex Group";
1615         ot->idname = "GPENCIL_OT_vertex_group_assign";
1616         ot->description = "Assign the selected vertices to the active vertex group";
1617
1618         /* api callbacks */
1619         ot->poll = gpencil_vertex_group_poll;
1620         ot->exec = gpencil_vertex_group_assign_exec;
1621
1622         /* flags */
1623         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1624 }
1625
1626 /* remove point from vertex group */
1627 static int gpencil_vertex_group_remove_from_exec(bContext *C, wmOperator *UNUSED(op))
1628 {
1629         Object *ob = CTX_data_active_object(C);
1630
1631         /* sanity checks */
1632         if (ELEM(NULL, ob, ob->data))
1633                 return OPERATOR_CANCELLED;
1634
1635         ED_gpencil_vgroup_remove(C, ob);
1636
1637         /* notifiers */
1638         bGPdata *gpd = ob->data;
1639         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1640         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
1641
1642         return OPERATOR_FINISHED;
1643 }
1644
1645 void GPENCIL_OT_vertex_group_remove_from(wmOperatorType *ot)
1646 {
1647         /* identifiers */
1648         ot->name = "Remove from Vertex Group";
1649         ot->idname = "GPENCIL_OT_vertex_group_remove_from";
1650         ot->description = "Remove the selected vertices from active or all vertex group(s)";
1651
1652         /* api callbacks */
1653         ot->poll = gpencil_vertex_group_poll;
1654         ot->exec = gpencil_vertex_group_remove_from_exec;
1655
1656         /* flags */
1657         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1658
1659 }
1660
1661 static int gpencil_vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
1662 {
1663         Object *ob = CTX_data_active_object(C);
1664
1665         /* sanity checks */
1666         if (ELEM(NULL, ob, ob->data))
1667                 return OPERATOR_CANCELLED;
1668
1669         ED_gpencil_vgroup_select(C, ob);
1670
1671         /* notifiers */
1672         bGPdata *gpd = ob->data;
1673         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1674         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
1675
1676         return OPERATOR_FINISHED;
1677 }
1678
1679 void GPENCIL_OT_vertex_group_select(wmOperatorType *ot)
1680 {
1681         /* identifiers */
1682         ot->name = "Select Vertex Group";
1683         ot->idname = "GPENCIL_OT_vertex_group_select";
1684         ot->description = "Select all the vertices assigned to the active vertex group";
1685
1686         /* api callbacks */
1687         ot->poll = gpencil_vertex_group_poll;
1688         ot->exec = gpencil_vertex_group_select_exec;
1689
1690         /* flags */
1691         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1692 }
1693
1694 static int gpencil_vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
1695 {
1696         Object *ob = CTX_data_active_object(C);
1697
1698         /* sanity checks */
1699         if (ELEM(NULL, ob, ob->data))
1700                 return OPERATOR_CANCELLED;
1701
1702         ED_gpencil_vgroup_deselect(C, ob);
1703
1704         /* notifiers */
1705         bGPdata *gpd = ob->data;
1706         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1707         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
1708
1709         return OPERATOR_FINISHED;
1710 }
1711
1712 void GPENCIL_OT_vertex_group_deselect(wmOperatorType *ot)
1713 {
1714         /* identifiers */
1715         ot->name = "Deselect Vertex Group";
1716         ot->idname = "GPENCIL_OT_vertex_group_deselect";
1717         ot->description = "Deselect all selected vertices assigned to the active vertex group";
1718
1719         /* api callbacks */
1720         ot->poll = gpencil_vertex_group_poll;
1721         ot->exec = gpencil_vertex_group_deselect_exec;
1722
1723         /* flags */
1724         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1725 }
1726
1727 /* invert */
1728 static int gpencil_vertex_group_invert_exec(bContext *C, wmOperator *UNUSED(op))
1729 {
1730         ToolSettings *ts = CTX_data_tool_settings(C);
1731         Object *ob = CTX_data_active_object(C);
1732
1733         /* sanity checks */
1734         if (ELEM(NULL, ts, ob, ob->data))
1735                 return OPERATOR_CANCELLED;
1736
1737         MDeformVert *dvert;
1738         const int def_nr = ob->actdef - 1;
1739         if (!BLI_findlink(&ob->defbase, def_nr))
1740                 return OPERATOR_CANCELLED;
1741
1742         CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
1743         {
1744                 for (int i = 0; i < gps->totpoints; i++) {
1745                         dvert = &gps->dvert[i];
1746                         MDeformWeight *dw = defvert_find_index(dvert, def_nr);
1747                         if (dw == NULL) {
1748                                 defvert_add_index_notest(dvert, def_nr, 1.0f);
1749                         }
1750                         else if (dw->weight == 1.0f) {
1751                                 defvert_remove_group(dvert, dw);
1752                         }
1753                         else {
1754                                 dw->weight = 1.0f - dw->weight;
1755                         }
1756                 }
1757         }
1758         CTX_DATA_END;
1759
1760         /* notifiers */
1761         bGPdata *gpd = ob->data;
1762         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1763         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
1764
1765         return OPERATOR_FINISHED;
1766 }
1767
1768 void GPENCIL_OT_vertex_group_invert(wmOperatorType *ot)
1769 {
1770         /* identifiers */
1771         ot->name = "Invert Vertex Group";
1772         ot->idname = "GPENCIL_OT_vertex_group_invert";
1773         ot->description = "Invert weights to the active vertex group";
1774
1775         /* api callbacks */
1776         ot->poll = gpencil_vertex_group_weight_poll;
1777         ot->exec = gpencil_vertex_group_invert_exec;
1778
1779         /* flags */
1780         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1781 }
1782
1783 /* smooth */
1784 static int gpencil_vertex_group_smooth_exec(bContext *C, wmOperator *op)
1785 {
1786         const float fac = RNA_float_get(op->ptr, "factor");
1787         const int repeat = RNA_int_get(op->ptr, "repeat");
1788
1789         ToolSettings *ts = CTX_data_tool_settings(C);
1790         Object *ob = CTX_data_active_object(C);
1791
1792         /* sanity checks */
1793         if (ELEM(NULL, ts, ob, ob->data))
1794                 return OPERATOR_CANCELLED;
1795
1796         bGPDspoint *pta, *ptb, *ptc;
1797         MDeformVert *dverta, *dvertb;
1798
1799         const int def_nr = ob->actdef - 1;
1800         if (!BLI_findlink(&ob->defbase, def_nr))
1801                 return OPERATOR_CANCELLED;
1802
1803         CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
1804         {
1805                 if (gps->dvert == NULL) {
1806                         continue;
1807                 }
1808
1809                 for (int s = 0; s < repeat; s++) {
1810                         for (int i = 0; i < gps->totpoints; i++) {
1811                                 /* previous point */
1812                                 if (i > 0) {
1813                                         pta = &gps->points[i - 1];
1814                                         dverta = &gps->dvert[i - 1];
1815                                 }
1816                                 else {
1817                                         pta = &gps->points[i];
1818                                         dverta = &gps->dvert[i];
1819                                 }
1820                                 /* current */
1821                                 ptb = &gps->points[i];
1822                                 dvertb = &gps->dvert[i];
1823                                 /* next point */
1824                                 if (i + 1 < gps->totpoints) {
1825                                         ptc = &gps->points[i + 1];
1826                                 }
1827                                 else {
1828                                         ptc = &gps->points[i];
1829                                 }
1830
1831                                 float wa = defvert_find_weight(dverta, def_nr);
1832                                 float wb = defvert_find_weight(dvertb, def_nr);
1833
1834                                 /* the optimal value is the corresponding to the interpolation of the weight
1835                                  * at the distance of point b
1836                                  */
1837                                 const float opfac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
1838                                 const float optimal = interpf(wa, wb, opfac);
1839                                 /* Based on influence factor, blend between original and optimal */
1840                                 MDeformWeight *dw = defvert_verify_index(dvertb, def_nr);
1841                                 if (dw) {
1842                                         dw->weight = interpf(wb, optimal, fac);
1843                                         CLAMP(dw->weight, 0.0, 1.0f);
1844                                 }
1845                         }
1846                 }
1847         }
1848         CTX_DATA_END;
1849
1850         /* notifiers */
1851         bGPdata *gpd = ob->data;
1852         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
1853         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED | ND_SPACE_PROPERTIES, NULL);
1854
1855         return OPERATOR_FINISHED;
1856 }
1857
1858 void GPENCIL_OT_vertex_group_smooth(wmOperatorType *ot)
1859 {
1860         /* identifiers */
1861         ot->name = "Smooth Vertex Group";
1862         ot->idname = "GPENCIL_OT_vertex_group_smooth";
1863         ot->description = "Smooth weights to the active vertex group";
1864
1865         /* api callbacks */
1866         ot->poll = gpencil_vertex_group_weight_poll;
1867         ot->exec = gpencil_vertex_group_smooth_exec;
1868
1869         /* flags */
1870         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1871
1872         RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 1.0, "Factor", "", 0.0f, 1.0f);
1873         RNA_def_int(ot->srna, "repeat", 1, 1, 10000, "Iterations", "", 1, 200);
1874 }
1875
1876 /****************************** Join ***********************************/
1877
1878 /* userdata for joined_gpencil_fix_animdata_cb() */
1879 typedef struct tJoinGPencil_AdtFixData {
1880         bGPdata *src_gpd;
1881         bGPdata *tar_gpd;
1882
1883         GHash *names_map;
1884 } tJoinGPencil_AdtFixData;
1885
1886 /* Callback to pass to BKE_fcurves_main_cb() for RNA Paths attached to each F-Curve used in the AnimData */
1887 static void joined_gpencil_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data)
1888 {
1889         tJoinGPencil_AdtFixData *afd = (tJoinGPencil_AdtFixData *)user_data;
1890         ID *src_id = &afd->src_gpd->id;
1891         ID *dst_id = &afd->tar_gpd->id;
1892
1893         GHashIterator gh_iter;
1894
1895         /* Fix paths - If this is the target datablock, it will have some "dirty" paths */
1896         if ((id == src_id) && fcu->rna_path && strstr(fcu->rna_path, "layers[")) {
1897                 GHASH_ITER(gh_iter, afd->names_map) {
1898                         const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
1899                         const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
1900
1901                         /* only remap if changed;
1902                          * this still means there will be some waste if there aren't many drivers/keys */
1903                         if (!STREQ(old_name, new_name) && strstr(fcu->rna_path, old_name)) {
1904                                 fcu->rna_path = BKE_animsys_fix_rna_path_rename(
1905                                         id, fcu->rna_path, "layers",
1906                                         old_name, new_name, 0, 0, false);
1907
1908                                 /* we don't want to apply a second remapping on this F-Curve now,
1909                                  * so stop trying to fix names names
1910                                  */
1911                                 break;
1912                         }
1913                 }
1914         }
1915
1916         /* Fix driver targets */
1917         if (fcu->driver) {
1918                 /* Fix driver references to invalid ID's */
1919                 for (DriverVar *dvar = fcu->driver->variables.first; dvar; dvar = dvar->next) {
1920                         /* only change the used targets, since the others will need fixing manually anyway */
1921                         DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar)
1922                         {
1923                                 /* change the ID's used... */
1924                                 if (dtar->id == src_id) {
1925                                         dtar->id = dst_id;
1926
1927                                         /* also check on the subtarget...
1928                                          * XXX: We duplicate the logic from drivers_path_rename_fix() here, with our own
1929                                          *      little twists so that we know that it isn't going to clobber the wrong data
1930                                          */
1931                                         if (dtar->rna_path && strstr(dtar->rna_path, "layers[")) {
1932                                                 GHASH_ITER(gh_iter, afd->names_map) {
1933                                                         const char *old_name = BLI_ghashIterator_getKey(&gh_iter);
1934                                                         const char *new_name = BLI_ghashIterator_getValue(&gh_iter);
1935
1936                                                         /* only remap if changed */
1937                                                         if (!STREQ(old_name, new_name)) {
1938                                                                 if ((dtar->rna_path) && strstr(dtar->rna_path, old_name)) {
1939                                                                         /* Fix up path */
1940                                                                         dtar->rna_path = BKE_animsys_fix_rna_path_rename(
1941                                                                                 id, dtar->rna_path, "layers",
1942                                                                                 old_name, new_name, 0, 0, false);
1943                                                                         break; /* no need to try any more names for layer path */
1944                                                                 }
1945                                                         }
1946                                                 }
1947                                         }
1948                                 }
1949                         }
1950                         DRIVER_TARGETS_LOOPER_END;
1951                 }
1952         }
1953 }
1954
1955 /* join objects called from OBJECT_OT_join */
1956 int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
1957 {
1958         Main *bmain = CTX_data_main(C);
1959         Scene *scene = CTX_data_scene(C);
1960         Depsgraph *depsgraph = CTX_data_depsgraph(C);
1961         Object  *ob_active = CTX_data_active_object(C);
1962         bGPdata *gpd_dst = NULL;
1963         bool ok = false;
1964
1965         /* Ensure we're in right mode and that the active object is correct */
1966         if (!ob_active || ob_active->type != OB_GPENCIL)
1967                 return OPERATOR_CANCELLED;
1968
1969         bGPdata *gpd = (bGPdata *)ob_active->data;
1970         if ((!gpd) || GPENCIL_ANY_MODE(gpd)) {
1971                 return OPERATOR_CANCELLED;
1972         }
1973
1974         /* Ensure all rotations are applied before */
1975         // XXX: Why don't we apply them here instead of warning?
1976         CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
1977         {
1978                 if (ob_iter->type == OB_GPENCIL) {
1979                         if ((ob_iter->rot[0] != 0) ||
1980                             (ob_iter->rot[1] != 0) ||
1981                             (ob_iter->rot[2] != 0))
1982                         {
1983                                 BKE_report(op->reports, RPT_ERROR, "Apply all rotations before join objects");
1984                                 return OPERATOR_CANCELLED;
1985                         }
1986                 }
1987         }
1988         CTX_DATA_END;
1989
1990         CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
1991         {
1992                 if (ob_iter == ob_active) {
1993                         ok = true;
1994                         break;
1995                 }
1996         }
1997         CTX_DATA_END;
1998
1999         /* that way the active object is always selected */
2000         if (ok == false) {
2001                 BKE_report(op->reports, RPT_WARNING, "Active object is not a selected grease pencil");
2002                 return OPERATOR_CANCELLED;
2003         }
2004
2005         gpd_dst = ob_active->data;
2006         Object *ob_dst = ob_active;
2007
2008         /* loop and join all data */
2009         CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects)
2010         {
2011                 if ((ob_iter->type == OB_GPENCIL) && (ob_iter != ob_active)) {
2012                         /* we assume that each datablock is not already used in active object */
2013                         if (ob_active->data != ob_iter->data) {
2014                                 Object *ob_src = ob_iter;
2015                                 bGPdata *gpd_src = ob_iter->data;
2016
2017                                 /* Apply all GP modifiers before */
2018                                 for (GpencilModifierData *md = ob_iter->greasepencil_modifiers.first; md; md = md->next) {
2019                                         const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type);
2020                                         if (mti->bakeModifier) {
2021                                                 mti->bakeModifier(bmain, depsgraph, md, ob_iter);
2022                                         }
2023                                 }
2024
2025                                 /* copy vertex groups to the base one's */
2026                                 int old_idx = 0;
2027                                 for (bDeformGroup *dg = ob_iter->defbase.first; dg; dg = dg->next) {
2028                                         bDeformGroup *vgroup = MEM_dupallocN(dg);
2029                                         int idx = BLI_listbase_count(&ob_active->defbase);
2030                                         defgroup_unique_name(vgroup, ob_active);
2031                                         BLI_addtail(&ob_active->defbase, vgroup);
2032                                         /* update vertex groups in strokes in original data */
2033                                         for (bGPDlayer *gpl_src = gpd->layers.first; gpl_src; gpl_src = gpl_src->next) {
2034                                                 for (bGPDframe *gpf = gpl_src->frames.first; gpf; gpf = gpf->next) {
2035                                                         for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
2036                                                                 MDeformVert *dvert;
2037                                                                 int i;
2038                                                                 for (i = 0, dvert = gps->dvert; i < gps->totpoints; i++, dvert++) {
2039                                                                         if ((dvert->dw) && (dvert->dw->def_nr == old_idx)) {
2040                                                                                 dvert->dw->def_nr = idx;
2041                                                                         }
2042                                                                 }
2043                                                         }
2044                                                 }
2045                                         }
2046                                         old_idx++;
2047                                 }
2048                                 if (ob_active->defbase.first && ob_active->actdef == 0) {
2049                                         ob_active->actdef = 1;
2050                                 }
2051
2052                                 /* add missing materials reading source materials and checking in destination object */
2053                                 short *totcol = give_totcolp(ob_src);
2054
2055                                 for (short i = 0; i < *totcol; i++) {
2056                                         Material *tmp_ma = give_current_material(ob_src, i + 1);
2057                                         BKE_gpencil_object_material_ensure(bmain, ob_dst, tmp_ma);
2058                                 }
2059
2060                                 /* duplicate bGPDlayers  */
2061                                 tJoinGPencil_AdtFixData afd = {0};
2062                                 afd.src_gpd = gpd_src;
2063                                 afd.tar_gpd = gpd_dst;
2064                                 afd.names_map = BLI_ghash_str_new("joined_gp_layers_map");
2065
2066                                 float imat[3][3], bmat[3][3];
2067                                 float offset_global[3];
2068                                 float offset_local[3];
2069
2070                                 sub_v3_v3v3(offset_global, ob_active->loc, ob_iter->obmat[3]);
2071                                 copy_m3_m4(bmat, ob_active->obmat);
2072                                 invert_m3_m3(imat, bmat);
2073                                 mul_m3_v3(imat, offset_global);
2074                                 mul_v3_m3v3(offset_local, imat, offset_global);
2075
2076
2077                                 for (bGPDlayer *gpl_src = gpd_src->layers.first; gpl_src; gpl_src = gpl_src->next) {
2078                                         bGPDlayer *gpl_new = BKE_gpencil_layer_duplicate(gpl_src);
2079                                         float diff_mat[4][4];
2080                                         float inverse_diff_mat[4][4];
2081
2082                                         /* recalculate all stroke points */
2083                                         ED_gpencil_parent_location(depsgraph, ob_iter, gpd_src, gpl_src, diff_mat);
2084                                         invert_m4_m4(inverse_diff_mat, diff_mat);
2085
2086                                         Material *ma_src = NULL;
2087                                         for (bGPDframe *gpf = gpl_new->frames.first; gpf; gpf = gpf->next) {
2088                                                 for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
2089
2090                                                         /* reasign material. Look old material and try to find in dst */
2091                                                         ma_src = give_current_material(ob_src, gps->mat_nr + 1);
2092                                                         gps->mat_nr = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
2093
2094                                                         bGPDspoint *pt;
2095                                                         int i;
2096                                                         for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
2097                                                                 float mpt[3];
2098                                                                 mul_v3_m4v3(mpt, inverse_diff_mat, &pt->x);
2099                                                                 sub_v3_v3(mpt, offset_local);
2100                                                                 mul_v3_m4v3(&pt->x, diff_mat, mpt);
2101                                                         }
2102                                                 }
2103                                         }
2104
2105                                         /* be sure name is unique in new object */
2106                                         BLI_uniquename(&gpd_dst->layers, gpl_new, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(gpl_new->info));
2107                                         BLI_ghash_insert(afd.names_map, BLI_strdup(gpl_src->info), gpl_new->info);
2108
2109                                         /* add to destination datablock */
2110                                         BLI_addtail(&gpd_dst->layers, gpl_new);
2111                                 }
2112
2113                                 /* Fix all the animation data */
2114                                 BKE_fcurves_main_cb(bmain, joined_gpencil_fix_animdata_cb, &afd);
2115                                 BLI_ghash_free(afd.names_map, MEM_freeN, NULL);
2116
2117                                 /* Only copy over animdata now, after all the remapping has been done,
2118                                  * so that we don't have to worry about ambiguities re which datablock
2119                                  * a layer came from!
2120                                  */
2121                                 if (ob_iter->adt) {
2122                                         if (ob_active->adt == NULL) {
2123                                                 /* no animdata, so just use a copy of the whole thing */
2124                                                 ob_active->adt = BKE_animdata_copy(bmain, ob_iter->adt, 0);
2125                                         }
2126                                         else {
2127                                                 /* merge in data - we'll fix the drivers manually */
2128                                                 BKE_animdata_merge_copy(bmain, &ob_active->id, &ob_iter->id, ADT_MERGECOPY_KEEP_DST, false);
2129                                         }
2130                                 }
2131
2132                                 if (gpd_src->adt) {
2133                                         if (gpd_dst->adt == NULL) {
2134                                                 /* no animdata, so just use a copy of the whole thing */
2135                                                 gpd_dst->adt = BKE_animdata_copy(bmain, gpd_src->adt, 0);
2136                                         }
2137                                         else {
2138                                                 /* merge in data - we'll fix the drivers manually */
2139                                                 BKE_animdata_merge_copy(bmain, &gpd_dst->id, &gpd_src->id, ADT_MERGECOPY_KEEP_DST, false);
2140                                         }
2141                                 }
2142                                 DEG_id_tag_update(&gpd_src->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
2143                         }
2144
2145                         /* Free the old object */
2146                         ED_object_base_free_and_unlink(bmain, scene, ob_iter);
2147                 }
2148         }
2149         CTX_DATA_END;
2150
2151         DEG_id_tag_update(&gpd_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
2152         DEG_relations_tag_update(bmain);  /* because we removed object(s) */
2153
2154         WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
2155
2156         return OPERATOR_FINISHED;
2157 }
2158
2159 /* Color Handle operator */
2160 static bool gpencil_active_color_poll(bContext *C)
2161 {
2162         Object *ob = CTX_data_active_object(C);
2163         if (ob && ob->data && (ob->type == OB_GPENCIL)) {
2164                 short *totcolp = give_totcolp(ob);
2165                 return *totcolp > 0;
2166         }
2167         return false;
2168 }
2169
2170
2171 /* ******************* Lock and hide any color non used in current layer ************************** */
2172 static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
2173 {
2174         bGPdata *gpd = ED_gpencil_data_get_active(C);
2175         Object *ob = CTX_data_active_object(C);
2176         MaterialGPencilStyle *gp_style = NULL;
2177
2178         /* sanity checks */
2179         if (ELEM(NULL, gpd))
2180                 return OPERATOR_CANCELLED;
2181
2182         /* first lock and hide all colors */
2183         Material *ma = NULL;
2184         short *totcol = give_totcolp(ob);
2185         if (totcol == 0)
2186                 return OPERATOR_CANCELLED;
2187
2188         for (short i = 0; i < *totcol; i++) {
2189                 ma = give_current_material(ob, i + 1);
2190                 gp_style = ma->gp_style;
2191                 gp_style->flag |= GP_STYLE_COLOR_LOCKED;
2192                 gp_style->flag |= GP_STYLE_COLOR_HIDE;
2193                 DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
2194         }
2195
2196         /* loop all selected strokes and unlock any color used in active layer */
2197         for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
2198                 /* only editable and visible layers are considered */
2199                 if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL) && (gpl->flag & GP_LAYER_ACTIVE)) {
2200                         for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
2201                                 /* skip strokes that are invalid for current view */
2202                                 if (ED_gpencil_stroke_can_use(C, gps) == false)
2203                                         continue;
2204
2205                                 ma = give_current_material(ob, gps->mat_nr + 1);
2206                                 DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
2207
2208                                 gp_style = ma->gp_style;
2209                                 /* unlock/unhide color if not unlocked before */
2210                                 if (gp_style != NULL) {
2211                                         gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
2212                                         gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
2213                                 }
2214                         }
2215                 }
2216         }
2217         /* updates */
2218         DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
2219
2220         /* copy on write tag is needed, or else no refresh happens */
2221         DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
2222
2223         /* notifiers */
2224         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
2225         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
2226
2227         return OPERATOR_FINISHED;
2228 }
2229
2230 void GPENCIL_OT_lock_layer(wmOperatorType *ot)
2231 {
2232         /* identifiers */
2233         ot->name = "Disable Unused Layer Colors";
2234         ot->idname = "GPENCIL_OT_lock_layer";
2235         ot->description = "Lock and hide any color not used in any layer";
2236
2237         /* api callbacks */
2238         ot->exec = gpencil_lock_layer_exec;
2239         ot->poll = gp_active_layer_poll;
2240 }
2241
2242 /* ********************** Isolate gpencil_ color **************************** */
2243
2244 static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
2245 {
2246         bGPdata *gpd = ED_gpencil_data_get_active(C);
2247         Object *ob = CTX_data_active_object(C);
2248         Material *active_ma = give_current_material(ob, ob->actcol);
2249         MaterialGPencilStyle *active_color = BKE_material_gpencil_settings_get(ob, ob->actcol);
2250         MaterialGPencilStyle *gp_style;
2251
2252         int flags = GP_STYLE_COLOR_LOCKED;
2253         bool isolate = false;
2254
2255         if (RNA_boolean_get(op->ptr, "affect_visibility"))
2256                 flags |= GP_STYLE_COLOR_HIDE;
2257
2258         if (ELEM(NULL, gpd, active_color)) {
2259                 BKE_report(op->reports, RPT_ERROR, "No active color to isolate");
2260                 return OPERATOR_CANCELLED;
2261         }
2262
2263         /* Test whether to isolate or clear all flags */
2264         Material *ma = NULL;
2265         short *totcol = give_totcolp(ob);
2266         for (short i = 0; i < *totcol; i++) {
2267                 ma = give_current_material(ob, i + 1);
2268                 /* Skip if this is the active one */
2269                 if (ma == active_ma)
2270                         continue;
2271
2272                 /* If the flags aren't set, that means that the color is
2273                  * not alone, so we have some colors to isolate still
2274                  */
2275                 gp_style = ma->gp_style;
2276                 if ((gp_style->flag & flags) == 0) {
2277                         isolate = true;
2278                         break;
2279                 }
2280         }
2281
2282         /* Set/Clear flags as appropriate */
2283         if (isolate) {
2284                 /* Set flags on all "other" colors */
2285                 for (short i = 0; i < *totcol; i++) {
2286                         ma = give_current_material(ob, i + 1);
2287                         gp_style = ma->gp_style;
2288                         if (gp_style == active_color)
2289                                 continue;
2290                         else
2291                                 gp_style->flag |= flags;
2292                         DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
2293                 }
2294         }
2295         else {
2296                 /* Clear flags - Restore everything else */
2297                 for (short i = 0; i < *totcol; i++) {
2298                         ma = give_current_material(ob, i + 1);
2299                         gp_style = ma->gp_style;
2300                         gp_style->flag &= ~flags;
2301                         DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
2302                 }
2303         }
2304
2305         /* notifiers */
2306         DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
2307
2308         /* copy on write tag is needed, or else no refresh happens */
2309         DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
2310
2311         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
2312
2313         return OPERATOR_FINISHED;
2314 }
2315
2316 void GPENCIL_OT_color_isolate(wmOperatorType *ot)
2317 {
2318         /* identifiers */
2319         ot->name = "Isolate Color";
2320         ot->idname = "GPENCIL_OT_color_isolate";
2321         ot->description = "Toggle whether the active color is the only one that is editable and/or visible";
2322
2323         /* callbacks */
2324         ot->exec = gpencil_color_isolate_exec;
2325         ot->poll = gpencil_active_color_poll;
2326
2327         /* flags */
2328         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2329
2330         /* properties */
2331         RNA_def_boolean(ot->srna, "affect_visibility", false, "Affect Visibility", "In addition to toggling "
2332                 "the editability, also affect the visibility");
2333 }
2334
2335 /* *********************** Hide colors ******************************** */
2336
2337 static int gpencil_color_hide_exec(bContext *C, wmOperator *op)
2338 {
2339         Object *ob = CTX_data_active_object(C);
2340         bGPdata *gpd = (bGPdata *)ob->data;
2341         MaterialGPencilStyle *active_color = BKE_material_gpencil_settings_get(ob, ob->actcol);
2342
2343         bool unselected = RNA_boolean_get(op->ptr, "unselected");
2344
2345         Material *ma = NULL;
2346         short *totcol = give_totcolp(ob);
2347         if (totcol == 0)
2348                 return OPERATOR_CANCELLED;
2349
2350         if (unselected) {
2351                 /* hide unselected */
2352                 MaterialGPencilStyle *color = NULL;
2353                 for (short i = 0; i < *totcol; i++) {
2354                         ma = give_current_material(ob, i + 1);
2355                         color = ma->gp_style;
2356                         if (active_color != color) {
2357                                 color->flag |= GP_STYLE_COLOR_HIDE;
2358                                 DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
2359                         }
2360                 }
2361         }
2362         else {
2363                 /* hide selected/active */
2364                 active_color->flag |= GP_STYLE_COLOR_HIDE;
2365         }
2366
2367         /* updates */
2368         DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
2369
2370         /* copy on write tag is needed, or else no refresh happens */
2371         DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
2372
2373         /* notifiers */
2374         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
2375
2376         return OPERATOR_FINISHED;
2377 }
2378
2379 void GPENCIL_OT_color_hide(wmOperatorType *ot)
2380 {
2381         /* identifiers */
2382         ot->name = "Hide Color(s)";
2383         ot->idname = "GPENCIL_OT_color_hide";
2384         ot->description = "Hide selected/unselected Grease Pencil colors";
2385
2386         /* callbacks */
2387         ot->exec = gpencil_color_hide_exec;
2388         ot->poll = gpencil_active_color_poll; /* NOTE: we need an active color to play with */
2389
2390                                                                                   /* flags */
2391         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2392
2393         /* props */
2394         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected colors");
2395 }
2396
2397 /* ********************** Show All Colors ***************************** */
2398
2399 static int gpencil_color_reveal_exec(bContext *C, wmOperator *UNUSED(op))
2400 {
2401         Object *ob = CTX_data_active_object(C);
2402         bGPdata *gpd = (bGPdata *)ob->data;
2403         Material *ma = NULL;
2404         short *totcol = give_totcolp(ob);
2405
2406         if (totcol == 0)
2407                 return OPERATOR_CANCELLED;
2408
2409         /* make all colors visible */
2410         MaterialGPencilStyle *gp_style = NULL;
2411
2412         for (short i = 0; i < *totcol; i++) {
2413                 ma = give_current_material(ob, i + 1);
2414                 gp_style = ma->gp_style;
2415                 gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
2416                 DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
2417         }
2418
2419         /* updates */
2420         DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
2421
2422         /* copy on write tag is needed, or else no refresh happens */
2423         DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
2424
2425         /* notifiers */
2426         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
2427
2428         return OPERATOR_FINISHED;
2429 }
2430
2431 void GPENCIL_OT_color_reveal(wmOperatorType *ot)
2432 {
2433         /* identifiers */
2434         ot->name = "Show All Colors";
2435         ot->idname = "GPENCIL_OT_color_reveal";
2436         ot->description = "Unhide all hidden Grease Pencil colors";
2437
2438         /* callbacks */
2439         ot->exec = gpencil_color_reveal_exec;
2440         ot->poll = gpencil_active_color_poll;
2441
2442         /* flags */
2443         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2444 }
2445
2446 /* ***************** Lock/Unlock All colors ************************ */
2447
2448 static int gpencil_color_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
2449 {
2450
2451         Object *ob = CTX_data_active_object(C);
2452         bGPdata *gpd = (bGPdata *)ob->data;
2453         Material *ma = NULL;
2454         short *totcol = give_totcolp(ob);
2455
2456         if (totcol == 0)
2457                 return OPERATOR_CANCELLED;
2458
2459         /* make all layers non-editable */
2460         MaterialGPencilStyle *gp_style = NULL;
2461
2462         for (short i = 0; i < *totcol; i++) {
2463                 ma = give_current_material(ob, i + 1);
2464                 gp_style = ma->gp_style;
2465                 gp_style->flag |= GP_STYLE_COLOR_LOCKED;
2466                 DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
2467         }
2468
2469         /* updates */
2470         DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
2471
2472         /* copy on write tag is needed, or else no refresh happens */
2473         DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
2474
2475         /* notifiers */
2476         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
2477
2478         return OPERATOR_FINISHED;
2479 }
2480
2481 void GPENCIL_OT_color_lock_all(wmOperatorType *ot)
2482 {
2483         /* identifiers */
2484         ot->name = "Lock All Colors";
2485         ot->idname = "GPENCIL_OT_color_lock_all";
2486         ot->description = "Lock all Grease Pencil colors to prevent them from being accidentally modified";
2487
2488         /* callbacks */
2489         ot->exec = gpencil_color_lock_all_exec;
2490         ot->poll = gpencil_active_color_poll;
2491
2492         /* flags */
2493         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2494 }
2495
2496 /* -------------------------- */
2497
2498 static int gpencil_color_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
2499 {
2500         Object *ob = CTX_data_active_object(C);
2501         bGPdata *gpd = (bGPdata *)ob->data;
2502         Material *ma = NULL;
2503         short *totcol = give_totcolp(ob);
2504
2505         if (totcol == 0)
2506                 return OPERATOR_CANCELLED;
2507
2508         /* make all layers editable again*/
2509         MaterialGPencilStyle *gp_style = NULL;
2510
2511         for (short i = 0; i < *totcol; i++) {
2512                 ma = give_current_material(ob, i + 1);
2513                 gp_style = ma->gp_style;
2514                 gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
2515                 DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
2516         }
2517
2518         /* updates */
2519         DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY);
2520
2521         /* copy on write tag is needed, or else no refresh happens */
2522         DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
2523
2524         /* notifiers */
2525         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
2526
2527         return OPERATOR_FINISHED;
2528 }
2529
2530 void GPENCIL_OT_color_unlock_all(wmOperatorType *ot)
2531 {
2532         /* identifiers */
2533         ot->name = "Unlock All Colors";
2534         ot->idname = "GPENCIL_OT_color_unlock_all";
2535         ot->description = "Unlock all Grease Pencil colors so that they can be edited";
2536
2537         /* callbacks */
2538         ot->exec = gpencil_color_unlock_all_exec;
2539         ot->poll = gpencil_active_color_poll;
2540
2541         /* flags */
2542         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2543 }
2544
2545
2546 /* ***************** Select all strokes using color ************************ */
2547
2548 static int gpencil_color_select_exec(bContext *C, wmOperator *op)
2549 {
2550         bGPdata *gpd = ED_gpencil_data_get_active(C);
2551         Object *ob = CTX_data_active_object(C);
2552         MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, ob->actcol);
2553         const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
2554         const bool deselected = RNA_boolean_get(op->ptr, "deselect");
2555
2556         /* sanity checks */
2557         if (ELEM(NULL, gpd, gp_style))
2558                 return OPERATOR_CANCELLED;
2559
2560         /* read all strokes and select*/
2561         CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
2562         {
2563                 bGPDframe *init_gpf = gpl->actframe;
2564                 if (is_multiedit) {
2565                         init_gpf = gpl->frames.first;
2566                 }
2567                 for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
2568                         if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
2569
2570                                 /* verify something to do */
2571                                 for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
2572                                         /* skip strokes that are invalid for current view */
2573                                         if (ED_gpencil_stroke_can_use(C, gps) == false)
2574                                                 continue;
2575                                         /* check if the color is editable */
2576                                         if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false)
2577                                                 continue;
2578
2579                                         /* select */
2580                                         if (ob->actcol == gps->mat_nr + 1) {
2581                                                 bGPDspoint *pt;
2582                                                 int i;
2583
2584                                                 if (!deselected) {
2585                                                         gps->flag |= GP_STROKE_SELECT;
2586                                                 }
2587                                                 else {
2588                                                         gps->flag &= ~GP_STROKE_SELECT;
2589                                                 }
2590                                                 for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
2591                                                         if (!deselected) {
2592                                                                 pt->flag |= GP_SPOINT_SELECT;
2593                                                         }
2594                                                         else {
2595                                                                 pt->flag &= ~GP_SPOINT_SELECT;
2596                                                         }
2597                                                 }
2598                                         }
2599                                 }
2600                         }
2601                         /* if not multiedit, exit loop*/
2602                         if (!is_multiedit) {
2603                                 break;
2604                         }
2605
2606                 }
2607         }
2608         CTX_DATA_END;
2609
2610         /* copy on write tag is needed, or else no refresh happens */
2611         DEG_id_tag_update(&gpd->id, ID_RECALC_COPY_ON_WRITE);
2612
2613         /* notifiers */
2614         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
2615
2616         return OPERATOR_FINISHED;
2617 }
2618
2619 void GPENCIL_OT_color_select(wmOperatorType *ot)
2620 {
2621         /* identifiers */
2622         ot->name = "Select Color";
2623         ot->idname = "GPENCIL_OT_color_select";
2624         ot->description = "Select all Grease Pencil strokes using current color";
2625
2626         /* callbacks */
2627         ot->exec = gpencil_color_select_exec;
2628         ot->poll = gpencil_active_color_poll;
2629
2630         /* flags */
2631         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2632
2633         /* props */
2634         ot->prop = RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Unselect strokes");
2635         RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
2636 }