~ubuntu-branches/ubuntu/maverick/blender/maverick

« back to all changes in this revision

Viewing changes to source/blender/src/editaction_gpencil.c

  • Committer: Bazaar Package Importer
  • Author(s): Khashayar Naderehvandi, Khashayar Naderehvandi, Alessio Treglia
  • Date: 2009-01-22 16:53:59 UTC
  • mfrom: (14.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20090122165359-v0996tn7fbit64ni
Tags: 2.48a+dfsg-1ubuntu1
[ Khashayar Naderehvandi ]
* Merge from debian experimental (LP: #320045), Ubuntu remaining changes:
  - Add patch correcting header file locations.
  - Add libvorbis-dev and libgsm1-dev to Build-Depends.
  - Use avcodec_decode_audio2() in source/blender/src/hddaudio.c

[ Alessio Treglia ]
* Add missing previous changelog entries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * $Id: editaction_gpencil.c 17126 2008-10-20 06:39:08Z aligorith $
 
3
 *
 
4
 * ***** BEGIN GPL LICENSE BLOCK *****
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version 2
 
9
 * of the License, or (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software Foundation,
 
18
 * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
19
 *
 
20
 * The Original Code is Copyright (C) 2008, Blender Foundation
 
21
 * This is a new part of Blender
 
22
 *
 
23
 * Contributor(s): Joshua Leung
 
24
 *
 
25
 * ***** END GPL LICENSE BLOCK *****
 
26
 */
 
27
 
 
28
#include <stdio.h>
 
29
#include <string.h>
 
30
#include <stdlib.h>
 
31
#include <stddef.h>
 
32
#include <math.h>
 
33
 
 
34
#ifdef HAVE_CONFIG_H
 
35
#include <config.h>
 
36
#endif
 
37
 
 
38
#include "MEM_guardedalloc.h"
 
39
 
 
40
#include "BMF_Api.h"
 
41
 
 
42
#include "BLI_arithb.h"
 
43
#include "BLI_blenlib.h"
 
44
 
 
45
#include "DNA_listBase.h"
 
46
#include "DNA_action_types.h"
 
47
#include "DNA_gpencil_types.h"
 
48
#include "DNA_scene_types.h"
 
49
#include "DNA_screen_types.h"
 
50
#include "DNA_space_types.h"
 
51
#include "DNA_userdef_types.h"
 
52
#include "DNA_view3d_types.h"
 
53
#include "DNA_view2d_types.h"
 
54
 
 
55
#include "BKE_global.h"
 
56
#include "BKE_utildefines.h"
 
57
#include "BKE_blender.h"
 
58
#include "BKE_ipo.h"
 
59
 
 
60
#include "BIF_gl.h"
 
61
#include "BIF_glutil.h"
 
62
#include "BIF_butspace.h"
 
63
#include "BIF_graphics.h"
 
64
#include "BIF_interface.h"
 
65
#include "BIF_mywindow.h"
 
66
#include "BIF_resources.h"
 
67
#include "BIF_space.h"
 
68
#include "BIF_screen.h"
 
69
#include "BIF_toolbox.h"
 
70
#include "BIF_toets.h"
 
71
 
 
72
#include "BIF_editaction.h"
 
73
#include "BSE_editaction_types.h"
 
74
 
 
75
#include "BDR_gpencil.h"
 
76
#include "BIF_drawgpencil.h"
 
77
 
 
78
#include "BSE_drawipo.h"
 
79
#include "BSE_headerbuttons.h"
 
80
#include "BSE_time.h"
 
81
#include "BSE_view.h"
 
82
 
 
83
#include "blendef.h"
 
84
#include "butspace.h"
 
85
 
 
86
#include "PIL_time.h"
 
87
#include "mydevice.h"
 
88
 
 
89
/* ***************************************** */
 
90
/* NOTE ABOUT THIS FILE:
 
91
 *      This file contains code for editing Grease Pencil data in the Action Editor
 
92
 *      as a 'keyframes', so that a user can adjust the timing of Grease Pencil drawings.
 
93
 *      Therefore, this file mostly contains functions for selecting Grease-Pencil frames.
 
94
 */
 
95
/* ***************************************** */
 
96
/* Generics - Loopers */
 
97
 
 
98
/* Loops over the gp-frames for a gp-layer, and applies the given callback */
 
99
short gplayer_frames_looper (bGPDlayer *gpl, short (*gpf_cb)(bGPDframe *))
 
100
{
 
101
        bGPDframe *gpf;
 
102
        
 
103
        /* error checker */
 
104
        if (gpl == NULL)
 
105
                return 0;
 
106
        
 
107
        /* do loop */
 
108
        for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
 
109
                /* execute callback */
 
110
                if (gpf_cb(gpf))
 
111
                        return 1;
 
112
        }
 
113
                
 
114
        /* nothing to return */
 
115
        return 0;
 
116
}
 
117
 
 
118
/* ****************************************** */
 
119
/* Data Conversion Tools */
 
120
 
 
121
/* make a listing all the gp-frames in a layer as cfraelems */
 
122
void gplayer_make_cfra_list (bGPDlayer *gpl, ListBase *elems, short onlysel)
 
123
{
 
124
        bGPDframe *gpf;
 
125
        CfraElem *ce;
 
126
        
 
127
        /* error checking */
 
128
        if (ELEM(NULL, gpl, elems))
 
129
                return;
 
130
        
 
131
        /* loop through gp-frames, adding */
 
132
        for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
 
133
                if ((onlysel == 0) || (gpf->flag & GP_FRAME_SELECT)) {
 
134
                        ce= MEM_callocN(sizeof(CfraElem), "CfraElem");
 
135
                        
 
136
                        ce->cfra= (float)gpf->framenum;
 
137
                        ce->sel= (gpf->flag & GP_FRAME_SELECT) ? 1 : 0;
 
138
                        
 
139
                        BLI_addtail(elems, ce);
 
140
                }
 
141
        }
 
142
}
 
143
 
 
144
/* ***************************************** */
 
145
/* Selection Tools */
 
146
 
 
147
/* check if one of the frames in this layer is selected */
 
148
short is_gplayer_frame_selected (bGPDlayer *gpl)
 
149
{
 
150
        bGPDframe *gpf;
 
151
        
 
152
        /* error checking */
 
153
        if (gpl == NULL) 
 
154
                return 0;
 
155
        
 
156
        /* stop at the first one found */
 
157
        for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
 
158
                if (gpf->flag & GP_FRAME_SELECT)
 
159
                        return 1;
 
160
        }
 
161
        
 
162
        /* not found */
 
163
        return 0;
 
164
}
 
