diff options
author | Joshua Leung <aligorith@gmail.com> | 2006-11-30 04:57:14 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2006-11-30 04:57:14 +0300 |
commit | d310f203da61eedf01d43f5c8690e8a58d5a584c (patch) | |
tree | 607b22c7e288f6e86a653a0c695d6654a8063d1f /source/blender/src/edittime.c | |
parent | 2572b9f72c8f10b01de949e59b481ac5a587aca4 (diff) |
Big Commit.
Now time-markers work in all time-related spaces (i.e. Ipo,
Action Editor, NLA editor, TimeLine, Sound). The hotkeys and
functionality set should be the same for each of these modes
(with a few exceptions still). I've had to change a few hotkeys
here and there, so hopefully they aren't too bad.
Marker Operations:
MKEY - Add Marker
SHIFT MKEY - Rename marker (was CTRL MKEY)
XKEY - Delete Marker
PAGE UP - Jump to next marker
PAGE DOWN - Jump to previous marker
CTRL A - Select all markers
SHIFT G - Transform markers (NLA, IPO, Action)
G - Transform markers (Sound, Timeline)
CTRL SHIFT D - Duplicate markers (NLA, IPO, Action)
SHIFT D - Duplicate markers (Sound, Timeline)
BKEY - select markers and other keyframes (if any)
I've also made a few little tool additions to NLA and Action editors:
* NLA editor - Snap To Frame.
Now with the option to offset strip so that it starts at the current frame.
Added menus for this.
* Action editor - Snap To Frame
A few new menus for this too
Diffstat (limited to 'source/blender/src/edittime.c')
-rw-r--r-- | source/blender/src/edittime.c | 468 |
1 files changed, 306 insertions, 162 deletions
diff --git a/source/blender/src/edittime.c b/source/blender/src/edittime.c index 919508aec0d..a92efac3034 100644 --- a/source/blender/src/edittime.c +++ b/source/blender/src/edittime.c @@ -63,8 +63,10 @@ #include "BIF_interface.h" #include "BIF_toolbox.h" #include "BIF_mywindow.h" +#include "BIF_editaction.h" #include "BSE_drawipo.h" +#include "BSE_edit.h" #include "BSE_headerbuttons.h" #include "BSE_time.h" @@ -79,10 +81,10 @@ /* declarations */ void winqreadtimespace(ScrArea *, void *, BWinEvent *); -/* ************* Timeline marker code **************** */ +/* ************* Marker API **************** */ /* add TimeMarker at curent frame */ -void add_timeline_marker(int frame) +void add_marker(int frame) { TimeMarker *marker; @@ -98,29 +100,29 @@ void add_timeline_marker(int frame) marker->frame= frame; BLI_addtail(&(G.scene->markers), marker); - BIF_undo_push("Add Timeline Marker"); + BIF_undo_push("Add Marker"); } -/* remove TimeMarker */ -void remove_timeline_marker(void) +/* remove selected TimeMarkers */ +void remove_marker(void) { TimeMarker *marker; - + for(marker= G.scene->markers.first; marker; marker= marker->next) { if(marker->flag & SELECT){ - BLI_freelinkN(&G.scene->markers, marker); + BLI_freelinkN(&(G.scene->markers), marker); } } - BIF_undo_push("Remove Timeline Marker"); + BIF_undo_push("Remove Marker"); } /* rename first selected TimeMarker */ -void rename_timeline_marker(void) +void rename_marker(void) { TimeMarker *marker; char name[64]; - + for(marker= G.scene->markers.first; marker; marker= marker->next) { if(marker->flag & SELECT) { sprintf(name, marker->name); @@ -130,14 +132,14 @@ void rename_timeline_marker(void) } } - BIF_undo_push("Rename Timeline Marker"); + BIF_undo_push("Rename Marker"); } /* duplicate selected TimeMarkers */ -void duplicate_timeline_marker(void) +void duplicate_marker(void) { TimeMarker *marker, *newmarker; - + /* go through the list of markers, duplicate selected markers and add duplicated copies * to the begining of the list (unselect original markers) */ for(marker= G.scene->markers.first; marker; marker= marker->next) { @@ -154,72 +156,194 @@ void duplicate_timeline_marker(void) } } - timeline_grab('g', 0); + transform_markers('g', 0); } - - -static int find_nearest_marker(float dx) +void transform_markers(int mode, int smode) // mode and smode unused here, for callback { - TimeMarker *marker, *nearest= NULL; - float dist, min_dist= 1000000; + SpaceLink *slink= curarea->spacedata.first; + SpaceTime *stime= curarea->spacedata.first; + TimeMarker *marker, *selmarker=NULL; + float dx, fac; + int a, ret_val= 0, totmark=0, *oldframe, offs, firsttime=1; + unsigned short event; + short val, pmval[2], mval[2], mvalo[2]; + char str[32]; for(marker= G.scene->markers.first; marker; marker= marker->next) { - dist = ABS((float)marker->frame - dx); - if(dist < min_dist){ - min_dist= dist; - nearest= marker; + if(marker->flag & SELECT) totmark++; + } + if(totmark==0) return; + + oldframe= MEM_mallocN(totmark*sizeof(int), "marker array"); + for(a=0, marker= G.scene->markers.first; marker; marker= marker->next) { + if(marker->flag & SELECT) { + oldframe[a]= marker->frame; + selmarker= marker; // used for hederprint + a++; } } - if(nearest) return nearest->frame; - else return (int)floor(dx); + dx= G.v2d->mask.xmax-G.v2d->mask.xmin; + dx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/dx; + + getmouseco_areawin(pmval); + mvalo[0]= pmval[0]; + + while(ret_val == 0) { + + getmouseco_areawin(mval); + + if (mval[0] != mvalo[0] || firsttime) { + mvalo[0]= mval[0]; + firsttime= 0; + + fac= (((float)(mval[0] - pmval[0]))*dx); + + if (ELEM(slink->spacetype, SPACE_TIME, SPACE_SOUND)) + apply_keyb_grid(&fac, 0.0, (float)G.scene->r.frs_sec, 0.1*(float)G.scene->r.frs_sec, 0); + else + apply_keyb_grid(&fac, 0.0, 1.0, 0.1, U.flag & USER_AUTOGRABGRID); + offs= (int)fac; + + for(a=0, marker= G.scene->markers.first; marker; marker= marker->next) { + if(marker->flag & SELECT) { + marker->frame= oldframe[a] + offs; + a++; + } + } + + if(totmark==1) { // we print current marker value + if (ELEM(slink->spacetype, SPACE_TIME, SPACE_SOUND)) { + if(stime->flag & TIME_DRAWFRAMES) + sprintf(str, "Marker %d offset %d", selmarker->frame, offs); + else + sprintf(str, "Marker %.2f offset %.2f", (selmarker->frame/(float)G.scene->r.frs_sec), (offs/(float)G.scene->r.frs_sec)); + } + else { + sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs)); + } + } + else { + if (ELEM(slink->spacetype, SPACE_TIME, SPACE_SOUND)) { + if(stime->flag & TIME_DRAWFRAMES) + sprintf(str, "Marker offset %d ", offs); + else + sprintf(str, "Marker offset %.2f ", (offs/(float)G.scene->r.frs_sec)); + } + else { + sprintf(str, "Marker offset %.2f ", (double)(offs)); + } + } + headerprint(str); + + force_draw(0); // areas identical to this, 0 = no header + } + else PIL_sleep_ms(10); // idle + + /* emptying queue and reading events */ + while( qtest() ) { + event= extern_qread(&val); + + if(val) { + if(event==ESCKEY || event==RIGHTMOUSE) ret_val= 2; + else if(event==LEFTMOUSE || event==RETKEY || event==SPACEKEY) ret_val= 1; + } + } + } + + /* restore? */ + if(ret_val==2) { + for(a=0, marker= G.scene->markers.first; marker; marker= marker->next) { + if(marker->flag & SELECT) { + marker->frame= oldframe[a]; + a++; + } + } + } + else { + BIF_undo_push("Move Markers"); + } + MEM_freeN(oldframe); + allqueue(REDRAWTIME, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + allqueue(REDRAWSOUND, 0); } -/* select/deselect TimeMarker at current frame */ -static void select_timeline_marker_frame(int frame, unsigned char shift) +/* select/deselect all TimeMarkers + * test - based on current selections? + * sel - selection status to set all markers to if blanket apply status + */ +void deselect_markers(short test, short sel) { TimeMarker *marker; - int select=0; - - for(marker= G.scene->markers.first; marker; marker= marker->next) { - /* if Shift is not set, then deselect Markers */ - if(!shift) marker->flag &= ~SELECT; - /* this way a not-shift select will allways give 1 selected marker */ - if((marker->frame == frame) && (!select)) { - if(marker->flag & SELECT) - marker->flag &= ~SELECT; - else - marker->flag |= SELECT; - select = 1; + + /* check if need to find out whether to how to select markers */ + if (test) { + /* dependant on existing selection */ + /* determine if select all or deselect all */ + sel = 1; + for (marker= G.scene->markers.first; marker; marker= marker->next) { + if (marker->flag & SELECT) { + sel = 0; + break; + } + } + + /* do selection */ + for (marker= G.scene->markers.first; marker; marker= marker->next) { + if (sel) { + if ((marker->flag & SELECT)==0) + marker->flag |= SELECT; + } + else { + if (marker->flag & SELECT) + marker->flag &= ~SELECT; + } + } + } + else { + /* not dependant on existing selection */ + for (marker= G.scene->markers.first; marker; marker= marker->next) { + if (sel) { + if ((marker->flag & SELECT)==0) + marker->flag |= SELECT; + } + else { + if (marker->flag & SELECT) + marker->flag &= ~SELECT; + } } } } -/* select/deselect all TimeMarkers */ -void select_timeline_markers(void) +void borderselect_markers(float xmin, float xmax, int selectmode) { TimeMarker *marker; - char any_selected= 0; - + for(marker= G.scene->markers.first; marker; marker= marker->next) { - if(marker->flag & SELECT) any_selected= 1; - marker->flag &= ~SELECT; - } - - /* no TimeMarker selected, then select all TimeMarkers */ - if(!any_selected){ - for(marker= G.scene->markers.first; marker; marker= marker->next) { - marker->flag |= SELECT; + if ((marker->frame > xmin) && (marker->frame <= xmax)) { + switch (selectmode) { + case SELECT_ADD: + if ((marker->flag & SELECT) == 0) + marker->flag |= SELECT; + break; + case SELECT_SUBTRACT: + if (marker->flag & SELECT) + marker->flag &= ~SELECT; + break; + } } } } -void nextprev_timeline_marker(short dir) +void nextprev_marker(short dir) { TimeMarker *marker, *cur=NULL, *first, *last; int mindist= MAXFRAME, dist; - + first= last= G.scene->markers.first; for(marker= G.scene->markers.first; marker; marker= marker->next) { /* find closest to current frame first */ @@ -248,7 +372,109 @@ void nextprev_timeline_marker(short dir) } } -/* *********** end Markers *************** */ +TimeMarker *find_nearest_marker(int clip_y) +{ + TimeMarker *marker; + float xmin, xmax; + rctf rectf; + short mval[2]; + + getmouseco_areawin (mval); + + /* first clip selection in Y */ + if((clip_y) && (mval[1] > 30)) + return NULL; + + mval[0]-=7; + areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin); + mval[0]+=14; + areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax); + + xmin= rectf.xmin; + xmax= rectf.xmax; + + for(marker= G.scene->markers.first; marker; marker= marker->next) { + if ((marker->frame > xmin) && (marker->frame <= xmax)) { + return marker; + } + } + + return NULL; +} + +/* *********** End Markers - Markers API *************** */ + +/* border-select markers */ +void borderselect_timeline_markers(void) +{ + rcti rect; + rctf rectf; + int val, selectmode; + short mval[2]; + + if ( (val = get_border(&rect, 3)) ){ + if (val == LEFTMOUSE) + selectmode = SELECT_ADD; + else + selectmode = SELECT_SUBTRACT; + + mval[0]= rect.xmin; + mval[1]= rect.ymin+2; + areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin); + mval[0]= rect.xmax; + mval[1]= rect.ymax-2; + areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax); + + /* do markers */ + borderselect_markers(rectf.xmin, rectf.xmax, selectmode); + + BIF_undo_push("Border Select TimeLine"); + allqueue(REDRAWTIME, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + allqueue(REDRAWSOUND, 0); + } +} + +static int find_nearest_timeline_marker(float dx) +{ + TimeMarker *marker, *nearest= NULL; + float dist, min_dist= 1000000; + + for(marker= G.scene->markers.first; marker; marker= marker->next) { + dist = ABS((float)marker->frame - dx); + if(dist < min_dist){ + min_dist= dist; + nearest= marker; + } + } + + if(nearest) return nearest->frame; + else return (int)floor(dx); +} + +/* select/deselect TimeMarker at current frame */ +static void select_timeline_marker_frame(int frame, unsigned char shift) +{ + TimeMarker *marker; + int select=0; + + for(marker= G.scene->markers.first; marker; marker= marker->next) { + /* if Shift is not set, then deselect Markers */ + if(!shift) marker->flag &= ~SELECT; + /* this way a not-shift select will allways give 1 selected marker */ + if((marker->frame == frame) && (!select)) { + if(marker->flag & SELECT) + marker->flag &= ~SELECT; + else + marker->flag |= SELECT; + select = 1; + } + } +} + +/* *********** end Markers - TimeLine *************** */ static int float_to_frame(float frame) { @@ -359,102 +585,6 @@ void timeline_frame_to_center(void) scrarea_queue_winredraw(curarea); } -void timeline_grab(int mode, int smode) // mode and smode unused here, for callback -{ - SpaceTime *stime= curarea->spacedata.first; - TimeMarker *marker, *selmarker=NULL; - float dx, fac; - int a, ret_val= 0, totmark=0, *oldframe, offs, firsttime=1; - unsigned short event; - short val, pmval[2], mval[2], mvalo[2]; - char str[32]; - - for(marker= G.scene->markers.first; marker; marker= marker->next) { - if(marker->flag & SELECT) totmark++; - } - if(totmark==0) return; - - oldframe= MEM_mallocN(totmark*sizeof(int), "marker array"); - for(a=0, marker= G.scene->markers.first; marker; marker= marker->next) { - if(marker->flag & SELECT) { - oldframe[a]= marker->frame; - selmarker= marker; // used for hederprint - a++; - } - } - - dx= G.v2d->mask.xmax-G.v2d->mask.xmin; - dx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/dx; - - getmouseco_areawin(pmval); - mvalo[0]= pmval[0]; - - while(ret_val == 0) { - - getmouseco_areawin(mval); - - if (mval[0] != mvalo[0] || firsttime) { - mvalo[0]= mval[0]; - firsttime= 0; - - fac= (((float)(mval[0] - pmval[0]))*dx); - - apply_keyb_grid(&fac, 0.0, (float)G.scene->r.frs_sec, 0.1*(float)G.scene->r.frs_sec, 0); - offs= (int)fac; - - for(a=0, marker= G.scene->markers.first; marker; marker= marker->next) { - if(marker->flag & SELECT) { - marker->frame= oldframe[a] + offs; - a++; - } - } - - if(totmark==1) { // we print current marker value - if(stime->flag & TIME_DRAWFRAMES) - sprintf(str, "Marker %d offset %d", selmarker->frame, offs); - else - sprintf(str, "Marker %.2f offset %.2f", (selmarker->frame/(float)G.scene->r.frs_sec), (offs/(float)G.scene->r.frs_sec)); - } - else { - if(stime->flag & TIME_DRAWFRAMES) - sprintf(str, "Marker offset %d ", offs); - else - sprintf(str, "Marker offset %.2f ", (offs/(float)G.scene->r.frs_sec)); - } - headerprint(str); - - force_draw(0); // areas identical to this, 0 = no header - } - else PIL_sleep_ms(10); // idle - - /* emptying queue and reading events */ - while( qtest() ) { - event= extern_qread(&val); - - if(val) { - if(event==ESCKEY || event==RIGHTMOUSE) ret_val= 2; - else if(event==LEFTMOUSE || event==RETKEY || event==SPACEKEY) ret_val= 1; - } - } - } - - /* restore? */ - if(ret_val==2) { - for(a=0, marker= G.scene->markers.first; marker; marker= marker->next) { - if(marker->flag & SELECT) { - marker->frame= oldframe[a]; - a++; - } - } - } - else { - BIF_undo_push("Move Markers"); - } - MEM_freeN(oldframe); - allqueue(REDRAWTIME, 0); - allqueue(REDRAWACTION, 0); -} - /* copy of this is actually in editscreen.c, but event based */ static void timeline_force_draw(short val) { @@ -564,7 +694,7 @@ void winqreadtimespace(ScrArea *sa, void *spacedata, BWinEvent *evt) getmouseco_areawin(mval); areamouseco_to_ipoco(G.v2d, mval, &dx, &dy); - cfra= find_nearest_marker(dx); + cfra= find_nearest_timeline_marker(dx); if (G.qual && LR_SHIFTKEY) select_timeline_marker_frame(cfra, 1); @@ -572,7 +702,7 @@ void winqreadtimespace(ScrArea *sa, void *spacedata, BWinEvent *evt) select_timeline_marker_frame(cfra, 0); force_draw(0); - std_rmouse_transform(timeline_grab); + std_rmouse_transform(transform_markers); break; case MIDDLEMOUSE: @@ -608,29 +738,37 @@ void winqreadtimespace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(G.qual==LR_CTRLKEY) nextprev_timeline_key(1); else - nextprev_timeline_marker(1); + nextprev_marker(1); break; case PAGEDOWNKEY: /* prev keyframe */ if(G.qual==LR_CTRLKEY) nextprev_timeline_key(-1); else - nextprev_timeline_marker(-1); + nextprev_marker(-1); break; case AKEY: /* deselect all TimeMarkers */ - select_timeline_markers(); - doredraw= 1; + deselect_markers(1, 0); + allqueue(REDRAWTIME, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + allqueue(REDRAWSOUND, 0); + break; + case BKEY: + /* borderselect markers */ + borderselect_timeline_markers(); break; case DKEY: if(G.qual==LR_SHIFTKEY) - duplicate_timeline_marker(); + duplicate_marker(); break; case CKEY: timeline_frame_to_center(); break; case GKEY: /* move marker */ - timeline_grab('g', 0); + transform_markers('g', 0); break; case EKEY: /* set end frame */ G.scene->r.efra = CFRA; @@ -638,12 +776,15 @@ void winqreadtimespace(ScrArea *sa, void *spacedata, BWinEvent *evt) allqueue(REDRAWTIME, 1); break; case MKEY: /* add, rename marker */ - if (G.qual & LR_CTRLKEY) - rename_timeline_marker(); + if (G.qual & LR_SHIFTKEY) + rename_marker(); else - add_timeline_marker(CFRA); + add_marker(CFRA); allqueue(REDRAWTIME, 0); + allqueue(REDRAWIPO, 0); allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + allqueue(REDRAWSOUND, 0); break; case SKEY: /* set start frame */ G.scene->r.sfra = CFRA; @@ -662,9 +803,12 @@ void winqreadtimespace(ScrArea *sa, void *spacedata, BWinEvent *evt) case XKEY: if( okee("Erase selected")==0 ) break; - remove_timeline_marker(); + remove_marker(); allqueue(REDRAWTIME, 0); + allqueue(REDRAWIPO, 0); allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + allqueue(REDRAWSOUND, 0); break; } } |