style cleanup: follow style guide for formatting of if/for/while loops, and else...
[blender.git] / source / blender / editors / gpencil / editaction_gpencil.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/gpencil/editaction_gpencil.c
27  *  \ingroup edgpencil
28  */
29
30  
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stddef.h>
35 #include <math.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLI_blenlib.h"
40 #include "BLI_math.h"
41 #include "BLI_utildefines.h"
42
43 #include "DNA_gpencil_types.h"
44 #include "DNA_scene_types.h"
45
46 #include "BKE_fcurve.h"
47 #include "BKE_gpencil.h"
48
49 #include "ED_anim_api.h"
50 #include "ED_gpencil.h"
51 #include "ED_keyframes_edit.h"
52
53 #include "gpencil_intern.h"
54
55 /* ***************************************** */
56 /* NOTE ABOUT THIS FILE:
57  *      This file contains code for editing Grease Pencil data in the Action Editor
58  *      as a 'keyframes', so that a user can adjust the timing of Grease Pencil drawings.
59  *      Therefore, this file mostly contains functions for selecting Grease-Pencil frames.
60  */
61 /* ***************************************** */
62 /* Generics - Loopers */
63
64 /* Loops over the gp-frames for a gp-layer, and applies the given callback */
65 short gplayer_frames_looper (bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPDframe *, Scene *))
66 {
67         bGPDframe *gpf;
68         
69         /* error checker */
70         if (gpl == NULL)
71                 return 0;
72         
73         /* do loop */
74         for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
75                 /* execute callback */
76                 if (gpf_cb(gpf, scene))
77                         return 1;
78         }
79                 
80         /* nothing to return */
81         return 0;
82 }
83
84 /* ****************************************** */
85 /* Data Conversion Tools */
86
87 /* make a listing all the gp-frames in a layer as cfraelems */
88 void gplayer_make_cfra_list (bGPDlayer *gpl, ListBase *elems, short onlysel)
89 {
90         bGPDframe *gpf;
91         CfraElem *ce;
92         
93         /* error checking */
94         if (ELEM(NULL, gpl, elems))
95                 return;
96         
97         /* loop through gp-frames, adding */
98         for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
99                 if ((onlysel == 0) || (gpf->flag & GP_FRAME_SELECT)) {
100                         ce= MEM_callocN(sizeof(CfraElem), "CfraElem");
101                         
102                         ce->cfra= (float)gpf->framenum;
103                         ce->sel= (gpf->flag & GP_FRAME_SELECT) ? 1 : 0;
104                         
105                         BLI_addtail(elems, ce);
106                 }
107         }
108 }
109
110 /* ***************************************** */
111 /* Selection Tools */
112
113 /* check if one of the frames in this layer is selected */
114 short is_gplayer_frame_selected (bGPDlayer *gpl)
115 {
116         bGPDframe *gpf;
117         
118         /* error checking */
119         if (gpl == NULL) 
120                 return 0;
121         
122         /* stop at the first one found */
123         for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
124                 if (gpf->flag & GP_FRAME_SELECT)
125                         return 1;
126         }
127         
128         /* not found */
129         return 0;
130 }
131
132 /* helper function - select gp-frame based on SELECT_* mode */
133 static void gpframe_select (bGPDframe *gpf, short select_mode)
134 {
135         if (gpf == NULL)
136                 return;
137         
138         switch (select_mode) {
139                 case SELECT_ADD:
140                         gpf->flag |= GP_FRAME_SELECT;
141                         break;
142                 case SELECT_SUBTRACT:
143                         gpf->flag &= ~GP_FRAME_SELECT;
144                         break;
145                 case SELECT_INVERT:
146                         gpf->flag ^= GP_FRAME_SELECT;
147                         break;
148         }
149 }
150
151 /* set all/none/invert select (like above, but with SELECT_* modes) */
152 void select_gpencil_frames (bGPDlayer *gpl, short select_mode)
153 {
154         bGPDframe *gpf;
155         
156         /* error checking */
157         if (gpl == NULL) 
158                 return;
159                 
160         /* handle according to mode */
161         for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
162                 gpframe_select(gpf, select_mode);
163         }
164 }
165
166 /* set all/none/invert select */
167 void set_gplayer_frame_selection (bGPDlayer *gpl, short mode)
168 {
169         /* error checking */
170         if (gpl == NULL) 
171                 return;
172         
173         /* now call the standard function */
174         select_gpencil_frames(gpl, mode);
175 }
176
177 /* select the frame in this layer that occurs on this frame (there should only be one at most) */
178 void select_gpencil_frame (bGPDlayer *gpl, int selx, short select_mode)
179 {
180         bGPDframe *gpf;
181         
182         if (gpl == NULL) 
183                 return;
184         
185         /* search through frames for a match */
186         for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
187                 /* there should only be one frame with this frame-number */
188                 if (gpf->framenum == selx) {
189                         gpframe_select(gpf, select_mode);
190                         break;
191                 }
192         }
193 }
194
195 /* select the frames in this layer that occur within the bounds specified */
196 void borderselect_gplayer_frames (bGPDlayer *gpl, float min, float max, short select_mode)
197 {
198         bGPDframe *gpf;
199         
200         if (gpl == NULL)
201                 return;
202         
203         /* only select those frames which are in bounds */
204         for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
205                 if (IN_RANGE(gpf->framenum, min, max))
206                         gpframe_select(gpf, select_mode);
207         }
208 }
209
210 /* ***************************************** */
211 /* Frame Editing Tools */
212
213 /* Delete selected frames */
214 void delete_gplayer_frames (bGPDlayer *gpl)
215 {
216         bGPDframe *gpf, *gpfn;
217         
218         /* error checking */
219         if (gpl == NULL)
220                 return;
221                 
222         /* check for frames to delete */
223         for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
224                 gpfn= gpf->next;
225                 
226                 if (gpf->flag & GP_FRAME_SELECT)
227                         gpencil_layer_delframe(gpl, gpf);
228         }
229 }
230
231 /* Duplicate selected frames from given gp-layer */
232 void duplicate_gplayer_frames (bGPDlayer *gpl)
233 {
234         bGPDframe *gpf, *gpfn;
235         
236         /* error checking */
237         if (gpl == NULL)
238                 return;
239         
240         /* duplicate selected frames  */
241         for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
242                 gpfn= gpf->next;
243                 
244                 /* duplicate this frame */
245                 if (gpf->flag & GP_FRAME_SELECT) {
246                         bGPDframe *gpfd; 
247                         
248                         /* duplicate frame, and deselect self */
249                         gpfd= gpencil_frame_duplicate(gpf);
250                         gpf->flag &= ~GP_FRAME_SELECT;
251                         
252                         BLI_insertlinkafter(&gpl->frames, gpf, gpfd);
253                 }
254         }
255 }
256
257 #if 0 // XXX disabled until grease pencil code stabilises again
258 /* -------------------------------------- */
259 /* Copy and Paste Tools */
260 /* - The copy/paste buffer currently stores a set of GP_Layers, with temporary
261  *      GP_Frames with the necessary strokes
262  * - Unless there is only one element in the buffer, names are also tested to check for compatibility.
263  * - All pasted frames are offset by the same amount. This is calculated as the difference in the times of
264  *      the current frame and the 'first keyframe' (i.e. the earliest one in all channels).
265  * - The earliest frame is calculated per copy operation.
266  */
267  
268 /* globals for copy/paste data (like for other copy/paste buffers) */
269 ListBase gpcopybuf = {NULL, NULL};
270 static int gpcopy_firstframe= 999999999;
271
272 /* This function frees any MEM_calloc'ed copy/paste buffer data */
273 void free_gpcopybuf ()
274 {
275         free_gpencil_layers(&gpcopybuf); 
276         
277         gpcopybuf.first= gpcopybuf.last= NULL;
278         gpcopy_firstframe= 999999999;
279 }
280
281 /* This function adds data to the copy/paste buffer, freeing existing data first
282  * Only the selected GP-layers get their selected keyframes copied.
283  */
284 void copy_gpdata ()
285 {
286         ListBase act_data = {NULL, NULL};
287         bActListElem *ale;
288         int filter;
289         void *data;
290         short datatype;
291         
292         /* clear buffer first */
293         free_gpcopybuf();
294         
295         /* get data */
296         data= get_action_context(&datatype);
297         if (data == NULL) return;
298         if (datatype != ACTCONT_GPENCIL) return;
299         
300         /* filter data */
301         filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL);
302         actdata_filter(&act_data, filter, data, datatype);
303         
304         /* assume that each of these is an ipo-block */
305         for (ale= act_data.first; ale; ale= ale->next) {
306                 bGPDlayer *gpls, *gpln;
307                 bGPDframe *gpf, *gpfn;
308                 
309                 /* get new layer to put into buffer */
310                 gpls= (bGPDlayer *)ale->data;
311                 gpln= MEM_callocN(sizeof(bGPDlayer), "GPCopyPasteLayer");
312                 
313                 gpln->frames.first= gpln->frames.last= NULL;
314                 BLI_strncpy(gpln->info, gpls->info, sizeof(gpln->info));
315                 
316                 BLI_addtail(&gpcopybuf, gpln);
317                 
318                 /* loop over frames, and copy only selected frames */
319                 for (gpf= gpls->frames.first; gpf; gpf= gpf->next) {
320                         /* if frame is selected, make duplicate it and its strokes */
321                         if (gpf->flag & GP_FRAME_SELECT) {
322                                 /* add frame to buffer */
323                                 gpfn= gpencil_frame_duplicate(gpf);
324                                 BLI_addtail(&gpln->frames, gpfn);
325                                 
326                                 /* check if this is the earliest frame encountered so far */
327                                 if (gpf->framenum < gpcopy_firstframe)
328                                         gpcopy_firstframe= gpf->framenum;
329                         }
330                 }
331         }
332         
333         /* check if anything ended up in the buffer */
334         if (ELEM(NULL, gpcopybuf.first, gpcopybuf.last))
335                 error("Nothing copied to buffer");
336         
337         /* free temp memory */
338         BLI_freelistN(&act_data);
339 }
340
341 void paste_gpdata (Scene *scene)
342 {
343         ListBase act_data = {NULL, NULL};
344         bActListElem *ale;
345         int filter;
346         void *data;
347         short datatype;
348         
349         const int offset = (CFRA - gpcopy_firstframe);
350         short no_name= 0;
351         
352         /* check if buffer is empty */
353         if (ELEM(NULL, gpcopybuf.first, gpcopybuf.last)) {
354                 error("No data in buffer to paste");
355                 return;
356         }
357         /* check if single channel in buffer (disregard names if so)  */
358         if (gpcopybuf.first == gpcopybuf.last)
359                 no_name= 1;
360         
361         /* get data */
362         data= get_action_context(&datatype);
363         if (data == NULL) return;
364         if (datatype != ACTCONT_GPENCIL) return;
365         
366         /* filter data */
367         filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_FOREDIT);
368         actdata_filter(&act_data, filter, data, datatype);
369         
370         /* from selected channels */
371         for (ale= act_data.first; ale; ale= ale->next) {
372                 bGPDlayer *gpld= (bGPDlayer *)ale->data;
373                 bGPDlayer *gpls= NULL;
374                 bGPDframe *gpfs, *gpf;
375                 
376                 /* find suitable layer from buffer to use to paste from */
377                 for (gpls= gpcopybuf.first; gpls; gpls= gpls->next) {
378                         /* check if layer name matches */
379                         if ((no_name) || (strcmp(gpls->info, gpld->info)==0))
380                                 break;
381                 }
382                 
383                 /* this situation might occur! */
384                 if (gpls == NULL)
385                         continue;
386                 
387                 /* add frames from buffer */
388                 for (gpfs= gpls->frames.first; gpfs; gpfs= gpfs->next) {
389                         /* temporarily apply offset to buffer-frame while copying */
390                         gpfs->framenum += offset;
391                         
392                         /* get frame to copy data into (if no frame returned, then just ignore) */
393                         gpf= gpencil_layer_getframe(gpld, gpfs->framenum, 1);
394                         if (gpf) {
395                                 bGPDstroke *gps, *gpsn;
396                                 ScrArea *sa;
397                                 
398                                 /* get area that gp-data comes from */
399                                 //sa= gpencil_data_findowner((bGPdata *)ale->owner);    
400                                 sa = NULL;
401                                 
402                                 /* this should be the right frame... as it may be a pre-existing frame, 
403                                  * must make sure that only compatible stroke types get copied over 
404                                  *      - we cannot just add a duplicate frame, as that would cause errors
405                                  *      - need to check for compatible types to minimise memory usage (copying 'junk' over)
406                                  */
407                                 for (gps= gpfs->strokes.first; gps; gps= gps->next) {
408                                         short stroke_ok;
409                                         
410                                         /* if there's an area, check that it supports this type of stroke */
411                                         if (sa) {
412                                                 stroke_ok= 0;
413                                                 
414                                                 /* check if spacetype supports this type of stroke
415                                                  *      - NOTE: must sync this with gp_paint_initstroke() in gpencil.c
416                                                  */
417                                                 switch (sa->spacetype) {
418                                                         case SPACE_VIEW3D: /* 3D-View: either screen-aligned or 3d-space */
419                                                                 if ((gps->flag == 0) || (gps->flag & GP_STROKE_3DSPACE))
420                                                                         stroke_ok= 1;
421                                                                 break;
422                                                                 
423                                                         case SPACE_NODE: /* Nodes Editor: either screen-aligned or view-aligned */
424                                                         case SPACE_IMAGE: /* Image Editor: either screen-aligned or view\image-aligned */
425                                                         case SPACE_CLIP: /* Image Editor: either screen-aligned or view\image-aligned */
426                                                                 if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DSPACE))
427                                                                         stroke_ok= 1;
428                                                                 break;
429                                                                 
430                                                         case SPACE_SEQ: /* Sequence Editor: either screen-aligned or view-aligned */
431                                                                 if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DIMAGE))
432                                                                         stroke_ok= 1;
433                                                                 break;
434                                                 }
435                                         }
436                                         else
437                                                 stroke_ok= 1;
438                                         
439                                         /* if stroke is ok, we make a copy of this stroke and add to frame */
440                                         if (stroke_ok) {
441                                                 /* make a copy of stroke, then of its points array */
442                                                 gpsn= MEM_dupallocN(gps);
443                                                 gpsn->points= MEM_dupallocN(gps->points);
444                                                 
445                                                 /* append stroke to frame */
446                                                 BLI_addtail(&gpf->strokes, gpsn);
447                                         }
448                                 }
449                                 
450                                 /* if no strokes (i.e. new frame) added, free gpf */
451                                 if (gpf->strokes.first == NULL)
452                                         gpencil_layer_delframe(gpld, gpf);
453                         }
454                         
455                         /* unapply offset from buffer-frame */
456                         gpfs->framenum -= offset;
457                 }
458         }
459         
460         /* free temp memory */
461         BLI_freelistN(&act_data);
462         
463         /* undo and redraw stuff */
464         BIF_undo_push("Paste Grease Pencil Frames");
465 }
466
467 /* -------------------------------------- */
468 /* Snap Tools */
469
470 static short snap_gpf_nearest (bGPDframe *gpf, Scene *scene)
471 {
472         if (gpf->flag & GP_FRAME_SELECT)
473                 gpf->framenum= (int)(floor(gpf->framenum+0.5));
474         return 0;
475 }
476
477 static short snap_gpf_nearestsec (bGPDframe *gpf, Scene *scene)
478 {
479         float secf = (float)FPS;
480         if (gpf->flag & GP_FRAME_SELECT)
481                 gpf->framenum= (int)(floor(gpf->framenum/secf + 0.5f) * secf);
482         return 0;
483 }
484
485 static short snap_gpf_cframe (bGPDframe *gpf, Scene *scene)
486 {
487         if (gpf->flag & GP_FRAME_SELECT)
488                 gpf->framenum= (int)CFRA;
489         return 0;
490 }
491
492 static short snap_gpf_nearmarker (bGPDframe *gpf, Scene *scene)
493 {
494         if (gpf->flag & GP_FRAME_SELECT)
495                 gpf->framenum= (int)find_nearest_marker_time(&scene->markers, (float)gpf->framenum);
496         return 0;
497 }
498
499
500 /* snap selected frames to ... */
501 void snap_gplayer_frames (bGPDlayer *gpl, Scene *scene, short mode)
502 {
503         switch (mode) {
504                 case 1: /* snap to nearest frame */
505                         gplayer_frames_looper(gpl, scene, snap_gpf_nearest);
506                         break;
507                 case 2: /* snap to current frame */
508                         gplayer_frames_looper(gpl, scene, snap_gpf_cframe);
509                         break;
510                 case 3: /* snap to nearest marker */
511                         gplayer_frames_looper(gpl, scene, snap_gpf_nearmarker);
512                         break;
513                 case 4: /* snap to nearest second */
514                         gplayer_frames_looper(gpl, scene, snap_gpf_nearestsec);
515                         break;
516                 default: /* just in case */
517                         gplayer_frames_looper(gpl, scene, snap_gpf_nearest);
518                         break;
519         }
520 }
521
522 /* -------------------------------------- */
523 /* Mirror Tools */
524
525 static short mirror_gpf_cframe (bGPDframe *gpf, Scene *scene)
526 {
527         int diff;
528         
529         if (gpf->flag & GP_FRAME_SELECT) {
530                 diff= CFRA - gpf->framenum;
531                 gpf->framenum= CFRA;
532         }
533         
534         return 0;
535 }
536
537 static short mirror_gpf_yaxis (bGPDframe *gpf, Scene *scene)
538 {
539         int diff;
540         
541         if (gpf->flag & GP_FRAME_SELECT) {
542                 diff= -gpf->framenum;
543                 gpf->framenum= diff;
544         }
545         
546         return 0;
547 }
548
549 static short mirror_gpf_xaxis (bGPDframe *gpf, Scene *scene)
550 {
551         int diff;
552         
553         if (gpf->flag & GP_FRAME_SELECT) {
554                 diff= -gpf->framenum;
555                 gpf->framenum= diff;
556         }
557         
558         return 0;
559 }
560
561 static short mirror_gpf_marker (bGPDframe *gpf, Scene *scene)
562 {
563         static TimeMarker *marker;
564         static short initialized = 0;
565         int diff;
566         
567         /* In order for this mirror function to work without
568          * any extra arguments being added, we use the case
569          * of bezt==NULL to denote that we should find the 
570          * marker to mirror over. The static pointer is safe
571          * to use this way, as it will be set to null after 
572          * each cycle in which this is called.
573          */
574         
575         if (gpf) {
576                 /* mirroring time */
577                 if ((gpf->flag & GP_FRAME_SELECT) && (marker)) {
578                         diff= (marker->frame - gpf->framenum);
579                         gpf->framenum= (marker->frame + diff);
580                 }
581         }
582         else {
583                 /* initialization time */
584                 if (initialized) {
585                         /* reset everything for safety */
586                         marker = NULL;
587                         initialized = 0;
588                 }
589                 else {
590                         /* try to find a marker */
591                         marker= ED_markers_get_first_selected(&scene->markers);
592                         if (marker) {
593                                 initialized= 1;
594                         }
595                 }
596         }
597         
598         return 0;
599 }
600
601
602 /* mirror selected gp-frames on... */
603 void mirror_gplayer_frames (bGPDlayer *gpl, Scene *scene, short mode)
604 {
605         switch (mode) {
606                 case 1: /* mirror over current frame */
607                         gplayer_frames_looper(gpl, scene, mirror_gpf_cframe);
608                         break;
609                 case 2: /* mirror over frame 0 */
610                         gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis);
611                         break;
612                 case 3: /* mirror over value 0 */
613                         gplayer_frames_looper(gpl, scene, mirror_gpf_xaxis);
614                         break;
615                 case 4: /* mirror over marker */
616                         mirror_gpf_marker(NULL, NULL);
617                         gplayer_frames_looper(gpl, scene, mirror_gpf_marker);
618                         mirror_gpf_marker(NULL, NULL);
619                         break;
620                 default: /* just in case */
621                         gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis);
622                         break;
623         }
624 }
625
626 /* ***************************************** */
627 #endif // XXX disabled until Grease Pencil code stabilises again...