4
* ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
20
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21
* All rights reserved.
23
* The Original Code is: all of this file.
25
* Contributor(s): none yet.
27
* ***** END GPL LICENSE BLOCK *****
40
#include "MEM_guardedalloc.h"
42
#include "BLI_blenlib.h"
43
#include "BLI_arithb.h"
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"
55
#include "BKE_utildefines.h"
56
#include "BKE_global.h"
58
#include "BKE_material.h"
59
#include "BKE_library.h"
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"
68
#include "BSE_drawipo.h"
70
#include "BSE_headerbuttons.h"
73
#include "BDR_editobject.h"
82
void winqreadtimespace(ScrArea *, void *, BWinEvent *);
84
/* ************* Marker API **************** */
86
/* add TimeMarker at curent frame */
87
void add_marker(int frame)
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;
95
for(marker= G.scene->markers.first; marker; marker= marker->next)
96
marker->flag &= ~SELECT;
98
marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
100
marker->frame= frame;
101
BLI_addtail(&(G.scene->markers), marker);
103
BIF_undo_push("Add Marker");
108
/* remove selected TimeMarkers */
109
void remove_marker(void)
111
TimeMarker *marker, *nmarker;
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);
123
BIF_undo_push("Remove Marker");
126
/* rename first selected TimeMarker */
127
void rename_marker(void)
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));
141
// BIF_undo_push("Rename Marker");
144
/* duplicate selected TimeMarkers */
145
void duplicate_marker(void)
147
TimeMarker *marker, *newmarker;
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);
165
transform_markers('g', 0);
168
void transform_markers(int mode, int smode) // mode and smode unused here, for callback
170
SpaceLink *slink= curarea->spacedata.first;
171
SpaceTime *stime= curarea->spacedata.first;
172
SpaceAction *saction = curarea->spacedata.first;
174
TimeMarker *marker, *selmarker=NULL;
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];
181
/* hack for pose-markers in action editor */
182
if ((slink->spacetype == SPACE_ACTION) && (saction->flag & SACTION_POSEMARKERS_MOVE)) {
184
markers= &saction->action->markers;
189
markers= &G.scene->markers;
191
for (marker= markers->first; marker; marker= marker->next) {
192
if (marker->flag & SELECT) totmark++;
194
if (totmark==0) return;
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
205
dx= G.v2d->mask.xmax-G.v2d->mask.xmin;
206
dx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/dx;
208
getmouseco_areawin(pmval);
211
while (ret_val == 0) {
212
getmouseco_areawin(mval);
214
if (mval[0] != mvalo[0] || firsttime) {
218
fac= (((float)(mval[0] - pmval[0]))*dx);
220
if (ELEM(slink->spacetype, SPACE_TIME, SPACE_SOUND))
221
apply_keyb_grid(&fac, 0.0, FPS, 0.1*FPS, 0);
223
apply_keyb_grid(&fac, 0.0, 1.0, 0.1, U.flag & USER_AUTOGRABGRID);
226
for (a=0, marker= markers->first; marker; marker= marker->next) {
227
if (marker->flag & SELECT) {
228
marker->frame= oldframe[a] + offs;
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);
239
sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
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));
245
sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
248
sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
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);
257
sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
259
else if (slink->spacetype == SPACE_ACTION) {
260
if (saction->flag & SACTION_DRAWTIME)
261
sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
263
sprintf(str, "Marker offset %.2f ", (double)(offs));
266
sprintf(str, "Marker offset %.2f ", (double)(offs));
271
force_draw(0); // areas identical to this, 0 = no header
273
else PIL_sleep_ms(10); // idle
275
/* emptying queue and reading events */
277
event= extern_qread(&val);
280
if (ELEM(event, ESCKEY, RIGHTMOUSE)) ret_val= 2;
281
else if (ELEM3(event, LEFTMOUSE, RETKEY, SPACEKEY)) ret_val= 1;
288
for (a=0, marker= markers->first; marker; marker= marker->next) {
289
if (marker->flag & SELECT) {
290
marker->frame= oldframe[a];
296
BIF_undo_push("Move Markers");
299
allqueue(REDRAWMARKER, 0);
302
/* select/deselect all TimeMarkers
303
* test - based on current selections?
304
* sel - selection status to set all markers to if blanket apply status
306
void deselect_markers(short test, short sel)
310
/* check if need to find out whether to how to select markers */
312
/* dependant on existing selection */
313
/* determine if select all or deselect all */
315
for (marker= G.scene->markers.first; marker; marker= marker->next) {
316
if (marker->flag & SELECT) {
323
for (marker= G.scene->markers.first; marker; marker= marker->next) {
325
marker->flag ^= SELECT;
328
if ((marker->flag & SELECT)==0)
329
marker->flag |= SELECT;
332
if (marker->flag & SELECT)
333
marker->flag &= ~SELECT;
338
/* not dependant on existing selection */
339
for (marker= G.scene->markers.first; marker; marker= marker->next) {
341
marker->flag ^= SELECT;
344
if ((marker->flag & SELECT)==0)
345
marker->flag |= SELECT;
348
if (marker->flag & SELECT)
349
marker->flag &= ~SELECT;
355
static void borderselect_markers_func(float xmin, float xmax, int selectmode)
359
for(marker= G.scene->markers.first; marker; marker= marker->next) {
360
if ((marker->frame > xmin) && (marker->frame <= xmax)) {
361
switch (selectmode) {
363
if ((marker->flag & SELECT) == 0)
364
marker->flag |= SELECT;
366
case SELECT_SUBTRACT:
367
if (marker->flag & SELECT)
368
marker->flag &= ~SELECT;
375
/* border-select markers */
376
void borderselect_markers(void)
383
if ( (val = get_border(&rect, 3)) ){
384
if (val == LEFTMOUSE)
385
selectmode = SELECT_ADD;
387
selectmode = SELECT_SUBTRACT;
390
mval[1]= rect.ymin+2;
391
areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
393
mval[1]= rect.ymax-2;
394
areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
397
borderselect_markers_func(rectf.xmin, rectf.xmax, selectmode);
399
BIF_undo_push("Border Select Markers");
400
allqueue(REDRAWMARKER, 0);
404
void nextprev_marker(short dir)
406
TimeMarker *marker, *cur=NULL, *first, *last;
407
int mindist= MAXFRAME, dist;
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) {
417
else if(dir==-1 && dist<0 && -dist<mindist) {
421
/* find first/last */
422
if(marker->frame > last->frame) last= marker;
423
if(marker->frame < first->frame) first= marker;
427
if(dir==1) cur= first;
431
CFRA= cur->frame/G.scene->r.framelen;
432
update_for_newframe();
433
allqueue(REDRAWALL, 0);
437
void get_minmax_markers(short sel, float *first, float *last)
444
markers= &(G.scene->markers);
447
for (marker= markers->first; marker; marker= marker->next) {
448
if (marker->flag & SELECT)
452
selcount= BLI_countlist(markers);
455
if (markers->first && markers->last) {
456
min= ((TimeMarker *)markers->first)->frame;
457
max= ((TimeMarker *)markers->last)->frame;
466
for (marker= markers->first; marker; marker= marker->next) {
468
if (marker->flag & SELECT) {
469
if (marker->frame < min)
471
else if (marker->frame > max)
476
if (marker->frame < min)
478
else if (marker->frame > max)
488
TimeMarker *find_nearest_marker(ListBase *markers, int clip_y)
495
getmouseco_areawin (mval);
497
/* first clip selection in Y */
498
if ((clip_y) && (mval[1] > 30))
502
areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
504
areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
509
for (marker= markers->first; marker; marker= marker->next) {
510
if ((marker->frame > xmin) && (marker->frame <= xmax)) {
518
/* Adds a marker to list of cfra elems */
519
void add_marker_to_cfra_elem(ListBase *lb, TimeMarker *marker, short only_sel)
523
/* should this one only be considered if it is selected? */
524
if ((only_sel) && ((marker->flag & SELECT)==0))
527
/* try to find a previous cfra elem */
531
if( ce->cfra==marker->frame ) {
532
/* do because of double keys */
533
if(marker->flag & SELECT) ce->sel= marker->flag;
536
else if(ce->cfra > marker->frame) break;
541
cen= MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem");
542
if(ce) BLI_insertlinkbefore(lb, ce, cen);
543
else BLI_addtail(lb, cen);
545
cen->cfra= marker->frame;
546
cen->sel= marker->flag;
549
/* This function makes a list of all the markers. The only_sel
550
* argument is used to specify whether only the selected markers
553
void make_marker_cfra_list(ListBase *lb, short only_sel)
557
for (marker= G.scene->markers.first; marker; marker= marker->next) {
558
add_marker_to_cfra_elem(lb, marker, only_sel);
562
int find_nearest_marker_time(float dx)
564
TimeMarker *marker, *nearest= NULL;
565
float dist, min_dist= 1000000;
567
for(marker= G.scene->markers.first; marker; marker= marker->next) {
568
dist = ABS((float)marker->frame - dx);
575
if(nearest) return nearest->frame;
576
else return (int)floor(dx);
579
/* *********** End Markers - Markers API *************** */
580
/* select/deselect TimeMarker at current frame */
581
static void select_timeline_marker_frame(int frame, unsigned char shift)
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;
594
marker->flag |= SELECT;
600
/* *********** end Markers - TimeLine *************** */
602
/* set the animation preview range of scene */
603
void anim_previewrange_set()
609
/* set range by drawing border-select rectangle */
610
if ( (val = get_border(&rect, 5)) ) {
611
/* get frame numbers */
613
mval[1]= rect.ymin+2;
614
areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
616
mval[1]= rect.ymax-2;
617
areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
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;
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);
634
/* clear the animation preview range for scene */
635
void anim_previewrange_clear()
637
G.scene->r.psfra = 0;
638
G.scene->r.pefra = 0;
640
BIF_undo_push("Clear anim-preview range");
641
allqueue(REDRAWTIME, 0);
642
allqueue(REDRAWACTION, 0);
643
allqueue(REDRAWNLA, 0);
644
allqueue(REDRAWBUTSALL, 0);
647
/* ************ end Animation Preview Range ********** */
650
static int float_to_frame(float frame)
652
int to= (int) floor(0.5 + frame/G.scene->r.framelen );
657
static float find_closest_cfra_elem(ListBase elems, int dir, float closest)
661
for(ce= elems.first; ce; ce= ce->next) {
663
if( float_to_frame(ce->cfra)<CFRA) {
664
if ((ce->cfra > closest) || (closest == CFRA)) {
670
if(float_to_frame(ce->cfra)>CFRA) {
671
if ((ce->cfra < closest) || (closest == CFRA)) {
680
void nextprev_timeline_key(short dir)
682
/*mostly copied from drawobject.c, draw_object() AND editipo.c, movekey_obipo() */
684
bActionChannel *achan;
696
/* convert the ipo to a list of 'current frame elements' */
698
elems.first= elems.last= NULL;
699
make_cfra_list(ob->ipo, &elems);
701
closest= find_closest_cfra_elem(elems, dir, closest);
703
BLI_freelistN(&elems);
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' */
713
elems.first= elems.last= NULL;
714
make_cfra_list(achan->ipo, &elems);
716
closest= find_closest_cfra_elem(elems, dir, closest);
718
BLI_freelistN(&elems);
723
for(a=0; a<ob->totcol; a++) {
724
Material *ma= give_current_material(ob, a+1);
726
elems.first= elems.last= NULL;
727
make_cfra_list(ma->ipo, &elems);
729
closest= find_closest_cfra_elem(elems, dir, closest);
731
BLI_freelistN(&elems);
737
a= float_to_frame(closest);
741
update_for_newframe();
744
BIF_undo_push("Next/Prev Key");
745
allqueue(REDRAWALL, 0);
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)
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) {
760
if ( marker->frame > best_frame && marker->frame < frame) {
761
best_marker = marker;
762
best_frame = marker->frame;
770
void timeline_frame_to_center(void)
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);
780
/* copy of this is actually in editscreen.c, but event based */
781
static void timeline_force_draw(short val)
783
ScrArea *sa, *tempsa, *samin= NULL;
786
if(val & TIME_LEFTMOST_3D_WIN) {
787
ScrArea *sa= G.curscreen->areabase.first;
789
for(; sa; sa= sa->next) {
790
if(sa->spacetype==SPACE_VIEW3D) {
791
if(sa->winrct.xmin - sa->winrct.ymin < min) {
793
min= sa->winrct.xmin - sa->winrct.ymin;
800
sa= G.curscreen->areabase.first;
803
if(sa->spacetype==SPACE_VIEW3D) {
804
if(sa==samin || (val & TIME_ALL_3D_WIN)) dodraw= 1;
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;
809
else if(sa->spacetype==SPACE_BUTS) {
810
if(val & TIME_ALL_BUTS_WIN) dodraw= 2;
812
else if(sa->spacetype==SPACE_IMAGE) {
813
if (val & TIME_ALL_IMAGE_WIN) dodraw = 1;
815
else if(sa->spacetype==SPACE_SEQ) {
816
if (val & TIME_SEQ) dodraw = 1;
818
else if(sa->spacetype==SPACE_TIME) dodraw= 2;
822
scrarea_do_windraw(sa);
823
if(dodraw==2) scrarea_do_headdraw(sa);
827
areawinset(tempsa->win);
829
screen_swapbuffers();
833
/* ***************************** */
835
/* Right. Now for some implementation: */
836
void winqreadtimespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
838
SpaceTime *stime= spacedata;
839
unsigned short event= evt->event;
842
int doredraw= 0, cfra, first = 0;
844
short mousebut = L_MOUSE;
846
if(sa->win==0) return;
850
if( uiDoBlocks(&sa->uiblocks, event, 1)!=UI_NOTHING ) event= 0;
852
/* swap mouse buttons based on user preference */
853
if (U.flag & USER_LMOUSESELECT) {
854
if (event == LEFTMOUSE) {
857
} else if (event == RIGHTMOUSE) {
865
stime->flag |= TIME_CFRA_NUM;
867
getmouseco_areawin(mval);
868
areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
870
cfra = (int)(dx+0.5f);
871
if(cfra< MINFRAME) cfra= MINFRAME;
873
if( cfra!=CFRA || first )
877
update_for_newframe_nodraw(0); // 1= nosound
878
timeline_force_draw(stime->redraws);
880
else PIL_sleep_ms(30);
882
} while(get_mbut() & mousebut);
884
stime->flag &= ~TIME_CFRA_NUM;
885
allqueue(REDRAWALL, 0);
888
case RIGHTMOUSE: /* select/deselect marker */
889
getmouseco_areawin(mval);
890
areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
892
cfra= find_nearest_marker_time(dx);
894
if (G.qual && LR_SHIFTKEY)
895
select_timeline_marker_frame(cfra, 1);
897
select_timeline_marker_frame(cfra, 0);
900
std_rmouse_transform(transform_markers);
906
view2dmove(event); /* in drawipo.c */
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);
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);
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;
932
case PAGEUPKEY: /* next keyframe */
933
if(G.qual==LR_CTRLKEY)
934
nextprev_timeline_key(1);
938
case PAGEDOWNKEY: /* prev keyframe */
939
if(G.qual==LR_CTRLKEY)
940
nextprev_timeline_key(-1);
946
/* deselect all TimeMarkers */
947
deselect_markers(1, 0);
948
allqueue(REDRAWMARKER, 0);
951
/* borderselect markers */
952
borderselect_markers();
955
if(G.qual==LR_SHIFTKEY)
959
timeline_frame_to_center();
961
case GKEY: /* move marker */
962
transform_markers('g', 0);
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;
971
G.scene->r.efra = CFRA;
972
allqueue(REDRAWALL, 1);
974
case MKEY: /* add, rename marker */
975
if (G.qual & LR_CTRLKEY)
979
allqueue(REDRAWMARKER, 0);
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();
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;
994
G.scene->r.sfra = CFRA;
995
allqueue(REDRAWALL, 1);
997
case TKEY: /* popup menu */
998
nr= pupmenu("Time value%t|Frames %x1|Seconds%x2");
1000
if(nr==1) stime->flag |= TIME_DRAWFRAMES;
1001
else stime->flag &= ~TIME_DRAWFRAMES;
1007
if( okee("Erase selected")==0 ) break;
1010
allqueue(REDRAWMARKER, 0);
1016
scrarea_queue_winredraw(sa);