Blender V2.61 - r43446

editaction_gpencil.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2008, Blender Foundation
00019  * This is a new part of Blender
00020  *
00021  * Contributor(s): Joshua Leung
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  */
00025 
00031 #include <stdio.h>
00032 #include <string.h>
00033 #include <stdlib.h>
00034 #include <stddef.h>
00035 #include <math.h>
00036 
00037 #include "MEM_guardedalloc.h"
00038 
00039 #include "BLI_blenlib.h"
00040 #include "BLI_math.h"
00041 #include "BLI_utildefines.h"
00042 
00043 #include "DNA_gpencil_types.h"
00044 #include "DNA_scene_types.h"
00045 
00046 #include "BKE_fcurve.h"
00047 #include "BKE_gpencil.h"
00048 
00049 #include "ED_anim_api.h"
00050 #include "ED_gpencil.h"
00051 #include "ED_keyframes_edit.h"
00052 
00053 #include "gpencil_intern.h"
00054 
00055 /* ***************************************** */
00056 /* NOTE ABOUT THIS FILE:
00057  *  This file contains code for editing Grease Pencil data in the Action Editor
00058  *  as a 'keyframes', so that a user can adjust the timing of Grease Pencil drawings.
00059  *  Therefore, this file mostly contains functions for selecting Grease-Pencil frames.
00060  */
00061 /* ***************************************** */
00062 /* Generics - Loopers */
00063 
00064 /* Loops over the gp-frames for a gp-layer, and applies the given callback */
00065 short gplayer_frames_looper (bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPDframe *, Scene *))
00066 {
00067     bGPDframe *gpf;
00068     
00069     /* error checker */
00070     if (gpl == NULL)
00071         return 0;
00072     
00073     /* do loop */
00074     for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
00075         /* execute callback */
00076         if (gpf_cb(gpf, scene))
00077             return 1;
00078     }
00079         
00080     /* nothing to return */
00081     return 0;
00082 }
00083 
00084 /* ****************************************** */
00085 /* Data Conversion Tools */
00086 
00087 /* make a listing all the gp-frames in a layer as cfraelems */
00088 void gplayer_make_cfra_list (bGPDlayer *gpl, ListBase *elems, short onlysel)
00089 {
00090     bGPDframe *gpf;
00091     CfraElem *ce;
00092     
00093     /* error checking */
00094     if (ELEM(NULL, gpl, elems))
00095         return;
00096     
00097     /* loop through gp-frames, adding */
00098     for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
00099         if ((onlysel == 0) || (gpf->flag & GP_FRAME_SELECT)) {
00100             ce= MEM_callocN(sizeof(CfraElem), "CfraElem");
00101             
00102             ce->cfra= (float)gpf->framenum;
00103             ce->sel= (gpf->flag & GP_FRAME_SELECT) ? 1 : 0;
00104             
00105             BLI_addtail(elems, ce);
00106         }
00107     }
00108 }
00109 
00110 /* ***************************************** */
00111 /* Selection Tools */
00112 
00113 /* check if one of the frames in this layer is selected */
00114 short is_gplayer_frame_selected (bGPDlayer *gpl)
00115 {
00116     bGPDframe *gpf;
00117     
00118     /* error checking */
00119     if (gpl == NULL) 
00120         return 0;
00121     
00122     /* stop at the first one found */
00123     for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
00124         if (gpf->flag & GP_FRAME_SELECT)
00125             return 1;
00126     }
00127     
00128     /* not found */
00129     return 0;
00130 }
00131 
00132 /* helper function - select gp-frame based on SELECT_* mode */
00133 static void gpframe_select (bGPDframe *gpf, short select_mode)
00134 {
00135     if (gpf == NULL)
00136         return;
00137     
00138     switch (select_mode) {
00139         case SELECT_ADD:
00140             gpf->flag |= GP_FRAME_SELECT;
00141             break;
00142         case SELECT_SUBTRACT:
00143             gpf->flag &= ~GP_FRAME_SELECT;
00144             break;
00145         case SELECT_INVERT:
00146             gpf->flag ^= GP_FRAME_SELECT;
00147             break;
00148     }
00149 }
00150 
00151 /* set all/none/invert select (like above, but with SELECT_* modes) */
00152 void select_gpencil_frames (bGPDlayer *gpl, short select_mode)
00153 {
00154     bGPDframe *gpf;
00155     
00156     /* error checking */
00157     if (gpl == NULL) 
00158         return;
00159         
00160     /* handle according to mode */
00161     for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
00162         gpframe_select(gpf, select_mode);
00163     }
00164 }
00165 
00166 /* set all/none/invert select */
00167 void set_gplayer_frame_selection (bGPDlayer *gpl, short mode)
00168 {
00169     /* error checking */
00170     if (gpl == NULL) 
00171         return;
00172     
00173     /* now call the standard function */
00174     select_gpencil_frames(gpl, mode);
00175 }
00176 
00177 /* select the frame in this layer that occurs on this frame (there should only be one at most) */
00178 void select_gpencil_frame (bGPDlayer *gpl, int selx, short select_mode)
00179 {
00180     bGPDframe *gpf;
00181     
00182     if (gpl == NULL) 
00183         return;
00184     
00185     /* search through frames for a match */
00186     for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
00187         /* there should only be one frame with this frame-number */
00188         if (gpf->framenum == selx) {
00189             gpframe_select(gpf, select_mode);
00190             break;
00191         }
00192     }
00193 }
00194 
00195 /* select the frames in this layer that occur within the bounds specified */
00196 void borderselect_gplayer_frames (bGPDlayer *gpl, float min, float max, short select_mode)
00197 {
00198     bGPDframe *gpf;
00199     
00200     if (gpl == NULL)
00201         return;
00202     
00203     /* only select those frames which are in bounds */
00204     for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
00205         if (IN_RANGE(gpf->framenum, min, max))
00206             gpframe_select(gpf, select_mode);
00207     }
00208 }
00209 
00210 /* ***************************************** */
00211 /* Frame Editing Tools */
00212 
00213 /* Delete selected frames */
00214 void delete_gplayer_frames (bGPDlayer *gpl)
00215 {
00216     bGPDframe *gpf, *gpfn;
00217     
00218     /* error checking */
00219     if (gpl == NULL)
00220         return;
00221         
00222     /* check for frames to delete */
00223     for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
00224         gpfn= gpf->next;
00225         
00226         if (gpf->flag & GP_FRAME_SELECT)
00227             gpencil_layer_delframe(gpl, gpf);
00228     }
00229 }
00230 
00231 /* Duplicate selected frames from given gp-layer */
00232 void duplicate_gplayer_frames (bGPDlayer *gpl)
00233 {
00234     bGPDframe *gpf, *gpfn;
00235     
00236     /* error checking */
00237     if (gpl == NULL)
00238         return;
00239     
00240     /* duplicate selected frames  */
00241     for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
00242         gpfn= gpf->next;
00243         
00244         /* duplicate this frame */
00245         if (gpf->flag & GP_FRAME_SELECT) {
00246             bGPDframe *gpfd; 
00247             
00248             /* duplicate frame, and deselect self */
00249             gpfd= gpencil_frame_duplicate(gpf);
00250             gpf->flag &= ~GP_FRAME_SELECT;
00251             
00252             BLI_insertlinkafter(&gpl->frames, gpf, gpfd);
00253         }
00254     }
00255 }
00256 
00257 #if 0 // XXX disabled until grease pencil code stabilises again
00258 /* -------------------------------------- */
00259 /* Copy and Paste Tools */
00260 /* - The copy/paste buffer currently stores a set of GP_Layers, with temporary
00261  *  GP_Frames with the necessary strokes
00262  * - Unless there is only one element in the buffer, names are also tested to check for compatibility.
00263  * - All pasted frames are offset by the same amount. This is calculated as the difference in the times of
00264  *  the current frame and the 'first keyframe' (i.e. the earliest one in all channels).
00265  * - The earliest frame is calculated per copy operation.
00266  */
00267  
00268 /* globals for copy/paste data (like for other copy/paste buffers) */
00269 ListBase gpcopybuf = {NULL, NULL};
00270 static int gpcopy_firstframe= 999999999;
00271 
00272 /* This function frees any MEM_calloc'ed copy/paste buffer data */
00273 void free_gpcopybuf ()
00274 {
00275     free_gpencil_layers(&gpcopybuf); 
00276     
00277     gpcopybuf.first= gpcopybuf.last= NULL;
00278     gpcopy_firstframe= 999999999;
00279 }
00280 
00281 /* This function adds data to the copy/paste buffer, freeing existing data first
00282  * Only the selected GP-layers get their selected keyframes copied.
00283  */
00284 void copy_gpdata ()
00285 {
00286     ListBase act_data = {NULL, NULL};
00287     bActListElem *ale;
00288     int filter;
00289     void *data;
00290     short datatype;
00291     
00292     /* clear buffer first */
00293     free_gpcopybuf();
00294     
00295     /* get data */
00296     data= get_action_context(&datatype);
00297     if (data == NULL) return;
00298     if (datatype != ACTCONT_GPENCIL) return;
00299     
00300     /* filter data */
00301     filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL);
00302     actdata_filter(&act_data, filter, data, datatype);
00303     
00304     /* assume that each of these is an ipo-block */
00305     for (ale= act_data.first; ale; ale= ale->next) {
00306         bGPDlayer *gpls, *gpln;
00307         bGPDframe *gpf, *gpfn;
00308         
00309         /* get new layer to put into buffer */
00310         gpls= (bGPDlayer *)ale->data;
00311         gpln= MEM_callocN(sizeof(bGPDlayer), "GPCopyPasteLayer");
00312         
00313         gpln->frames.first= gpln->frames.last= NULL;
00314         BLI_strncpy(gpln->info, gpls->info, sizeof(gpln->info));
00315         
00316         BLI_addtail(&gpcopybuf, gpln);
00317         
00318         /* loop over frames, and copy only selected frames */
00319         for (gpf= gpls->frames.first; gpf; gpf= gpf->next) {
00320             /* if frame is selected, make duplicate it and its strokes */
00321             if (gpf->flag & GP_FRAME_SELECT) {
00322                 /* add frame to buffer */
00323                 gpfn= gpencil_frame_duplicate(gpf);
00324                 BLI_addtail(&gpln->frames, gpfn);
00325                 
00326                 /* check if this is the earliest frame encountered so far */
00327                 if (gpf->framenum < gpcopy_firstframe)
00328                     gpcopy_firstframe= gpf->framenum;
00329             }
00330         }
00331     }
00332     
00333     /* check if anything ended up in the buffer */
00334     if (ELEM(NULL, gpcopybuf.first, gpcopybuf.last))
00335         error("Nothing copied to buffer");
00336     
00337     /* free temp memory */
00338     BLI_freelistN(&act_data);
00339 }
00340 
00341 void paste_gpdata (Scene *scene)
00342 {
00343     ListBase act_data = {NULL, NULL};
00344     bActListElem *ale;
00345     int filter;
00346     void *data;
00347     short datatype;
00348     
00349     const int offset = (CFRA - gpcopy_firstframe);
00350     short no_name= 0;
00351     
00352     /* check if buffer is empty */
00353     if (ELEM(NULL, gpcopybuf.first, gpcopybuf.last)) {
00354         error("No data in buffer to paste");
00355         return;
00356     }
00357     /* check if single channel in buffer (disregard names if so)  */
00358     if (gpcopybuf.first == gpcopybuf.last)
00359         no_name= 1;
00360     
00361     /* get data */
00362     data= get_action_context(&datatype);
00363     if (data == NULL) return;
00364     if (datatype != ACTCONT_GPENCIL) return;
00365     
00366     /* filter data */
00367     filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_FOREDIT);
00368     actdata_filter(&act_data, filter, data, datatype);
00369     
00370     /* from selected channels */
00371     for (ale= act_data.first; ale; ale= ale->next) {
00372         bGPDlayer *gpld= (bGPDlayer *)ale->data;
00373         bGPDlayer *gpls= NULL;
00374         bGPDframe *gpfs, *gpf;
00375         
00376         /* find suitable layer from buffer to use to paste from */
00377         for (gpls= gpcopybuf.first; gpls; gpls= gpls->next) {
00378             /* check if layer name matches */
00379             if ((no_name) || (strcmp(gpls->info, gpld->info)==0))
00380                 break;
00381         }
00382         
00383         /* this situation might occur! */
00384         if (gpls == NULL)
00385             continue;
00386         
00387         /* add frames from buffer */
00388         for (gpfs= gpls->frames.first; gpfs; gpfs= gpfs->next) {
00389             /* temporarily apply offset to buffer-frame while copying */
00390             gpfs->framenum += offset;
00391             
00392             /* get frame to copy data into (if no frame returned, then just ignore) */
00393             gpf= gpencil_layer_getframe(gpld, gpfs->framenum, 1);
00394             if (gpf) {
00395                 bGPDstroke *gps, *gpsn;
00396                 ScrArea *sa;
00397                 
00398                 /* get area that gp-data comes from */
00399                 //sa= gpencil_data_findowner((bGPdata *)ale->owner);    
00400                 sa = NULL;
00401                 
00402                 /* this should be the right frame... as it may be a pre-existing frame, 
00403                  * must make sure that only compatible stroke types get copied over 
00404                  *  - we cannot just add a duplicate frame, as that would cause errors
00405                  *  - need to check for compatible types to minimise memory usage (copying 'junk' over)
00406                  */
00407                 for (gps= gpfs->strokes.first; gps; gps= gps->next) {
00408                     short stroke_ok;
00409                     
00410                     /* if there's an area, check that it supports this type of stroke */
00411                     if (sa) {
00412                         stroke_ok= 0;
00413                         
00414                         /* check if spacetype supports this type of stroke
00415                          *  - NOTE: must sync this with gp_paint_initstroke() in gpencil.c
00416                          */
00417                         switch (sa->spacetype) {
00418                             case SPACE_VIEW3D: /* 3D-View: either screen-aligned or 3d-space */
00419                                 if ((gps->flag == 0) || (gps->flag & GP_STROKE_3DSPACE))
00420                                     stroke_ok= 1;
00421                                 break;
00422                                 
00423                             case SPACE_NODE: /* Nodes Editor: either screen-aligned or view-aligned */
00424                             case SPACE_IMAGE: /* Image Editor: either screen-aligned or view\image-aligned */
00425                             case SPACE_CLIP: /* Image Editor: either screen-aligned or view\image-aligned */
00426                                 if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DSPACE))
00427                                     stroke_ok= 1;
00428                                 break;
00429                                 
00430                             case SPACE_SEQ: /* Sequence Editor: either screen-aligned or view-aligned */
00431                                 if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DIMAGE))
00432                                     stroke_ok= 1;
00433                                 break;
00434                         }
00435                     }
00436                     else
00437                         stroke_ok= 1;
00438                     
00439                     /* if stroke is ok, we make a copy of this stroke and add to frame */
00440                     if (stroke_ok) {
00441                         /* make a copy of stroke, then of its points array */
00442                         gpsn= MEM_dupallocN(gps);
00443                         gpsn->points= MEM_dupallocN(gps->points);
00444                         
00445                         /* append stroke to frame */
00446                         BLI_addtail(&gpf->strokes, gpsn);
00447                     }
00448                 }
00449                 
00450                 /* if no strokes (i.e. new frame) added, free gpf */
00451                 if (gpf->strokes.first == NULL)
00452                     gpencil_layer_delframe(gpld, gpf);
00453             }
00454             
00455             /* unapply offset from buffer-frame */
00456             gpfs->framenum -= offset;
00457         }
00458     }
00459     
00460     /* free temp memory */
00461     BLI_freelistN(&act_data);
00462     
00463     /* undo and redraw stuff */
00464     BIF_undo_push("Paste Grease Pencil Frames");
00465 }
00466 
00467 /* -------------------------------------- */
00468 /* Snap Tools */
00469 
00470 static short snap_gpf_nearest (bGPDframe *gpf, Scene *scene)
00471 {
00472     if (gpf->flag & GP_FRAME_SELECT)
00473         gpf->framenum= (int)(floor(gpf->framenum+0.5));
00474     return 0;
00475 }
00476 
00477 static short snap_gpf_nearestsec (bGPDframe *gpf, Scene *scene)
00478 {
00479     float secf = (float)FPS;
00480     if (gpf->flag & GP_FRAME_SELECT)
00481         gpf->framenum= (int)(floor(gpf->framenum/secf + 0.5f) * secf);
00482     return 0;
00483 }
00484 
00485 static short snap_gpf_cframe (bGPDframe *gpf, Scene *scene)
00486 {
00487     if (gpf->flag & GP_FRAME_SELECT)
00488         gpf->framenum= (int)CFRA;
00489     return 0;
00490 }
00491 
00492 static short snap_gpf_nearmarker (bGPDframe *gpf, Scene *scene)
00493 {
00494     if (gpf->flag & GP_FRAME_SELECT)
00495         gpf->framenum= (int)find_nearest_marker_time(&scene->markers, (float)gpf->framenum);
00496     return 0;
00497 }
00498 
00499 
00500 /* snap selected frames to ... */
00501 void snap_gplayer_frames (bGPDlayer *gpl, Scene *scene, short mode)
00502 {
00503     switch (mode) {
00504         case 1: /* snap to nearest frame */
00505             gplayer_frames_looper(gpl, scene, snap_gpf_nearest);
00506             break;
00507         case 2: /* snap to current frame */
00508             gplayer_frames_looper(gpl, scene, snap_gpf_cframe);
00509             break;
00510         case 3: /* snap to nearest marker */
00511             gplayer_frames_looper(gpl, scene, snap_gpf_nearmarker);
00512             break;
00513         case 4: /* snap to nearest second */
00514             gplayer_frames_looper(gpl, scene, snap_gpf_nearestsec);
00515             break;
00516         default: /* just in case */
00517             gplayer_frames_looper(gpl, scene, snap_gpf_nearest);
00518             break;
00519     }
00520 }
00521 
00522 /* -------------------------------------- */
00523 /* Mirror Tools */
00524 
00525 static short mirror_gpf_cframe (bGPDframe *gpf, Scene *scene)
00526 {
00527     int diff;
00528     
00529     if (gpf->flag & GP_FRAME_SELECT) {
00530         diff= CFRA - gpf->framenum;
00531         gpf->framenum= CFRA;
00532     }
00533     
00534     return 0;
00535 }
00536 
00537 static short mirror_gpf_yaxis (bGPDframe *gpf, Scene *scene)
00538 {
00539     int diff;
00540     
00541     if (gpf->flag & GP_FRAME_SELECT) {
00542         diff= -gpf->framenum;
00543         gpf->framenum= diff;
00544     }
00545     
00546     return 0;
00547 }
00548 
00549 static short mirror_gpf_xaxis (bGPDframe *gpf, Scene *scene)
00550 {
00551     int diff;
00552     
00553     if (gpf->flag & GP_FRAME_SELECT) {
00554         diff= -gpf->framenum;
00555         gpf->framenum= diff;
00556     }
00557     
00558     return 0;
00559 }
00560 
00561 static short mirror_gpf_marker (bGPDframe *gpf, Scene *scene)
00562 {
00563     static TimeMarker *marker;
00564     static short initialised = 0;
00565     int diff;
00566     
00567     /* In order for this mirror function to work without
00568      * any extra arguments being added, we use the case
00569      * of bezt==NULL to denote that we should find the 
00570      * marker to mirror over. The static pointer is safe
00571      * to use this way, as it will be set to null after 
00572      * each cycle in which this is called.
00573      */
00574     
00575     if (gpf) {
00576         /* mirroring time */
00577         if ((gpf->flag & GP_FRAME_SELECT) && (marker)) {
00578             diff= (marker->frame - gpf->framenum);
00579             gpf->framenum= (marker->frame + diff);
00580         }
00581     }
00582     else {
00583         /* initialisation time */
00584         if (initialised) {
00585             /* reset everything for safety */
00586             marker = NULL;
00587             initialised = 0;
00588         }
00589         else {
00590             /* try to find a marker */
00591             marker= ED_markers_get_first_selected(&scene->markers);
00592             if(marker) {
00593                 initialised= 1;
00594             }
00595         }
00596     }
00597     
00598     return 0;
00599 }
00600 
00601 
00602 /* mirror selected gp-frames on... */
00603 void mirror_gplayer_frames (bGPDlayer *gpl, Scene *scene, short mode)
00604 {
00605     switch (mode) {
00606         case 1: /* mirror over current frame */
00607             gplayer_frames_looper(gpl, scene, mirror_gpf_cframe);
00608             break;
00609         case 2: /* mirror over frame 0 */
00610             gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis);
00611             break;
00612         case 3: /* mirror over value 0 */
00613             gplayer_frames_looper(gpl, scene, mirror_gpf_xaxis);
00614             break;
00615         case 4: /* mirror over marker */
00616             mirror_gpf_marker(NULL, NULL);
00617             gplayer_frames_looper(gpl, scene, mirror_gpf_marker);
00618             mirror_gpf_marker(NULL, NULL);
00619             break;
00620         default: /* just in case */
00621             gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis);
00622             break;
00623     }
00624 }
00625 
00626 /* ***************************************** */
00627 #endif // XXX disabled until Grease Pencil code stabilises again...