~diresu/blender/blender-command-port

« back to all changes in this revision

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

  • Committer: theeth
  • Date: 2008-10-14 16:52:04 UTC
  • Revision ID: vcs-imports@canonical.com-20081014165204-r32w2gm6s0osvdhn
copy back trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * $Id: BIF_edittime.c
 
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) 2001-2002 by NaN Holding BV.
 
21
 * All rights reserved.
 
22
 *
 
23
 * The Original Code is: all of this file.
 
24
 *
 
25
 * Contributor(s): none yet.
 
26
 *
 
27
 * ***** END GPL LICENSE BLOCK *****
 
28
 */
 
29
 
 
30
#include <stdio.h>
 
31
#include <stdlib.h>
 
32
#include <math.h>
 
33
#include <string.h>
 
34
#include <math.h>
 
35
 
 
36
#ifdef HAVE_CONFIG_H
 
37
#include <config.h>
 
38
#endif
 
39
 
 
40
#include "MEM_guardedalloc.h"
 
41
 
 
42
#include "BLI_blenlib.h"
 
43
#include "BLI_arithb.h"
 
44
 
 
45
#include "DNA_action_types.h"
 
46
#include "DNA_ipo_types.h"
 
47
#include "DNA_object_types.h"
 
48
#include "DNA_material_types.h"
 
49
#include "DNA_space_types.h"
 
50
#include "DNA_screen_types.h"
 
51
#include "DNA_scene_types.h"
 
52
#include "DNA_userdef_types.h"
 
53
 
 
54
#include "BKE_ipo.h"
 
55
#include "BKE_utildefines.h"
 
56
#include "BKE_global.h"
 
57
#include "BKE_main.h"
 
58
#include "BKE_material.h"
 
59
#include "BKE_library.h"
 
60
 
 
61
#include "BIF_space.h"
 
62
#include "BIF_screen.h"
 
63
#include "BIF_interface.h"
 
64
#include "BIF_toolbox.h"
 
65
#include "BIF_mywindow.h"
 
66
#include "BIF_editaction.h"
 
67
 
 
68
#include "BSE_drawipo.h"
 
69
#include "BSE_edit.h"
 
70
#include "BSE_headerbuttons.h"
 
71
#include "BSE_time.h"
 
72
 
 
73
#include "BDR_editobject.h"
 
74
 
 
75
#include "blendef.h"
 
76
 
 
77
#include "mydevice.h"
 
78
 
 
79
#include "PIL_time.h"
 
80
 
 
81
/* declarations */
 
82
void winqreadtimespace(ScrArea *, void *, BWinEvent *);
 
83
 
 
84
/* ************* Marker API **************** */
 
85
 
 
86
/* add TimeMarker at curent frame */
 
87
void add_marker(int frame)
 
88
{
 
89
        TimeMarker *marker;
 
90
        
 
91
        /* two markers can't be at the same place */
 
92
        for(marker= G.scene->markers.first; marker; marker= marker->next)
 
93
                if(marker->frame == frame) return;
 
94
        /* deselect all */
 
95
        for(marker= G.scene->markers.first; marker; marker= marker->next)
 
96
                marker->flag &= ~SELECT;
 
97
                
 
98
        marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
 
99
        marker->flag= SELECT;
 
100
        marker->frame= frame;
 
101
        BLI_addtail(&(G.scene->markers), marker);
 
102
        
 
103
        BIF_undo_push("Add Marker");
 
104
}
 
105
 
 
106
 
 
107
 
 
108
/* remove selected TimeMarkers */
 
109
void remove_marker(void)
 
110
{
 
111
        TimeMarker *marker, *nmarker;
 
112
        short changed= 0;
 
113
                
 
114
        for(marker= G.scene->markers.first; marker; marker= nmarker) {
 
115
                nmarker= marker->next;
 
116
                if(marker->flag & SELECT) {
 
117
                        BLI_freelinkN(&(G.scene->markers), marker);
 
118
                        changed= 1;
 
119
                }
 
120
        }
 
121
        
 
122
        if (changed)
 
123
                BIF_undo_push("Remove Marker");
 
124
}
 
125
 
 
126
/* rename first selected TimeMarker */
 
127
void rename_marker(void)
 
128
{
 
129
        TimeMarker *marker;
 
130
        char name[64];
 
131
                        
 
132
        for(marker= G.scene->markers.first; marker; marker= marker->next) {
 
133
                if(marker->flag & SELECT) {
 
134
                        strcpy(name, marker->name);
 
135
                        if (sbutton(name, 0, sizeof(name)-1, "Name: "))
 
136
                                BLI_strncpy(marker->name, name, sizeof(marker->name));
 
137
                        break;
 
138
                }
 
139
        }
 
140
        
 
141
//      BIF_undo_push("Rename Marker");
 
142
}
 
143
 
 
144
/* duplicate selected TimeMarkers */
 
145
void duplicate_marker(void)
 