165
 
 
166
/* helper function - select gp-frame based on SELECT_* mode */
 
167
static void gpframe_select (bGPDframe *gpf, short select_mode)
 
168
{
 
169
        switch (select_mode) {
 
170
                case SELECT_ADD:
 
171
                        gpf->flag |= GP_FRAME_SELECT;
 
172
                        break;
 
173
                case SELECT_SUBTRACT:
 
174
                        gpf->flag &= ~GP_FRAME_SELECT;
 
175
                        break;
 
176
                case SELECT_INVERT:
 
177
                        gpf->flag ^= GP_FRAME_SELECT;
 
178
                        break;
 
179
        }
 
180
}
 
181
 
 
182
/* set all/none/invert select (like above, but with SELECT_* modes) */
 
183
void select_gpencil_frames (bGPDlayer *gpl, short select_mode)
 
184
{
 
185
        bGPDframe *gpf;
 
186
        
 
187
        /* error checking */
 
188
        if (gpl == NULL) 
 
189
                return;
 
190
                
 
191
        /* handle according to mode */
 
192
        for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
 
193
                gpframe_select(gpf, select_mode);
 
194
        }
 
195
}
 
196
 
 
197
/* set all/none/invert select */
 
198
void set_gplayer_frame_selection (bGPDlayer *gpl, short mode)
 
