Cycles / Sky Texture:
[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): Campbell Barton
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/mask/mask_editaction.c
27  *  \ingroup edmask
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 #include "ED_mask.h"  /* own include */
52 #include "ED_markers.h"
53
54 /* ***************************************** */
55 /* NOTE ABOUT THIS FILE:
56  *  This file contains code for editing Mask data in the Action Editor
57  *  as a 'keyframes', so that a user can adjust the timing of Mask shapekeys.
58  *  Therefore, this file mostly contains functions for selecting Mask frames (shapekeys).
59  */
60 /* ***************************************** */
61 /* Generics - Loopers */
62
63 /* Loops over the mask-frames for a mask-layer, and applies the given callback */
64 short ED_masklayer_frames_looper(MaskLayer *masklay, Scene *scene, short (*masklay_shape_cb)(MaskLayerShape *, Scene *))
65 {
66         MaskLayerShape *masklay_shape;
67
68         /* error checker */
69         if (masklay == NULL)
70                 return 0;
71
72         /* do loop */
73         for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
74                 /* execute callback */
75                 if (masklay_shape_cb(masklay_shape, scene))
76                         return 1;
77         }
78
79         /* nothing to return */
80         return 0;
81 }
82
83 /* ****************************************** */
84 /* Data Conversion Tools */
85
86 /* make a listing all the mask-frames in a layer as cfraelems */
87 void ED_masklayer_make_cfra_list(MaskLayer *masklay, ListBase *elems, short onlysel)
88 {
89         MaskLayerShape *masklay_shape;
90         CfraElem *ce;
91
92         /* error checking */
93         if (ELEM(NULL, masklay, elems))
94                 return;
95
96         /* loop through mask-frames, adding */
97         for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
98                 if ((onlysel == 0) || (masklay_shape->flag & MASK_SHAPE_SELECT)) {
99                         ce = MEM_callocN(sizeof(CfraElem), "CfraElem");
100
101                         ce->cfra = (float)masklay_shape->frame;
102                         ce->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? 1 : 0;
103
104                         BLI_addtail(elems, ce);
105                 }
106         }
107 }
108
109 /* ***************************************** */
110 /* Selection Tools */
111
112 /* check if one of the frames in this layer is selected */
113 short ED_masklayer_frame_select_check(MaskLayer *masklay)
114 {
115         MaskLayerShape *masklay_shape;
116
117         /* error checking */
118         if (masklay == NULL)
119                 return 0;
120
121         /* stop at the first one found */
122         for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
123                 if (masklay_shape->flag & MASK_SHAPE_SELECT)
124                         return 1;
125         }
126
127         /* not found */
128         return 0;
129 }
130
131 /* helper function - select mask-frame based on SELECT_* mode */
132 static void masklayshape_select(MaskLayerShape *masklay_shape, short select_mode)
133 {
134         if (masklay_shape == NULL)
135                 return;
136
137         switch (select_mode) {
138                 case SELECT_ADD:
139                         masklay_shape->flag |= MASK_SHAPE_SELECT;
140                         break;
141                 case SELECT_SUBTRACT:
142                         masklay_shape->flag &= ~MASK_SHAPE_SELECT;
143                         break;
144                 case SELECT_INVERT:
145                         masklay_shape->flag ^= MASK_SHAPE_SELECT;
146                         break;
147         }
148 }
149
150 /* set all/none/invert select (like above, but with SELECT_* modes) */
151 void ED_mask_select_frames(MaskLayer *masklay, short select_mode)
152 {
153         MaskLayerShape *masklay_shape;
154
155         /* error checking */
156         if (masklay == NULL)
157                 return;
158
159         /* handle according to mode */
160         for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
161                 masklayshape_select(masklay_shape, select_mode);
162         }
163 }
164
165 /* set all/none/invert select */
166 void ED_masklayer_frame_select_set(MaskLayer *masklay, short mode)
167 {
168         /* error checking */
169         if (masklay == NULL)
170                 return;
171
172         /* now call the standard function */
173         ED_mask_select_frames(masklay, mode);
174 }
175
176 /* select the frame in this layer that occurs on this frame (there should only be one at most) */
177 void ED_mask_select_frame(MaskLayer *masklay, int selx, short select_mode)
178 {
179         MaskLayerShape *masklay_shape;
180
181         if (masklay == NULL)
182                 return;
183
184         masklay_shape = BKE_mask_layer_shape_find_frame(masklay, selx);
185
186         if (masklay_shape) {
187                 masklayshape_select(masklay_shape, select_mode);
188         }
189 }
190
191 /* select the frames in this layer that occur within the bounds specified */
192 void ED_masklayer_frames_select_border(MaskLayer *masklay, float min, float max, short select_mode)
193 {
194         MaskLayerShape *masklay_shape;
195
196         if (masklay == NULL)
197                 return;
198
199         /* only select those frames which are in bounds */
200         for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
201                 if (IN_RANGE(masklay_shape->frame, min, max))
202                         masklayshape_select(masklay_shape, select_mode);
203         }
204 }
205
206 /* ***************************************** */
207 /* Frame Editing Tools */
208
209 /* Delete selected frames */
210 void ED_masklayer_frames_delete(MaskLayer *masklay)
211 {
212         MaskLayerShape *masklay_shape, *masklay_shape_next;
213
214         /* error checking */
215         if (masklay == NULL)
216                 return;
217
218         /* check for frames to delete */
219         for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape_next) {
220                 masklay_shape_next = masklay_shape->next;
221
222                 if (masklay_shape->flag & MASK_SHAPE_SELECT)
223                         BKE_mask_layer_shape_unlink(masklay, masklay_shape);
224         }
225 }
226
227 /* Duplicate selected frames from given mask-layer */
228 void ED_masklayer_frames_duplicate(MaskLayer *masklay)
229 {
230         MaskLayerShape *masklay_shape, *gpfn;
231
232         /* error checking */
233         if (masklay == NULL)
234                 return;
235
236         /* duplicate selected frames  */
237         for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = gpfn) {
238                 gpfn = masklay_shape->next;
239
240                 /* duplicate this frame */
241                 if (masklay_shape->flag & MASK_SHAPE_SELECT) {
242                         MaskLayerShape *mask_shape_dupe;
243
244                         /* duplicate frame, and deselect self */
245                         mask_shape_dupe = BKE_mask_layer_shape_duplicate(masklay_shape);
246                         masklay_shape->flag &= ~MASK_SHAPE_SELECT;
247
248                         /* XXX - how to handle duplicate frames? */
249                         BLI_insertlinkafter(&masklay->splines_shapes, masklay_shape, mask_shape_dupe);
250                 }
251         }
252 }
253
254 /* -------------------------------------- */
255 /* Snap Tools */
256
257 static short snap_masklayer_nearest(MaskLayerShape *masklay_shape, Scene *UNUSED(scene))
258 {
259         if (masklay_shape->flag & MASK_SHAPE_SELECT)
260                 masklay_shape->frame = (int)(floor(masklay_shape->frame + 0.5));
261         return 0;
262 }
263
264 static short snap_masklayer_nearestsec(MaskLayerShape *masklay_shape, Scene *scene)
265 {
266         float secf = (float)FPS;
267         if (masklay_shape->flag & MASK_SHAPE_SELECT)
268                 masklay_shape->frame = (int)(floorf(masklay_shape->frame / secf + 0.5f) * secf);
269         return 0;
270 }
271
272 static short snap_masklayer_cframe(MaskLayerShape *masklay_shape, Scene *scene)
273 {
274         if (masklay_shape->flag & MASK_SHAPE_SELECT)
275                 masklay_shape->frame = (int)CFRA;
276         return 0;
277 }
278
279 static short snap_masklayer_nearmarker(MaskLayerShape *masklay_shape, Scene *scene)
280 {
281         if (masklay_shape->flag & MASK_SHAPE_SELECT)
282                 masklay_shape->frame = (int)ED_markers_find_nearest_marker_time(&scene->markers, (float)masklay_shape->frame);
283         return 0;
284 }
285
286 /* snap selected frames to ... */
287 void ED_masklayer_snap_frames(MaskLayer *masklay, Scene *scene, short mode)
288 {
289         switch (mode) {
290                 case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */
291                         ED_masklayer_frames_looper(masklay, scene, snap_masklayer_nearest);
292                         break;
293                 case SNAP_KEYS_CURFRAME: /* snap to current frame */
294                         ED_masklayer_frames_looper(masklay, scene, snap_masklayer_cframe);
295                         break;
296                 case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */
297                         ED_masklayer_frames_looper(masklay, scene, snap_masklayer_nearmarker);
298                         break;
299                 case SNAP_KEYS_NEARSEC: /* snap to nearest second */
300                         ED_masklayer_frames_looper(masklay, scene, snap_masklayer_nearestsec);
301                         break;
302                 default: /* just in case */
303                         break;
304         }
305 }
306