146
{
 
147
        TimeMarker *marker, *newmarker;
 
148
        
 
149
        /* go through the list of markers, duplicate selected markers and add duplicated copies
 
150
         * to the begining of the list (unselect original markers) */
 
151
        for(marker= G.scene->markers.first; marker; marker= marker->next) {
 
152
                if(marker->flag & SELECT){
 
153
                        /* unselect selected marker */
 
154
                        marker->flag &= ~SELECT;
 
155
                        /* create and set up new marker */
 
156
                        newmarker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
 
157
                        newmarker->flag= SELECT;
 
158
                        newmarker->frame= marker->frame;
 
159
                        BLI_strncpy(newmarker->name, marker->name, sizeof(marker->name));
 
160
                        /* new marker is added to the begining of list */
 
161
                        BLI_addhead(&(G.scene->markers), newmarker);
 
162
                }
 
163
        }
 
164
        
 
165
        transform_markers('g', 0);
 
166
}
 
167
 
 
168
void transform_markers(int mode, int smode)     // mode and smode unused here, for callback
 
169
{
 
170
        SpaceLink *slink= curarea->spacedata.first;
 
171
        SpaceTime *stime= curarea->spacedata.first;
 
172
        SpaceAction *saction = curarea->spacedata.first;
 
173
        ListBase *markers;
 
174
        TimeMarker *marker, *selmarker=NULL;
 
175
        float dx, fac;
 
176
        int a, ret_val= 0, totmark=0, *oldframe, offs, firsttime=1;
 
177
        unsigned short event;
 
178
        short val, pmval[2], mval[2], mvalo[2];
 
179
        char str[32];
 
180
        
 
181
        /* hack for pose-markers in action editor */
 
182
        if ((slink->spacetype == SPACE_ACTION) && (saction->flag & SACTION_POSEMARKERS_MOVE)) {
 
183
                if (saction->action)
 
184
                        markers= &saction->action->markers;
 
185
                else
 
186
                        markers= NULL;
 
187
        }
 
188
        else
 
189
                markers= &G.scene->markers;
 
190
        
 
191
        for (marker= markers->first; marker; marker= marker->next) {
 
192
                if (marker->flag & SELECT) totmark++;
 
193
        }
 
194
        if (totmark==0) return;
 
195
        
 
196
        oldframe= MEM_mallocN(totmark*sizeof(int), "marker array");
 
197
        for (a=0, marker= markers->first; marker; marker= marker->next) {
 
198
                if (marker->flag & SELECT) {
 
199
                        oldframe[a]= marker->frame;
 
200
                        selmarker= marker;      // used for headerprint
 
201
                        a++;
 
202
                }
 
203
        }
 
204
        
 
205
        dx= G.v2d->mask.xmax-G.v2d->mask.xmin;
 
206
        dx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/dx;
 
207
        
 
208
        getmouseco_areawin(pmval);
 
209
        mvalo[0]= pmval[0];
 
210
        
 
211
        while (ret_val == 0) {
 
212
                getmouseco_areawin(mval);
 
213
                
 
214
                if (mval[0] != mvalo[0] || firsttime) {
 
215
                        mvalo[0]= mval[0];
 
216
                        firsttime= 0;
 
217
                        
 
218
                        fac= (((float)(mval[0] - pmval[0]))*dx);
 
219
                        
 
220
                        if (ELEM(slink->spacetype, SPACE_TIME, SPACE_SOUND)) 
 
221
                                apply_keyb_grid(&fac, 0.0, FPS, 0.1*FPS, 0);
 
222
                        else
 
223
                                apply_keyb_grid(&fac, 0.0, 1.0, 0.1, U.flag & USER_AUTOGRABGRID);
 
224
                        offs= (int)fac;
 
225
                        
 
226
                        for (a=0, marker= markers->first; marker; marker= marker->next) {
 
227
                                if (marker->flag & SELECT) {
 
228
                                        marker->frame= oldframe[a] + offs;
 
229
                                        a++;
 
230
                                }
 
231
                        }
 
232
                        
 
233
                        if (totmark==1) {       
 
234
                                /* we print current marker value */
 
235
                                if (ELEM(slink->spacetype, SPACE_TIME, SPACE_SOUND)) {
 
236
                                        if (stime->flag & TIME_DRAWFRAMES) 
 
237
                                                sprintf(str, "Marker %d offset %d", selmarker->frame, offs);
 
238
                                        else 
 
239
                                                sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
 
240
                                }
 
241
                                else if (slink->spacetype == SPACE_ACTION) {
 
242
                                        if (saction->flag & SACTION_DRAWTIME)
 
243
                                                sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
 
244
                                        else
 
245
                                                sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
 
246
                                }
 
247
                                else {
 
248
                                        sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
 
249
                                }
 
250
                        }
 
251
                        else {
 
252
                                /* we only print the offset */
 
253
                                if (ELEM(slink->spacetype, SPACE_TIME, SPACE_SOUND)) { 
 
254
                                        if (stime->flag & TIME_DRAWFRAMES) 
 
255
                                                sprintf(str, "Marker offset %d ", offs);
 
256
                                        else 
 
257
                                                sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
 
258
                                }
 
259
                                else if (slink->spacetype == SPACE_ACTION) {
 
260
                                        if (saction->flag & SACTION_DRAWTIME)
 
261
                                                sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
 
262
                                        else
 
263
                                                sprintf(str, "Marker offset %.2f ", (double)(offs));
 
264
                                }
 
265
                                else {
 
266
                                        sprintf(str, "Marker offset %.2f ", (double)(offs));
 
267
                                }
 
268
                        }
 
269
                        headerprint(str);
 
270
                        
 
271
                        force_draw(0);  // areas identical to this, 0 = no header
 
272
                }
 
273
                else PIL_sleep_ms(10);  // idle
 
274
                
 
275
                /* emptying queue and reading events */
 
276
                while ( qtest() ) {
 
277
                        event= extern_qread(&val);
 
278
                        
 
279
                        if (val) {
 
280
                                if (ELEM(event, ESCKEY, RIGHTMOUSE)) ret_val= 2;
 
281
                                else if (ELEM3(event, LEFTMOUSE, RETKEY, SPACEKEY)) ret_val= 1;
 
282
                        }
 
283
                }
 
284
        }
 
285
        
 
286
        /* restore? */
 
287
        if (ret_val==2) {
 
288
                for (a=0, marker= markers->first; marker; marker= marker->next) {
 
289
                        if (marker->flag & SELECT) {
 
290
                                marker->frame= oldframe[a];
 
291
                                a++;
 
292
                        }
 
293
                }
 
294
        }
 
295
        else {
 
296
                BIF_undo_push("Move Markers");
 
297
        }
 
298
        MEM_freeN(oldframe);
 
299
        allqueue(REDRAWMARKER, 0);
 
300
}
 