199
{
 
200
        /* error checking */
 
201
        if (gpl == NULL) 
 
202
                return;
 
203
                
 
204
        /* convert mode to select_mode */
 
205
        switch (mode) {
 
206
                case 2:
 
207
                        mode= SELECT_INVERT;
 
208
                        break;
 
209
                case 1:
 
210
                        mode= SELECT_ADD;
 
211
                        break;
 
212
                case 0:
 
213
                        mode= SELECT_SUBTRACT;
 
214
                        break;
 
215
                default:
 
216
                        return;
 
217
        }
 
218
        
 
219
        /* now call the standard function */
 
220
        select_gpencil_frames (gpl, mode);
 
221
}
 
222
 
 
223
/* select the frame in this layer that occurs on this frame (there should only be one at most) */
 
224
void select_gpencil_frame (bGPDlayer *gpl, int selx, short select_mode)
 
225
{
 
226
        bGPDframe *gpf;
 
227
   
 
228
        /* search through frames for a match */
 
229
        for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
 
230
                /* there should only be one frame with this frame-number */
 
231
                if (gpf->framenum == selx) {
 
232
                        gpframe_select(gpf, select_mode);
 
233
                        break;
 
234
                }
 
235
        }
 
236
}
 
237
 
 
238
/* select the frames in this layer that occur within the bounds specified */
 
239
void borderselect_gplayer_frames (bGPDlayer *gpl, float min, float max, short select_mode)
 
240
{
 
241
        bGPDframe *gpf;
 
242
        
 
243
        /* only select those frames which are in bounds */
 
244
        for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
 
245
                if (IN_RANGE(gpf->framenum, min, max))
 
246
                        gpframe_select(gpf, select_mode);
 
247
        }
 
248
}
 
249
 
 
250
 
 
251
/* De-selects or inverts the selection of Layers for a grease-pencil block
 
252
 *      mode: 0 = default behaviour (select all), 1 = test if (de)select all, 2 = invert all 
 
253
 */
 
254
void deselect_gpencil_layers (void *data, short mode)
 
255
{
 
256
        ListBase act_data = {NULL, NULL};
 
257
        bActListElem *ale;
 
258
        int filter, sel=1;
 
259
        
 
260
        /* filter data */
 
261
        filter= ACTFILTER_VISIBLE;
 
262
        actdata_filter(&act_data, filter, data, ACTCONT_GPENCIL);
 
263
        
 
264
        /* See if we should be selecting or deselecting */
 
265
        if (mode == 1) {
 
266
                for (ale= act_data.first; ale; ale= ale->next) {
 
267
                        if (sel == 0) 
 
268
                                break;
 
269
                        
 
270
                        if (ale->flag & GP_LAYER_SELECT)
 
271
                                sel= 0;
 
272
                }
 
273
        }
 
274
        else
 
275
                sel= 0;
 
276
                
 
277
        /* Now set the flags */
 
278
        for (ale= act_data.first; ale; ale= ale->next) {
 
279
                bGPDlayer *gpl= (bGPDlayer *)ale->data;
 
280
                
 
281
                if (mode == 2)
 
282
                        gpl->flag ^= GP_LAYER_SELECT;
 
283
                else if (sel)
 
284
                        gpl->flag |= GP_LAYER_SELECT;
 
285
                else
 
286
                        gpl->flag &= ~GP_LAYER_SELECT;
 
287
                        
 
288
                gpl->flag &= ~GP_LAYER_ACTIVE;
 
289
        }
 
290
        
 
291
        /* Cleanup */
 
292
        BLI_freelistN(&act_data);
 
293
}
 
294
 
 
295
/* ***************************************** */
 
296
/* Frame Editing Tools */
 
