Code Cleanup: Reshuffling some of the GPencil code
[blender.git] / source / blender / editors / gpencil / gpencil_data.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2008, Blender Foundation, Joshua Leung
19  * This is a new part of Blender
20  *
21  * Contributor(s): Joshua Leung
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  *
25  * Operators for dealing with GP datablocks and layers
26  */
27
28 /** \file blender/editors/gpencil/gpencil_data.c
29  *  \ingroup edgpencil
30  */
31
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <stddef.h>
37 #include <math.h>
38
39 #include "MEM_guardedalloc.h"
40
41 #include "BLI_math.h"
42 #include "BLI_blenlib.h"
43 #include "BLI_rand.h"
44 #include "BLI_utildefines.h"
45
46 #include "BLF_translation.h"
47
48 #include "DNA_anim_types.h"
49 #include "DNA_curve_types.h"
50 #include "DNA_object_types.h"
51 #include "DNA_node_types.h"
52 #include "DNA_scene_types.h"
53 #include "DNA_screen_types.h"
54 #include "DNA_space_types.h"
55 #include "DNA_view3d_types.h"
56 #include "DNA_gpencil_types.h"
57
58 #include "BKE_context.h"
59 #include "BKE_curve.h"
60 #include "BKE_depsgraph.h"
61 #include "BKE_fcurve.h"
62 #include "BKE_global.h"
63 #include "BKE_gpencil.h"
64 #include "BKE_library.h"
65 #include "BKE_object.h"
66 #include "BKE_report.h"
67 #include "BKE_scene.h"
68 #include "BKE_screen.h"
69
70 #include "UI_interface.h"
71
72 #include "WM_api.h"
73 #include "WM_types.h"
74
75 #include "RNA_access.h"
76 #include "RNA_define.h"
77
78 #include "UI_view2d.h"
79
80 #include "ED_gpencil.h"
81 #include "ED_view3d.h"
82 #include "ED_keyframing.h"
83
84 #include "gpencil_intern.h"
85
86
87 /* ************************************************ */
88 /* Datablock Operators */
89
90 /* ******************* Add New Data ************************ */
91
92 /* add new datablock - wrapper around API */
93 static int gp_data_add_exec(bContext *C, wmOperator *op)
94 {
95         bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
96         
97         if (gpd_ptr == NULL) {
98                 BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
99                 return OPERATOR_CANCELLED;
100         }
101         else {
102                 /* decrement user count and add new datablock */
103                 bGPdata *gpd = (*gpd_ptr);
104                 
105                 id_us_min(&gpd->id);
106                 *gpd_ptr = gpencil_data_addnew(DATA_("GPencil"));
107         }
108         
109         /* notifiers */
110         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
111         
112         return OPERATOR_FINISHED;
113 }
114
115 void GPENCIL_OT_data_add(wmOperatorType *ot)
116 {
117         /* identifiers */
118         ot->name = "Grease Pencil Add New";
119         ot->idname = "GPENCIL_OT_data_add";
120         ot->description = "Add new Grease Pencil datablock";
121         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
122         
123         /* callbacks */
124         ot->exec = gp_data_add_exec;
125         ot->poll = gp_add_poll;
126 }
127
128 /* ******************* Unlink Data ************************ */
129
130 /* poll callback for adding data/layers - special */
131 static int gp_data_unlink_poll(bContext *C)
132 {
133         bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
134         
135         /* if we have access to some active data, make sure there's a datablock before enabling this */
136         return (gpd_ptr && *gpd_ptr);
137 }
138
139
140 /* unlink datablock - wrapper around API */
141 static int gp_data_unlink_exec(bContext *C, wmOperator *op)
142 {
143         bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
144         
145         if (gpd_ptr == NULL) {
146                 BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
147                 return OPERATOR_CANCELLED;
148         }
149         else {
150                 /* just unlink datablock now, decreasing its user count */
151                 bGPdata *gpd = (*gpd_ptr);
152
153                 id_us_min(&gpd->id);
154                 *gpd_ptr = NULL;
155         }
156         
157         /* notifiers */
158         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
159         
160         return OPERATOR_FINISHED;
161 }
162
163 void GPENCIL_OT_data_unlink(wmOperatorType *ot)
164 {
165         /* identifiers */
166         ot->name = "Grease Pencil Unlink";
167         ot->idname = "GPENCIL_OT_data_unlink";
168         ot->description = "Unlink active Grease Pencil datablock";
169         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
170         
171         /* callbacks */
172         ot->exec = gp_data_unlink_exec;
173         ot->poll = gp_data_unlink_poll;
174 }
175
176
177 /* ************************************************ */
178 /* Layer Operators */
179
180 /* ******************* Add New Layer ************************ */
181
182 /* add new layer - wrapper around API */
183 static int gp_layer_add_exec(bContext *C, wmOperator *op)
184 {
185         bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
186         
187         /* if there's no existing Grease-Pencil data there, add some */
188         if (gpd_ptr == NULL) {
189                 BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go");
190                 return OPERATOR_CANCELLED;
191         }
192         if (*gpd_ptr == NULL)
193                 *gpd_ptr = gpencil_data_addnew(DATA_("GPencil"));
194         
195         /* add new layer now */
196         gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), 1);
197         
198         /* notifiers */
199         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
200         
201         return OPERATOR_FINISHED;
202 }
203
204 void GPENCIL_OT_layer_add(wmOperatorType *ot)
205 {
206         /* identifiers */
207         ot->name = "Add New Layer";
208         ot->idname = "GPENCIL_OT_layer_add";
209         ot->description = "Add new Grease Pencil layer for the active Grease Pencil datablock";
210         
211         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
212         
213         /* callbacks */
214         ot->exec = gp_layer_add_exec;
215         ot->poll = gp_add_poll;
216 }
217
218 /* ******************* Remove Active Layer ************************* */
219
220 static int gp_layer_remove_exec(bContext *C, wmOperator *op)
221 {
222         bGPdata *gpd = ED_gpencil_data_get_active(C);
223         bGPDlayer *gpl = gpencil_layer_getactive(gpd);
224         
225         /* sanity checks */
226         if (ELEM(NULL, gpd, gpl))
227                 return OPERATOR_CANCELLED;
228         
229         if (gpl->flag & GP_LAYER_LOCKED) {
230                 BKE_report(op->reports, RPT_ERROR, "Cannot delete locked layers");
231                 return OPERATOR_CANCELLED;
232         }
233         
234         /* make the layer before this the new active layer
235          * - use the one after if this is the first
236          * - if this is the only layer, this naturally becomes NULL
237          */
238         if (gpl->prev)
239                 gpencil_layer_setactive(gpd, gpl->prev);
240         else
241                 gpencil_layer_setactive(gpd, gpl->next);
242         
243         /* delete the layer now... */
244         gpencil_layer_delete(gpd, gpl);
245         
246         /* notifiers */
247         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
248         
249         return OPERATOR_FINISHED;
250 }
251
252 void GPENCIL_OT_layer_remove(wmOperatorType *ot)
253 {
254         /* identifiers */
255         ot->name = "Remove Layer";
256         ot->idname = "GPENCIL_OT_layer_remove";
257         ot->description = "Remove active Grease Pencil layer";
258         
259         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
260         
261         /* callbacks */
262         ot->exec = gp_layer_remove_exec;
263         ot->poll = gp_active_layer_poll;
264 }
265
266 /* ******************* Move Layer Up/Down ************************** */
267
268 enum {
269         GP_LAYER_MOVE_UP   = -1,
270         GP_LAYER_MOVE_DOWN = 1
271 };
272
273 static int gp_layer_move_exec(bContext *C, wmOperator *op)
274 {
275         bGPdata *gpd = ED_gpencil_data_get_active(C);
276         bGPDlayer *gpl = gpencil_layer_getactive(gpd);
277         
278         int direction = RNA_enum_get(op->ptr, "type");
279         
280         /* sanity checks */
281         if (ELEM(NULL, gpd, gpl))
282                 return OPERATOR_CANCELLED;
283         
284         /* up or down? */
285         if (direction == GP_LAYER_MOVE_UP) {
286                 /* up */
287                 BLI_remlink(&gpd->layers, gpl);
288                 BLI_insertlinkbefore(&gpd->layers, gpl->prev, gpl);
289         }
290         else {
291                 /* down */
292                 BLI_remlink(&gpd->layers, gpl);
293                 BLI_insertlinkafter(&gpd->layers, gpl->next, gpl);
294         }
295         
296         /* notifiers */
297         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
298         
299         return OPERATOR_FINISHED;
300 }
301
302 void GPENCIL_OT_layer_move(wmOperatorType *ot)
303 {
304         static EnumPropertyItem slot_move[] = {
305                 {GP_LAYER_MOVE_UP, "UP", 0, "Up", ""},
306                 {GP_LAYER_MOVE_DOWN, "DOWN", 0, "Down", ""},
307                 {0, NULL, 0, NULL, NULL}
308         };
309         
310         /* identifiers */
311         ot->name = "Move Grease Pencil Layer";
312         ot->idname = "GPENCIL_OT_layer_move";
313         ot->description = "Move the active Grease Pencil layer up/down in the list";
314         
315         /* api callbacks */
316         ot->exec = gp_layer_move_exec;
317         ot->poll = gp_active_layer_poll;
318         
319         /* flags */
320         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
321         
322         ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
323 }
324
325 /* ********************* Duplicate Layer ************************** */
326
327 static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op))
328 {
329         bGPdata *gpd = ED_gpencil_data_get_active(C);
330         bGPDlayer *gpl = gpencil_layer_getactive(gpd);
331         bGPDlayer *new_layer;
332         
333         /* sanity checks */
334         if (ELEM(NULL, gpd, gpl))
335                 return OPERATOR_CANCELLED;
336         
337         /* make copy of layer, and add it immediately after the existing layer */
338         new_layer = gpencil_layer_duplicate(gpl);
339         BLI_insertlinkafter(&gpd->layers, gpl, new_layer);
340         
341         /* ensure new layer has a unique name, and is now the active layer */
342         BLI_uniquename(&gpd->layers, new_layer, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(new_layer->info));
343         gpencil_layer_setactive(gpd, new_layer);
344         
345         /* notifiers */
346         WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
347         
348         return OPERATOR_FINISHED;
349 }
350
351 void GPENCIL_OT_layer_duplicate(wmOperatorType *ot)
352 {
353         /* identifiers */
354         ot->name = "Duplicate Layer";
355         ot->idname = "GPENCIL_OT_layer_duplicate";
356         ot->description = "Make a copy of the active Grease Pencil layer";
357         
358         /* callbacks */
359         ot->exec = gp_layer_copy_exec;
360         ot->poll = gp_active_layer_poll;
361         
362         /* flags */
363         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
364 }
365
366 /* ************************************************ */