301
 
 
302
/* select/deselect all TimeMarkers
 
303
 *      test - based on current selections?
 
304
 *      sel - selection status to set all markers to if blanket apply status
 
305
 */
 
306
void deselect_markers(short test, short sel)
 
307
{
 
308
        TimeMarker *marker;
 
309
                
 
310
        /* check if need to find out whether to how to select markers */
 
311
        if (test) {
 
312
                /* dependant on existing selection */
 
313
                /* determine if select all or deselect all */
 
314
                sel = 1;
 
315
                for (marker= G.scene->markers.first; marker; marker= marker->next) {
 
316
                        if (marker->flag & SELECT) {
 
317
                                sel = 0;
 
318
                                break;
 
319
                        }
 
320
                }
 
321
                
 
322
                /* do selection */
 
323
                for (marker= G.scene->markers.first; marker; marker= marker->next) {
 
324
                        if (sel == 2) {
 
325
                                marker->flag ^= SELECT;
 
326
                        }
 
327
                        else if (sel == 1) {
 
328
                                if ((marker->flag & SELECT)==0) 
 
329
                                        marker->flag |= SELECT;
 
330
                        }
 
331
                        else {
 
332
                                if (marker->flag & SELECT)
 
333
                                        marker->flag &= ~SELECT;
 
334
                        }
 
335
                }
 
336
        }
 
337
        else {
 
338
                /* not dependant on existing selection */
 
339
                for (marker= G.scene->markers.first; marker; marker= marker->next) {
 
340
                                if (sel==2) {
 
341
                                        marker->flag ^= SELECT;
 
342
                                }
 
343
                                else if (sel==1) {
 
344
                                        if ((marker->flag & SELECT)==0)
 
345
                                                marker->flag |= SELECT;
 
346
                                }
 
347
                                else {
 
348
                                        if (marker->flag & SELECT)
 
349
                                                marker->flag &= ~SELECT;
 
350
                                }
 
351
                }
 
352
        }
 
353
}
 
354
 
 
355
static void borderselect_markers_func(float xmin, float xmax, int selectmode)
 
356
{
 
357
        TimeMarker *marker;
 
358
                
 
359
        for(marker= G.scene->markers.first; marker; marker= marker->next) {
 
360
                if ((marker->frame > xmin) && (marker->frame <= xmax)) {
 
361
                        switch (selectmode) {
 
362
                                case SELECT_ADD:
 
363
                                        if ((marker->flag & SELECT) == 0) 
 
364
                                                marker->flag |= SELECT;
 
365
                                        break;
 
366
                                case SELECT_SUBTRACT:
 
367
                                        if (marker->flag & SELECT) 
 
368
                                                marker->flag &= ~SELECT;
 
369
                                        break;
 
370
                        }
 
371
                }
 
372
        }
 
373
}
 
374
 
 
375
/* border-select markers */
 
376
void borderselect_markers(void) 
 
377
{
 
378
        rcti rect;
 
379
        rctf rectf;
 
380
        int val, selectmode;            
 
381
        short   mval[2];
 
382
 
 
383
        if ( (val = get_border(&rect, 3)) ){
 
384
                if (val == LEFTMOUSE)
 
385
                        selectmode = SELECT_ADD;
 
386
                else
 
387
                        selectmode = SELECT_SUBTRACT;
 
388
 
 
389
                mval[0]= rect.xmin;
 
390
                mval[1]= rect.ymin+2;
 
391
                areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
 
392
                mval[0]= rect.xmax;
 
393
                mval[1]= rect.ymax-2;
 
394
                areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
 
395
                        
 
396
                /* do markers */
 
397
                borderselect_markers_func(rectf.xmin, rectf.xmax, selectmode);
 
398
                
 
399
                BIF_undo_push("Border Select Markers");
 
400
                allqueue(REDRAWMARKER, 0);
 
401
        }
 
402
}
 