297
 
 
298
/* Delete selected grease-pencil layers */
 
299
void delete_gpencil_layers (void)
 
300
{
 
301
        ListBase act_data = {NULL, NULL};
 
302
        bActListElem *ale, *next;
 
303
        void *data;
 
304
        short datatype;
 
305
        int filter;
 
306
        
 
307
        /* determine what type of data we are operating on */
 
308
        data = get_action_context(&datatype);
 
309
        if (data == NULL) return;
 
310
        if (datatype != ACTCONT_GPENCIL) return;
 
311
        
 
312
        /* filter data */
 
313
        filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_CHANNELS | ACTFILTER_SEL);
 
314
        actdata_filter(&act_data, filter, data, datatype);
 
315
        
 
316
        /* clean up grease-pencil layers */
 
317
        for (ale= act_data.first; ale; ale= next) {
 
318
                bGPdata *gpd= (bGPdata *)ale->owner;
 
319
                bGPDlayer *gpl= (bGPDlayer *)ale->data;
 
320
                next= ale->next;
 
321
                
 
322
                /* free layer and its data */
 
323
                if (SEL_GPL(gpl)) {
 
324
                        free_gpencil_frames(gpl);
 
325
                        BLI_freelinkN(&gpd->layers, gpl);
 
326
                }
 
327
                
 
328
                /* free temp memory */
 
329
                BLI_freelinkN(&act_data, ale);
 
330
        }
 
331
        
 
332
        BIF_undo_push("Delete GPencil Layers");
 
333
        allspace(REDRAWVIEW3D, 0);
 
334
        allqueue(REDRAWACTION, 0);
 
335
}
 
336
 
 
337
/* Delete selected frames */
 
338
void delete_gplayer_frames (bGPDlayer *gpl)
 
339
{
 
340
        bGPDframe *gpf, *gpfn;
 
341
        
 
342
        /* error checking */
 
343
        if (gpl == NULL)
 
344
                return;
 
345
                
 
346
        /* check for frames to delete */
 
347
        for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
 
348
                gpfn= gpf->next;
 
349
                
 
350
                if (gpf->flag & GP_FRAME_SELECT)
 
351
                        gpencil_layer_delframe(gpl, gpf);
 
352
        }
 
353
}
 
354
 
 
355
/* Duplicate selected frames from given gp-layer */
 
356
void duplicate_gplayer_frames (bGPDlayer *gpl)
 
357
{
 
358
        bGPDframe *gpf, *gpfn;
 
359
        
 
360
        /* error checking */
 
361
        if (gpl == NULL)
 
362
                return;
 
363
        
 
364
        /* duplicate selected frames  */
 
365
        for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
 
366
                gpfn= gpf->next;
 
367
                
 
368
                /* duplicate this frame */
 
369
                if (gpf->flag & GP_FRAME_SELECT) {
 
370
                        bGPDframe *gpfd; 
 
371
                        
 
372
                        /* duplicate frame, and deselect self */
 
373
                        gpfd= gpencil_frame_duplicate(gpf);
 
374
                        gpf->flag &= ~GP_FRAME_SELECT;
 
375
                        
 
376
                        BLI_insertlinkafter(&gpl->frames, gpf, gpfd);
 
377
                }
 
378
        }
 
379
}
 
380
 
 
381
/* -------------------------------------- */
 
382
/* Copy and Paste Tools */
 
383
/* - The copy/paste buffer currently stores a set of GP_Layers, with temporary
 
384
 *      GP_Frames with the necessary strokes
 
385
 * - Unless there is only one element in the buffer, names are also tested to check for compatability.
 
386
 * - All pasted frames are offset by the same amount. This is calculated as the difference in the times of
 
387
 *      the current frame and the 'first keyframe' (i.e. the earliest one in all channels).
 
388
 * - The earliest frame is calculated per copy operation.
 
389
 */
 
390
 
 
391
/* globals for copy/paste data (like for other copy/paste buffers) */
 
