style cleanup
[blender-staging.git] / source / blender / editors / mask / mask_editaction.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
19  * This is a new part of Blender
20  *
21  * Contributor(s): Joshua Leung
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/mask/mask_editaction.c
27  *  \ingroup edgpencil
28  */
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <stddef.h>
34 #include <math.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLI_blenlib.h"
39 #include "BLI_math.h"
40 #include "BLI_utildefines.h"
41
42 #include "DNA_mask_types.h"
43 #include "DNA_object_types.h"
44 #include "DNA_scene_types.h"
45
46 #include "BKE_fcurve.h"
47 #include "BKE_mask.h"
48
49 #include "ED_anim_api.h"
50 #include "ED_keyframes_edit.h"
51
52 /* ***************************************** */
53 /* NOTE ABOUT THIS FILE:
54  *  This file contains code for editing Grease Pencil data in the Action Editor
55  *  as a 'keyframes', so that a user can adjust the timing of Grease Pencil drawings.
56  *  Therefore, this file mostly contains functions for selecting Grease-Pencil frames.
57  */
58 /* ***************************************** */
59 /* Generics - Loopers */
60
61 /* Loops over the gp-frames for a gp-layer, and applies the given callback */
62 short ED_masklayer_frames_looper(MaskLayer *masklay, Scene *scene, short (*masklay_shape_cb)(MaskLayerShape *, Scene *))
63 {
64         MaskLayerShape *masklay_shape;
65
66         /* error checker */
67         if (masklay == NULL)
68                 return 0;
69
70         /* do loop */
71         for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
72                 /* execute callback */
73                 if (masklay_shape_cb(masklay_shape, scene))
74                         return 1;
75         }
76
77         /* nothing to return */
78         return 0;
79 }
80
81 /* ****************************************** */
82 /* Data Conversion Tools */
83
84 /* make a listing all the gp-frames in a layer as cfraelems */
85 void ED_masklayer_make_cfra_list(MaskLayer *masklay, ListBase *elems, short onlysel)
86 {
87         MaskLayerShape *masklay_shape;
88         CfraElem *ce;
89
90         /* error checking */
91         if (ELEM(NULL, masklay, elems))
92                 return;
93
94         /* loop through gp-frames, adding */
95         for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
96                 if ((onlysel == 0) || (masklay_shape->flag & MASK_SHAPE_SELECT)) {
97                         ce = MEM_callocN(sizeof(CfraElem), "CfraElem");
98
99                         ce->cfra = (float)masklay_shape->frame;
100                         ce->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? 1 : 0;
101
102                         BLI_addtail(elems, ce);
103                 }
104         }
105 }
106
107 /* ***************************************** */
108 /* Selection Tools */
109
110 /* check if one of the frames in this layer is selected */
111 short ED_masklayer_frame_select_check(MaskLayer *masklay)
112 {
113         MaskLayerShape *masklay_shape;
114
115         /* error checking */
116         if (masklay == NULL)
117                 return 0;
118
119         /* stop at the first one found */
120         for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
121                 if (masklay_shape->flag & MASK_SHAPE_SELECT)
122                         return 1;
123         }
124
125         /* not found */
126         return 0;
127 }
128
129 /* helper function - select gp-frame based on SELECT_* mode */
130 static void masklayshape_select(MaskLayerShape *masklay_shape, short select_mode)
131 {
132         if (masklay_shape == NULL)
133                 return;
134
135         switch (select_mode) {
136                 case SELECT_ADD:
137                         masklay_shape->flag |= MASK_SHAPE_SELECT;
138                         break;
139                 case SELECT_SUBTRACT:
140                         masklay_shape->flag &= ~MASK_SHAPE_SELECT;
141                         break;
142                 case SELECT_INVERT:
143                         masklay_shape->flag ^= MASK_SHAPE_SELECT;
144                         break;
145         }
146 }
147
148 /* set all/none/invert select (like above, but with SELECT_* modes) */
149 void ED_mask_select_frames(MaskLayer *masklay, short select_mode)
150 {
151         MaskLayerShape *masklay_shape;
152
153         /* error checking */
154         if (masklay == NULL)
155                 return;
156
157         /* handle according to mode */
158         for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
159                 masklayshape_select(masklay_shape, select_mode);
160         }
161 }
162
163 /* set all/none/invert select */
164 void ED_masklayer_frame_select_set(MaskLayer *masklay, short mode)
165 {
166         /* error checking */
167         if (masklay == NULL)
168                 return;
169
170         /* now call the standard function */
171         ED_mask_select_frames(masklay, mode);
172 }
173
174 /* select the frame in this layer that occurs on this frame (there should only be one at most) */
175 void ED_mask_select_frame(MaskLayer *masklay, int selx, short select_mode)
176 {
177         MaskLayerShape *masklay_shape;
178
179         if (masklay == NULL)
180                 return;
181
182         masklay_shape = BKE_mask_layer_shape_find_frame(masklay, selx);
183
184         if (masklay_shape) {
185                 masklayshape_select(masklay_shape, select_mode);
186         }
187 }
188
189 /* select the frames in this layer that occur within the bounds specified */
190 void ED_masklayer_frames_select_border(MaskLayer *masklay, float min, float max, short select_mode)
191 {
192         MaskLayerShape *masklay_shape;
193
194         if (masklay == NULL)
195                 return;
196
197         /* only select those frames which are in bounds */
198         for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
199                 if (IN_RANGE(masklay_shape->frame, min, max))
200                         masklayshape_select(masklay_shape, select_mode);
201         }
202 }
203
204 /* ***************************************** */
205 /* Frame Editing Tools */
206
207 /* Delete selected frames */
208 void ED_masklayer_frames_delete(MaskLayer *masklay)
209 {
210         MaskLayerShape *masklay_shape, *masklay_shape_next;
211
212         /* error checking */
213         if (masklay == NULL)
214                 return;
215
216         /* check for frames to delete */
217         for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape_next) {
218                 masklay_shape_next = masklay_shape->next;
219
220                 if (masklay_shape->flag & MASK_SHAPE_SELECT)
221                         BKE_mask_layer_shape_unlink(masklay, masklay_shape);
222         }
223 }
224
225 /* Duplicate selected frames from given gp-layer */
226 void ED_masklayer_frames_duplicate(MaskLayer *masklay)
227 {
228         MaskLayerShape *masklay_shape, *gpfn;
229
230         /* error checking */
231         if (masklay == NULL)
232                 return;
233
234         /* duplicate selected frames  */
235         for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = gpfn) {
236                 gpfn = masklay_shape->next;
237
238                 /* duplicate this frame */
239                 if (masklay_shape->flag & MASK_SHAPE_SELECT) {
240                         MaskLayerShape *mask_shape_dupe;
241
242                         /* duplicate frame, and deselect self */
243                         mask_shape_dupe = BKE_mask_layer_shape_duplicate(masklay_shape);
244                         masklay_shape->flag &= ~MASK_SHAPE_SELECT;
245
246                         /* XXX - how to handle duplicate frames? */
247                         BLI_insertlinkafter(&masklay->splines_shapes, masklay_shape, mask_shape_dupe);
248                 }
249         }
250 }