403
 
 
404
void nextprev_marker(short dir)
 
405
{
 
406
        TimeMarker *marker, *cur=NULL, *first, *last;
 
407
        int mindist= MAXFRAME, dist;
 
408
                
 
409
        first= last= G.scene->markers.first; 
 
410
        for(marker= G.scene->markers.first; marker; marker= marker->next) {
 
411
                /* find closest to current frame first */
 
412
                dist= (marker->frame/G.scene->r.framelen) - CFRA;
 
413
                if(dir==1 && dist>0 && dist<mindist) {
 
414
                        mindist= dist;
 
415
                        cur= marker;
 
416
                }
 
417
                else if(dir==-1 && dist<0 && -dist<mindist) {
 
418
                        mindist= -dist;
 
419
                        cur= marker;
 
420
                }
 
421
                /* find first/last */
 
422
                if(marker->frame > last->frame) last= marker;
 
423
                if(marker->frame < first->frame) first= marker;
 
424
        }
 
425
        
 
426
        if(cur==NULL) {
 
427
                if(dir==1) cur= first;
 
428
                else cur= last;
 
429
        }
 
430
        if(cur) {
 
431
                CFRA= cur->frame/G.scene->r.framelen;
 
432
                update_for_newframe();
 
433
                allqueue(REDRAWALL, 0);
 
434
        }
 
435
}
 
436
 
 
437
void get_minmax_markers(short sel, float *first, float *last)
 
438
{
 
439
        TimeMarker *marker;
 
440
        ListBase *markers;
 
441
        float min, max;
 
442
        int selcount = 0;
 
443
        
 
444
        markers= &(G.scene->markers);
 
445
        
 
446
        if (sel)
 
447
                for (marker= markers->first; marker; marker= marker->next) {
 
448
                        if (marker->flag & SELECT)
 
449
                                selcount++;
 
450
                }
 
451
        else {
 
452
                selcount= BLI_countlist(markers);
 
453
        }
 
454
        
 
455
        if (markers->first && markers->last) {
 
456
                min= ((TimeMarker *)markers->first)->frame;
 
457
                max= ((TimeMarker *)markers->last)->frame;
 
458
        }
 
459
        else {
 
460
                *first = 0.0f;
 
461
                *last = 0.0f;
 
462
                return;
 
463
        }
 
464
        
 
465
        if (selcount > 1) {
 
466
                for (marker= markers->first; marker; marker= marker->next) {
 
467
                        if (sel) {
 
468
                                if (marker->flag & SELECT) {
 
469
                                        if (marker->frame < min)
 
470
                                                min= marker->frame;
 
471
                                        else if (marker->frame > max)
 
472
                                                max= marker->frame;
 
473
                                }
 
474
                        }
 
475
                        else {
 
476
                                if (marker->frame < min)
 
477
                                        min= marker->frame;
 
478
                                else if (marker->frame > max)
 
479
                                        max= marker->frame;
 
480
                        }       
 
481
                }
 
482
        }
 
483
        
 
484
        *first= min;
 
485
        *last= max;
 
486
}
 
487
 
 
488
TimeMarker *find_nearest_marker(ListBase *markers, int clip_y)
 
489
{
 
490
        TimeMarker *marker;
 
491
        float xmin, xmax;
 
492
        rctf    rectf;
 
493
        short mval[2];
 
494
        
 
495
        getmouseco_areawin (mval);
 
496
        
 
497
        /* first clip selection in Y */
 
498
        if ((clip_y) && (mval[1] > 30))
 
499
                return NULL;
 
500
        
 
501
        mval[0]-=7;
 
502
        areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
 
503
        mval[0]+=14;
 
504
        areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
 
505
        
 
506
        xmin= rectf.xmin;
 
507
        xmax= rectf.xmax;
 
508
        
 
509
        for (marker= markers->first; marker; marker= marker->next) {
 
510
                if ((marker->frame > xmin) && (marker->frame <= xmax)) {
 
511
                        return marker;
 
512
                }
 
513
        }
 
514
        
 
515
        return NULL;
 
516
}
 
517
 
 
518
/* Adds a marker to list of cfra elems */
 
519
void add_marker_to_cfra_elem(ListBase *lb, TimeMarker *marker, short only_sel)
 
520
{
 
521
        CfraElem *ce, *cen;
 
522
        
 
523
        /* should this one only be considered if it is selected? */
 
524
        if ((only_sel) && ((marker->flag & SELECT)==0))
 
525
                return;
 
526
        
 
527
        /* try to find a previous cfra elem */
 
528
        ce= lb->first;
 
529
        while(ce) {
 
530
                
 
531
                if( ce->cfra==marker->frame ) {
 
532
                        /* do because of double keys */
 
533
                        if(marker->flag & SELECT) ce->sel= marker->flag;
 
534
                        return;
 
535
                }
 
536
                else if(ce->cfra > marker->frame) break;
 
537
                
 
538
                ce= ce->next;
 
539
        }       
 
540
        
 
541
        cen= MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem"); 
 
542
        if(ce) BLI_insertlinkbefore(lb, ce, cen);
 
543
        else BLI_addtail(lb, cen);
 
544
 
 
545
        cen->cfra= marker->frame;
 
546
        cen->sel= marker->flag;
 
547
}
 