392
ListBase gpcopybuf = {NULL, NULL};
 
393
static int gpcopy_firstframe= 999999999;
 
394
 
 
395
/* This function frees any MEM_calloc'ed copy/paste buffer data */
 
396
void free_gpcopybuf ()
 
397
{
 
398
        free_gpencil_layers(&gpcopybuf); 
 
399
        
 
400
        gpcopybuf.first= gpcopybuf.last= NULL;
 
401
        gpcopy_firstframe= 999999999;
 
402
}
 
403
 
 
404
/* This function adds data to the copy/paste buffer, freeing existing data first
 
405
 * Only the selected GP-layers get their selected keyframes copied.
 
406
 */
 
407
void copy_gpdata ()
 
408
{
 
409
        ListBase act_data = {NULL, NULL};
 
410
        bActListElem *ale;
 
411
        int filter;
 
412
        void *data;
 
413
        short datatype;
 
414
        
 
415
        /* clear buffer first */
 
416
        free_gpcopybuf();
 
417
        
 
418
        /* get data */
 
419
        data= get_action_context(&datatype);
 
420
        if (data == NULL) return;
 
421
        if (datatype != ACTCONT_GPENCIL) return;
 
422
        
 
423
        /* filter data */
 
424
        filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL);
 
425
        actdata_filter(&act_data, filter, data, datatype);
 
426
        
 
427
        /* assume that each of these is an ipo-block */
 
428
        for (ale= act_data.first; ale; ale= ale->next) {
 
429
                bGPDlayer *gpls, *gpln;
 
430
                bGPDframe *gpf, *gpfn;
 
431
                
 
432
                /* get new layer to put into buffer */
 
433
                gpls= (bGPDlayer *)ale->data;
 
434
                gpln= MEM_callocN(sizeof(bGPDlayer), "GPCopyPasteLayer");
 
435
                
 
436
                gpln->frames.first= gpln->frames.last= NULL;
 
437
                strcpy(gpln->info, gpls->info);
 
438
                
 
439
                BLI_addtail(&gpcopybuf, gpln);
 
440
                
 
441
                /* loop over frames, and copy only selected frames */
 
442
                for (gpf= gpls->frames.first; gpf; gpf= gpf->next) {
 
443
                        /* if frame is selected, make duplicate it and its strokes */
 
444
                        if (gpf->flag & GP_FRAME_SELECT) {
 
445
                                /* add frame to buffer */
 
446
                                gpfn= gpencil_frame_duplicate(gpf);
 
447
                                BLI_addtail(&gpln->frames, gpfn);
 
448
                                
 
449
                                /* check if this is the earliest frame encountered so far */
 
450
                                if (gpf->framenum < gpcopy_firstframe)
 
451
                                        gpcopy_firstframe= gpf->framenum;
 
452
                        }
 
453
                }
 
454
        }
 
455
        
 
456
        /* check if anything ended up in the buffer */
 
457
        if (ELEM(NULL, gpcopybuf.first, gpcopybuf.last))
 
458
                error("Nothing copied to buffer");
 
459
        
 
460
        /* free temp memory */
 
461
        BLI_freelistN(&act_data);
 
462
}
 
463
 
 
464
void paste_gpdata ()
 
465
{
 
466
        ListBase act_data = {NULL, NULL};
 
467
        bActListElem *ale;
 
468
        int filter;
 
469
        void *data;
 
470
        short datatype;
 
471
        
 
472
        const int offset = (CFRA - gpcopy_firstframe);
 
473
        short no_name= 0;
 
474
        
 
475
        /* check if buffer is empty */
 
476
        if (ELEM(NULL, gpcopybuf.first, gpcopybuf.last)) {
 
477
                error("No data in buffer to paste");
 
478
                return;
 
479
        }
 
480
        /* check if single channel in buffer (disregard names if so)  */
 
481
        if (gpcopybuf.first == gpcopybuf.last)
 
482
                no_name= 1;
 
483
        
 
484
        /* get data */
 
485
        data= get_action_context(&datatype);
 
486
        if (data == NULL) return;
 
487
        if (datatype != ACTCONT_GPENCIL) return;
 
488
        
 
489
        /* filter data */
 
490
        filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_FOREDIT);
 