548
 
 
549
/* This function makes a list of all the markers. The only_sel
 
550
 * argument is used to specify whether only the selected markers
 
551
 * are added.
 
552
 */
 
553
void make_marker_cfra_list(ListBase *lb, short only_sel)
 
554
{
 
555
        TimeMarker *marker;
 
556
        
 
557
        for (marker= G.scene->markers.first; marker; marker= marker->next) {
 
558
                add_marker_to_cfra_elem(lb, marker, only_sel);
 
559
        }
 
560
}
 
561
 
 
562
int find_nearest_marker_time(float dx)
 
563
{
 
564
        TimeMarker *marker, *nearest= NULL;
 
565
        float dist, min_dist= 1000000;
 
566
        
 
567
        for(marker= G.scene->markers.first; marker; marker= marker->next) {
 
568
                dist = ABS((float)marker->frame - dx);
 
569
                if(dist < min_dist){
 
570
                        min_dist= dist;
 
571
                        nearest= marker;
 
572
                }
 
573
        }
 
574
        
 
575
        if(nearest) return nearest->frame;
 
576
        else return (int)floor(dx);
 
577
}
 
578
 
 
579
/* *********** End Markers - Markers API *************** */
 
580
/* select/deselect TimeMarker at current frame */
 
581
static void select_timeline_marker_frame(int frame, unsigned char shift)
 
582
{
 
583
        TimeMarker *marker;
 
584
        int select=0;
 
585
        
 
586
        for(marker= G.scene->markers.first; marker; marker= marker->next) {
 
587
                /* if Shift is not set, then deselect Markers */
 
588
                if(!shift) marker->flag &= ~SELECT;
 
589
                /* this way a not-shift select will allways give 1 selected marker */
 
590
                if((marker->frame == frame) && (!select)) {
 
591
                        if(marker->flag & SELECT) 
 
592
                                marker->flag &= ~SELECT;
 
593
                        else
 
594
                                marker->flag |= SELECT;
 
595
                        select = 1;
 
596
                }
 
597
        }
 
598
}
 
599
 
 
600
/* *********** end Markers - TimeLine *************** */
 
601
 
 
602
/* set the animation preview range of scene */
 
603
void anim_previewrange_set()
 
604
{
 
605
        rcti rect;
 
606
        rctf rectf;
 
607
        short val, mval[2];
 
608
        
 
609
        /* set range by drawing border-select rectangle */
 
610
        if ( (val = get_border(&rect, 5)) ) {   
 
611
                /* get frame numbers */
 
612
                mval[0]= rect.xmin;
 
613
                mval[1]= rect.ymin+2;
 
614
                areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
 
615
                mval[0]= rect.xmax;
 
616
                mval[1]= rect.ymax-2;
 
617
                areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
 
618
                        
 
619
                /* set preview-range */
 
620
                if (rectf.xmin < 1) rectf.xmin = 1.0f;
 
621
                if (rectf.xmax < 1) rectf.xmax = 1.0f;
 
622
                G.scene->r.psfra= rectf.xmin;
 
623
                G.scene->r.pefra= rectf.xmax;
 
624
                
 
625
                BIF_undo_push("Set anim-preview range");
 
626
                allqueue(REDRAWTIME, 0);
 
627
                allqueue(REDRAWACTION, 0);
 
628
                allqueue(REDRAWNLA, 0);
 
629
                allqueue(REDRAWIPO, 0);
 
630
                allqueue(REDRAWBUTSALL, 0);
 
631
        }
 
632
}
 
633
 
 
634
/* clear the animation preview range for scene */
 
635
void anim_previewrange_clear()
 
636
{
 
637
        G.scene->r.psfra = 0;
 
638
        G.scene->r.pefra = 0;
 
639
        
 
640
        BIF_undo_push("Clear anim-preview range");
 
641
        allqueue(REDRAWTIME, 0);
 
642
        allqueue(REDRAWACTION, 0);
 
643
        allqueue(REDRAWNLA, 0);
 
644
        allqueue(REDRAWBUTSALL, 0);
 
645
}
 
646
 
 
647
/* ************ end Animation Preview Range ********** */
 
648
 
 
649
 
 
650
static int float_to_frame(float frame) 
 
651
{
 
652
        int to= (int) floor(0.5 + frame/G.scene->r.framelen );
 
653
        
 
654
        return to;      
 
655
}
 
656
 
 
657
static float find_closest_cfra_elem(ListBase elems, int dir, float closest)
 
658
{
 
659
        CfraElem *ce;
 
660
        
 
661
        for(ce= elems.first; ce; ce= ce->next) {
 
662
                if (dir==-1) {
 
663
                        if( float_to_frame(ce->cfra)<CFRA) {
 
664
                                if ((ce->cfra > closest) || (closest == CFRA)) {
 
665
                                        closest= ce->cfra;
 
666
                                }
 
667
                        }
 
668
                } 
 
669
                else {
 
670
                        if(float_to_frame(ce->cfra)>CFRA) {
 
671
                                if ((ce->cfra < closest) || (closest == CFRA)) {
 
672
                                        closest= ce->cfra;
 
673
                                }
 
674
                        }
 
675
                }
 
676
        }
 
677
        return closest;
 
678
}
 
679
 
 
680
void nextprev_timeline_key(short dir)
 
681
{
 
682
        /*mostly copied from drawobject.c, draw_object() AND editipo.c, movekey_obipo() */
 
683
        Object *ob;
 
684
        bActionChannel *achan;
 
685
        bAction *act;
 
686
        ListBase elems;
 
687
        float closest= CFRA;
 
688
        int a;
 
689
        
 
690
        if (OBACT) {
 
691
                ob = OBACT;
 
692
                
 
693
                if(ob) {
 
694
                        if(ob!=G.obedit) {
 
695
                                if(ob->ipo) {
 
696
                                        /* convert the ipo to a list of 'current frame elements' */
 
697
                                        
 
698
                                        elems.first= elems.last= NULL;
 
699
                                        make_cfra_list(ob->ipo, &elems);
 
700
                                        
 
701
                                        closest= find_closest_cfra_elem(elems, dir, closest);
 
702
                                        
 
703
                                        BLI_freelistN(&elems);
 
704
                                }
 
705
                                
 
706
                                if(ob->action) {
 
707
                                        act = ob->action;
 
708
                                        /* go through each channel in the action */
 
709
                                        for (achan=act->chanbase.first; achan; achan=achan->next){
 
710
                                                /* convert the ipo to a list of 'current frame elements' */
 
711
                                                
 
712
                                                if(achan->ipo) {
 
713
                                                        elems.first= elems.last= NULL;
 
714
                                                        make_cfra_list(achan->ipo, &elems);
 
715
                                                        
 
716
                                                        closest= find_closest_cfra_elem(elems, dir, closest);
 
717
                                                        
 
718
                                                        BLI_freelistN(&elems);
 
719
                                                }
 
720
                                        }
 
721
                                }
 
722
                                
 
723
                                for(a=0; a<ob->totcol; a++) {
 
724
                                        Material *ma= give_current_material(ob, a+1);
 
725
                                        if(ma && ma->ipo) {
 
726
                                                elems.first= elems.last= NULL;
 
727
                                                make_cfra_list(ma->ipo, &elems);
 
728
                                                
 
729
                                                closest= find_closest_cfra_elem(elems, dir, closest);
 
730
                                                
 
731
                                                BLI_freelistN(&elems);
 
732
                                        }
 
733
                                }
 
734
                        }
 
735
                }
 
736
                
 
737
                a= float_to_frame(closest);
 
738
                
 
739
                if (a!=CFRA) {
 
740
                        CFRA= a;
 
741
                        update_for_newframe();
 
742
                }       
 
743
                
 
744
                BIF_undo_push("Next/Prev Key");
 
745
                allqueue(REDRAWALL, 0);
 
746
        }
 
747
}
 
748
 
 
749
/* return the current marker for this frame,
 
750
we can have more then 1 marker per frame, this just returns the first :/ */
 
751
TimeMarker *get_frame_marker(int frame)
 
752
{
 
753
        TimeMarker *marker, *best_marker = NULL;
 
754
        int best_frame = -MAXFRAME*2; 
 
755
        for (marker= G.scene->markers.first; marker; marker= marker->next) {
 
756
                if (marker->frame==frame) {
 
757
                        return marker;
 
758
                }
 
759
                
 
760
                if ( marker->frame > best_frame && marker->frame < frame) {
 
761
                        best_marker = marker;
 
762
                        best_frame = marker->frame;
 
763
                }
 
764
        }
 
765
        
 
766
        return best_marker;
 
767
}
 
768
 
 
769
 
 
770
void timeline_frame_to_center(void)
 
771
{
 
772
        float dtime;
 
773
        
 
774
        dtime= CFRA*(G.scene->r.framelen) - (G.v2d->cur.xmin + G.v2d->cur.xmax)/2.0; 
 
775
        G.v2d->cur.xmin += dtime;
 
776
        G.v2d->cur.xmax += dtime;
 
777
        scrarea_queue_winredraw(curarea);
 
778
}
 
779
 
 
780
/* copy of this is actually in editscreen.c, but event based */
 
781
static void timeline_force_draw(short val)
 