491
        actdata_filter(&act_data, filter, data, datatype);
 
492
        
 
493
        /* from selected channels */
 
494
        for (ale= act_data.first; ale; ale= ale->next) {
 
495
                bGPDlayer *gpld= (bGPDlayer *)ale->data;
 
496
                bGPDlayer *gpls= NULL;
 
497
                bGPDframe *gpfs, *gpf;
 
498
                
 
499
                /* find suitable layer from buffer to use to paste from */
 
500
                for (gpls= gpcopybuf.first; gpls; gpls= gpls->next) {
 
501
                        /* check if layer name matches */
 
502
                        if ((no_name) || (strcmp(gpls->info, gpld->info)==0))
 
503
                                break;
 
504
                }
 
505
                
 
506
                /* this situation might occur! */
 
507
                if (gpls == NULL)
 
508
                        continue;
 
509
                
 
510
                /* add frames from buffer */
 
511
                for (gpfs= gpls->frames.first; gpfs; gpfs= gpfs->next) {
 
512
                        /* temporarily apply offset to buffer-frame while copying */
 
513
                        gpfs->framenum += offset;
 
514
                        
 
515
                        /* get frame to copy data into (if no frame returned, then just ignore) */
 
516
                        gpf= gpencil_layer_getframe(gpld, gpfs->framenum, 1);
 
517
                        if (gpf) {
 
518
                                bGPDstroke *gps, *gpsn;
 
519
                                ScrArea *sa;
 
520
                                
 
521
                                /* get area that gp-data comes from */
 
522
                                sa= gpencil_data_findowner((bGPdata *)ale->owner);                              
 
523
                                
 
524
                                /* this should be the right frame... as it may be a pre-existing frame, 
 
525
                                 * must make sure that only compatible stroke types get copied over 
 
526
                                 *      - we cannot just add a duplicate frame, as that would cause errors
 
527
                                 *      - need to check for compatible types to minimise memory usage (copying 'junk' over)
 
528
                                 */
 
529
                                for (gps= gpfs->strokes.first; gps; gps= gps->next) {
 
530
                                        short stroke_ok;
 
531
                                        
 
532
                                        /* if there's an area, check that it supports this type of stroke */
 
533
                                        if (sa) {
 
534
                                                stroke_ok= 0;
 
535
                                                
 
536
                                                /* check if spacetype supports this type of stroke
 
537
                                                 *      - NOTE: must sync this with gp_paint_initstroke() in gpencil.c
 
538
                                                 */
 
539
                                                switch (sa->spacetype) {
 
540
                                                        case SPACE_VIEW3D: /* 3D-View: either screen-aligned or 3d-space */
 
541
                                                                if ((gps->flag == 0) || (gps->flag & GP_STROKE_3DSPACE))
 
542
                                                                        stroke_ok= 1;
 
543
                                                                break;
 
544
                                                                
 
545
                                                        case SPACE_NODE: /* Nodes Editor: either screen-aligned or view-aligned */
 
546
                                                        case SPACE_IMAGE: /* Image Editor: either screen-aligned or view\image-aligned */
 
547
                                                                if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DSPACE))
 
548
                                                                        stroke_ok= 1;
 
549
                                                                break;
 
550
                                                                
 
551
                                                        case SPACE_SEQ: /* Sequence Editor: either screen-aligned or view-aligned */
 
552
                                                                if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DIMAGE))
 
553
                                                                        stroke_ok= 1;
 
554
                                                                break;
 
555
                                                }
 
556
                                        }
 
557
                                        else
 