782
{
 
783
        ScrArea *sa, *tempsa, *samin= NULL;
 
784
        int dodraw;
 
785
        
 
786
        if(val & TIME_LEFTMOST_3D_WIN) {
 
787
                ScrArea *sa= G.curscreen->areabase.first;
 
788
                int min= 10000;
 
789
                for(; sa; sa= sa->next) {
 
790
                        if(sa->spacetype==SPACE_VIEW3D) {
 
791
                                if(sa->winrct.xmin - sa->winrct.ymin < min) {
 
792
                                        samin= sa;
 
793
                                        min= sa->winrct.xmin - sa->winrct.ymin;
 
794
                                }
 
795
                        }
 
796
                }
 
797
        }
 
798
        
 
799
        tempsa= curarea;
 
800
        sa= G.curscreen->areabase.first;
 
801
        while(sa) {
 
802
                dodraw= 0;
 
803
                if(sa->spacetype==SPACE_VIEW3D) {
 
804
                        if(sa==samin || (val & TIME_ALL_3D_WIN)) dodraw= 1;
 
805
                }
 
806
                else if(ELEM5(sa->spacetype, SPACE_NLA, SPACE_IPO, SPACE_SEQ, SPACE_ACTION, SPACE_SOUND)) {
 
807
                        if(val & TIME_ALL_ANIM_WIN) dodraw= 1;
 
808
                }
 
809
                else if(sa->spacetype==SPACE_BUTS) {
 
810
                        if(val & TIME_ALL_BUTS_WIN) dodraw= 2;
 
811
                }
 
812
                else if(sa->spacetype==SPACE_IMAGE) {
 
813
                        if (val & TIME_ALL_IMAGE_WIN) dodraw = 1;
 
814
                }
 
815
                else if(sa->spacetype==SPACE_SEQ) {
 
816
                        if (val & TIME_SEQ) dodraw = 1;
 
817
                }
 
818
                else if(sa->spacetype==SPACE_TIME) dodraw= 2;
 
819
                
 
820
                if(dodraw) {
 
821
                        areawinset(sa->win);
 
822
                        scrarea_do_windraw(sa);
 
823
                        if(dodraw==2) scrarea_do_headdraw(sa);
 
824
                }
 
825
                sa= sa->next;
 
826
        }
 
827
        areawinset(tempsa->win);
 
828
        
 
829
        screen_swapbuffers();
 
830
 
 
831
}
 
832
 
 
833
/* ***************************** */
 
834
 
 
835
/* Right. Now for some implementation: */
 
836
void winqreadtimespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
 