558
                                                stroke_ok= 1;
 
559
                                        
 
560
                                        /* if stroke is ok, we make a copy of this stroke and add to frame */
 
561
                                        if (stroke_ok) {
 
562
                                                /* make a copy of stroke, then of its points array */
 
563
                                                gpsn= MEM_dupallocN(gps);
 
564
                                                gpsn->points= MEM_dupallocN(gps->points);
 
565
                                                
 
566
                                                /* append stroke to frame */
 
567
                                                BLI_addtail(&gpf->strokes, gpsn);
 
568
                                        }
 
569
                                }
 
570
                                
 
571
                                /* if no strokes (i.e. new frame) added, free gpf */
 
572
                                if (gpf->strokes.first == NULL)
 
573
                                        gpencil_layer_delframe(gpld, gpf);
 
574
                        }
 
575
                        
 
576
                        /* unapply offset from buffer-frame */
 
577
                        gpfs->framenum -= offset;
 
578
                }
 
579
        }
 
580
        
 
581
        /* free temp memory */
 
582
        BLI_freelistN(&act_data);
 
583
        
 
584
        /* undo and redraw stuff */
 
585
        allqueue(REDRAWVIEW3D, 0);
 
586
        //allqueue(REDRAWNODES, 0);
 
587
        allqueue(REDRAWACTION, 0);
 
588
        BIF_undo_push("Paste Grease Pencil Frames");
 
589
}
 
590
 
 
591
/* -------------------------------------- */
 
592
/* Snap Tools */
 
593
 
 
594
static short snap_gpf_nearest (bGPDframe *gpf)
 
595
{
 
596
        if (gpf->flag & GP_FRAME_SELECT)
 
597
                gpf->framenum= (int)(floor(gpf->framenum+0.5));
 
598
        return 0;
 
599
}
 
600
 
 
601
static short snap_gpf_nearestsec (bGPDframe *gpf)
 
602
{
 
603
        float secf = (float)FPS;
 
604
        if (gpf->flag & GP_FRAME_SELECT)
 
605
                gpf->framenum= (int)(floor(gpf->framenum/secf + 0.5f) * secf);
 
606
        return 0;
 
607
}
 
608
 
 
609
static short snap_gpf_cframe (bGPDframe *gpf)
 
610
{
 
611
        if (gpf->flag & GP_FRAME_SELECT)
 
612
                gpf->framenum= (int)CFRA;
 
613
        return 0;
 
614
}
 
615
 
 
616
static short snap_gpf_nearmarker (bGPDframe *gpf)
 
617
{
 
618
        if (gpf->flag & GP_FRAME_SELECT)
 
619
                gpf->framenum= (int)find_nearest_marker_time((float)gpf->framenum);
 
620
        return 0;
 
621
}
 
622
 
 
623
 
 
624
/* snap selected frames to ... */
 
625
void snap_gplayer_frames (bGPDlayer *gpl, short mode)
 
626
{
 
627
        switch (mode) {
 
628
                case 1: /* snap to nearest frame */
 
629
                        gplayer_frames_looper(gpl, snap_gpf_nearest);
 
630
                        break;
 
631
                case 2: /* snap to current frame */
 
632
                        gplayer_frames_looper(gpl, snap_gpf_cframe);
 
633
                        break;
 
634
                case 3: /* snap to nearest marker */
 
635
                        gplayer_frames_looper(gpl, snap_gpf_nearmarker);
 
636
                        break;
 
637
                case 4: /* snap to nearest second */
 
638
                        gplayer_frames_looper(gpl, snap_gpf_nearestsec);
 
639
                        break;
 
640
                default: /* just in case */
 
641
                        gplayer_frames_looper(gpl, snap_gpf_nearest);
 
642
                        break;
 
643
        }
 
644
}
 
645
 
 
646
/* -------------------------------------- */
 
647
/* Mirror Tools */
 
648
 
 
649
static short mirror_gpf_cframe (bGPDframe *gpf)
 