837
{
 
838
        SpaceTime *stime= spacedata;
 
839
        unsigned short event= evt->event;
 
840
        short val= evt->val;
 
841
        float dx, dy;
 
842
        int doredraw= 0, cfra, first = 0;
 
843
        short mval[2], nr;
 
844
        short mousebut = L_MOUSE;
 
845
        
 
846
        if(sa->win==0) return;
 
847
 
 
848
        if(val) {
 
849
                
 
850
                if( uiDoBlocks(&sa->uiblocks, event, 1)!=UI_NOTHING ) event= 0;
 
851
 
 
852
                /* swap mouse buttons based on user preference */
 
853
                if (U.flag & USER_LMOUSESELECT) {
 
854
                        if (event == LEFTMOUSE) {
 
855
                                event = RIGHTMOUSE;
 
856
                                mousebut = L_MOUSE;
 
857
                        } else if (event == RIGHTMOUSE) {
 
858
                                event = LEFTMOUSE;
 
859
                                mousebut = R_MOUSE;
 
860
                        }
 
861
                }
 
862
 
 
863
                switch(event) {
 
864
                case LEFTMOUSE:
 
865
                        stime->flag |= TIME_CFRA_NUM;
 
866
                        do {
 
867
                                getmouseco_areawin(mval);
 
868
                                areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
 
869
                                
 
870
                                cfra = (int)(dx+0.5f);
 
871
                                if(cfra< MINFRAME) cfra= MINFRAME;
 
872
                                
 
873
                                if( cfra!=CFRA || first )
 
874
                                {
 
875
                                        first= 0;
 
876
                                        CFRA= cfra;
 
877
                                        update_for_newframe_nodraw(0);  // 1= nosound
 
878
                                        timeline_force_draw(stime->redraws);
 
879
                                }
 
880
                                else PIL_sleep_ms(30);
 
881
                        
 
882
                        } while(get_mbut() & mousebut);
 
883
                        
 
884
                        stime->flag &= ~TIME_CFRA_NUM;
 
885
                        allqueue(REDRAWALL, 0);
 
886
                        break;
 
887
                        
 
888
                case RIGHTMOUSE: /* select/deselect marker */
 
889
                        getmouseco_areawin(mval);
 
890
                        areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
 
891
                        
 
892
                        cfra= find_nearest_marker_time(dx);
 
893
                        
 
894
                        if (G.qual && LR_SHIFTKEY)
 
895
                                select_timeline_marker_frame(cfra, 1);
 
896
                        else
 
897
                                select_timeline_marker_frame(cfra, 0);
 
898
                        
 
899
                        force_draw(0);
 
900
                        std_rmouse_transform(transform_markers);
 
901
 
 
902
                        break;
 
903
                case MIDDLEMOUSE:
 
904
                case WHEELUPMOUSE:
 
905
                case WHEELDOWNMOUSE:
 
906
                        view2dmove(event);      /* in drawipo.c */
 
907
                        break;
 
908
                case PADPLUSKEY:
 
909
                        dx= (float)(0.1154*(G.v2d->cur.xmax-G.v2d->cur.xmin));
 
910
                        G.v2d->cur.xmin+= dx;
 
911
                        G.v2d->cur.xmax-= dx;
 
912
                        test_view2d(G.v2d, sa->winx, sa->winy);
 
913
                        view2d_do_locks(curarea, V2D_LOCK_COPY);
 
914
                        doredraw= 1;
 
915
                        break;
 
916
                case PADMINUS:
 
917
                        dx= (float)(0.15*(G.v2d->cur.xmax-G.v2d->cur.xmin));
 
918
                        G.v2d->cur.xmin-= dx;
 
919
                        G.v2d->cur.xmax+= dx;
 
920
                        test_view2d(G.v2d, sa->winx, sa->winy);
 
921
                        view2d_do_locks(curarea, V2D_LOCK_COPY);
 
922
                        doredraw= 1;
 
923
                        break;
 
924
                case HOMEKEY:
 
925
                        first= G.scene->r.sfra;
 
926
                        if(first >= G.scene->r.efra) first= G.scene->r.efra;
 
927
                        G.v2d->cur.xmin=G.v2d->tot.xmin= (float)first-2;
 
928
                        G.v2d->cur.xmax=G.v2d->tot.xmax= (float)G.scene->r.efra+2;
 
929
                        doredraw= 1;
 
930
                        break;
 
931
                        
 
932
                case PAGEUPKEY: /* next keyframe */
 
933
                        if(G.qual==LR_CTRLKEY)
 
934
                                nextprev_timeline_key(1);
 
935
                        else
 
936
                                nextprev_marker(1);
 
937
                        break;
 
938
                case PAGEDOWNKEY: /* prev keyframe */
 
939
                        if(G.qual==LR_CTRLKEY)
 
940
                                nextprev_timeline_key(-1);
 
941
                        else
 
942
                                nextprev_marker(-1);
 
943
                        break;
 
944
                        
 
945
                case AKEY:
 
946
                        /* deselect all TimeMarkers */
 
947
                        deselect_markers(1, 0);
 
948
                        allqueue(REDRAWMARKER, 0);
 
949
                        break;
 
950
                case BKEY:
 
951
                        /* borderselect markers */
 
952
                        borderselect_markers();
 
953
                        break;
 
954
                case DKEY:
 
955
                        if(G.qual==LR_SHIFTKEY)
 
956
                                duplicate_marker();
 
957
                        break;
 
958
                case CKEY:
 
959
                        timeline_frame_to_center();
 
960
                        break;
 
961
                case GKEY: /* move marker */
 
962
                        transform_markers('g', 0);
 
963
                        break;
 
964
                case EKEY: /* set end frame */
 
965
                        if (G.scene->r.psfra) {
 
966
                                if (CFRA < G.scene->r.psfra)
 
967
                                        G.scene->r.psfra= CFRA;
 
968
                                G.scene->r.pefra= CFRA;
 
969
                        }                               
 
970
                        else
 
971
                                G.scene->r.efra = CFRA;
 
972
                        allqueue(REDRAWALL, 1);
 
973
                        break;
 
974
                case MKEY: /* add, rename marker */
 
975
                        if (G.qual & LR_CTRLKEY)
 
976
                                rename_marker();
 
977
                        else
 
978
                                add_marker(CFRA);
 
979
                        allqueue(REDRAWMARKER, 0);
 
980
                        break;
 
981
                case PKEY:      /* preview-range stuff */
 
982
                        if (G.qual & LR_CTRLKEY) /* set preview range */
 
983
                                anim_previewrange_set();
 
984
                        else if (G.qual & LR_ALTKEY) /* clear preview range */
 
985
                                anim_previewrange_clear();
 
986
                        break;
 
987
                case SKEY: /* set start frame */
 
988
                        if (G.scene->r.psfra) {
 
989
                                if (G.scene->r.pefra < CFRA)
 
990
                                        G.scene->r.pefra= CFRA;
 
991
                                G.scene->r.psfra= CFRA;
 
992
                        }                               
 
993
                        else
 
994
                                G.scene->r.sfra = CFRA;
 
995
                        allqueue(REDRAWALL, 1);
 
996
                        break;
 
997
                case TKEY: /* popup menu */
 
998
                        nr= pupmenu("Time value%t|Frames %x1|Seconds%x2");
 
999
                        if (nr>0) {
 
1000
                                if(nr==1) stime->flag |= TIME_DRAWFRAMES;
 
1001
                                else stime->flag &= ~TIME_DRAWFRAMES;
 
1002
                                doredraw= 1;
 
1003
                        }
 
1004
                        break;
 
1005
                case DELKEY:
 
1006
                case XKEY:
 
1007
                        if( okee("Erase selected")==0 ) break;
 
1008
 
 
1009
                        remove_marker();
 
1010
                        allqueue(REDRAWMARKER, 0);
 
1011
                        break;
 
1012
                }
 
1013
        }
 
1014
 
 
1015
        if(doredraw)
 
1016
                scrarea_queue_winredraw(sa);
 
1017
}
 
1018
 
 
1019