650
{
 
651
        int diff;
 
652
        
 
653
        if (gpf->flag & GP_FRAME_SELECT) {
 
654
                diff= CFRA - gpf->framenum;
 
655
                gpf->framenum= CFRA;
 
656
        }
 
657
        
 
658
        return 0;
 
659
}
 
660
 
 
661
static short mirror_gpf_yaxis (bGPDframe *gpf)
 
662
{
 
663
        int diff;
 
664
        
 
665
        if (gpf->flag & GP_FRAME_SELECT) {
 
666
                diff= -gpf->framenum;
 
667
                gpf->framenum= diff;
 
668
        }
 
669
        
 
670
        return 0;
 
671
}
 
672
 
 
673
static short mirror_gpf_xaxis (bGPDframe *gpf)
 
674
{
 
675
        int diff;
 
676
        
 
677
        if (gpf->flag & GP_FRAME_SELECT) {
 
678
                diff= -gpf->framenum;
 
679
                gpf->framenum= diff;
 
680
        }
 
681
        
 
682
        return 0;
 
683
}
 
684
 
 
685
static short mirror_gpf_marker (bGPDframe *gpf)
 
686
{
 
687
        static TimeMarker *marker;
 
688
        static short initialised = 0;
 
689
        int diff;
 
690
        
 
691
        /* In order for this mirror function to work without
 
692
         * any extra arguments being added, we use the case
 
693
         * of bezt==NULL to denote that we should find the 
 
694
         * marker to mirror over. The static pointer is safe
 
695
         * to use this way, as it will be set to null after 
 
696
         * each cycle in which this is called.
 
697
         */
 
698
        
 
699
        if (gpf) {
 
700
                /* mirroring time */
 
701
                if ((gpf->flag & GP_FRAME_SELECT) && (marker)) {
 
702
                        diff= (marker->frame - gpf->framenum);
 
703
                        gpf->framenum= (marker->frame + diff);
 
704
                }
 
705
        }
 
706
        else {
 
707
                /* initialisation time */
 
708
                if (initialised) {
 
709
                        /* reset everything for safety */
 
710
                        marker = NULL;
 
711
                        initialised = 0;
 
712
                }
 
713
                else {
 
714
                        /* try to find a marker */
 
715
                        for (marker= G.scene->markers.first; marker; marker=marker->next) {
 
716
                                if (marker->flag & SELECT) {
 
717
                                        initialised = 1;
 
718
                                        break;
 
719
                                }
 
720
                        }
 
721
                        
 
722
                        if (initialised == 0) 
 
723
                                marker = NULL;
 
724
                }
 
725
        }
 
726
        
 
727
        return 0;
 
728
}
 
729
 
 
730
 
 
731
/* mirror selected gp-frames on... */
 
732
void mirror_gplayer_frames (bGPDlayer *gpl, short mode)
 
733
{
 
734
        switch (mode) {
 
735
                case 1: /* mirror over current frame */
 
736
                        gplayer_frames_looper(gpl, mirror_gpf_cframe);
 
737
                        break;
 
738
                case 2: /* mirror over frame 0 */
 
739
                        gplayer_frames_looper(gpl, mirror_gpf_yaxis);
 
740
                        break;
 
741
                case 3: /* mirror over value 0 */
 
742
                        gplayer_frames_looper(gpl, mirror_gpf_xaxis);
 
743
                        break;
 
744
                case 4: /* mirror over marker */
 
745
                        mirror_gpf_marker(NULL);
 
746
                        gplayer_frames_looper(gpl, mirror_gpf_marker);
 
747
                        mirror_gpf_marker(NULL);
 
748
                        break;
 
749
                default: /* just in case */
 
750
                        gplayer_frames_looper(gpl, mirror_gpf_yaxis);
 
751
                        break;
 
752
        }
 
753
}
 
754
 
 
755
/* ***************************************** */