diff options
-rw-r--r-- | source/blender/blenkernel/intern/action.c | 5 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 5 | ||||
-rw-r--r-- | source/blender/include/BIF_editaction.h | 15 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_action_types.h | 13 | ||||
-rw-r--r-- | source/blender/src/drawaction.c | 91 | ||||
-rw-r--r-- | source/blender/src/editaction.c | 521 | ||||
-rw-r--r-- | source/blender/src/edittime.c | 3 | ||||
-rw-r--r-- | source/blender/src/header_action.c | 120 |
8 files changed, 670 insertions, 103 deletions
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 9f42e682e82..3ee6b89804c 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -176,6 +176,10 @@ void free_action(bAction *act) free_constraint_channels(&chan->constraintChannels); } + /* Free markers */ + if (act->markers.first) + BLI_freelistN (&act->markers); + if (act->chanbase.first) BLI_freelistN (&act->chanbase); } @@ -189,6 +193,7 @@ bAction* copy_action(bAction *src) dst= copy_libblock(src); duplicatelist(&(dst->chanbase), &(src->chanbase)); + duplicatelist(&(dst->markers), &(src->markers)); for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next){ dchan->ipo = copy_ipo(dchan->ipo); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 2ee553824ef..2b2ba9f77bd 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1551,6 +1551,7 @@ static void write_actions(WriteData *wd, ListBase *idbase) { bAction *act; bActionChannel *chan; + TimeMarker *marker; for(act=idbase->first; act; act= act->id.next) { if (act->id.us>0 || wd->current) { @@ -1560,6 +1561,10 @@ static void write_actions(WriteData *wd, ListBase *idbase) writestruct(wd, DATA, "bActionChannel", 1, chan); write_constraint_channels(wd, &chan->constraintChannels); } + + /* writing dynamic list of TimeMarkers to the blend file */ + for(marker= act->markers.first; marker; marker= marker->next) + writestruct(wd, DATA, "TimeMarker", 1, marker); } } } diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h index 4645cb415e8..6ccec20181d 100644 --- a/source/blender/include/BIF_editaction.h +++ b/source/blender/include/BIF_editaction.h @@ -67,6 +67,7 @@ struct Object; struct Ipo; struct BWinEvent; struct Key; +struct ListBase; /* Key operations */ void delete_meshchannel_keys(struct Key *key); @@ -81,6 +82,18 @@ void snap_keys_to_frame(void); void clean_shapekeys(struct Key *key); void clean_actionchannels(struct bAction *act); +/* Marker Operations */ +struct ListBase *get_saction_markers(struct SpaceAction *saction); +void add_saction_marker(struct ListBase *markers, int frame); +void duplicate_saction_markers(struct ListBase *markers); +void remove_saction_markers(struct ListBase *markers); +void rename_saction_markers(struct ListBase *markers); +void transform_saction_markers(int mode, int smode); +void deselect_saction_markers(struct ListBase *markers, int test); +void borderselect_saction_markers(struct ListBase *markers, float xmin, float xmax, int selectmode); +struct TimeMarker *find_nearest_saction_marker(struct ListBase *markers); + + /* channel/strip operations */ void up_sel_action(void); void down_sel_action(void); @@ -99,12 +112,14 @@ void set_extendtype_actionchannels(int extendtype); /* Select */ void borderselect_mesh(struct Key *key); void borderselect_action(void); +void borderselect_markers(struct ListBase *markers); void deselect_actionchannel_keys(struct bAction *act, int test); void deselect_actionchannels (struct bAction *act, int test); void deselect_meshchannel_keys (struct Key *key, int test); int select_channel(struct bAction *act, struct bActionChannel *chan, int selectmode); void select_actionchannel_by_name (struct bAction *act, char *name, int select); + /* Action */ struct bActionChannel* get_hilighted_action_channel(struct bAction* action); struct bAction *add_empty_action(int blocktype); diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index d27dc391f24..d9db6e0c889 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -100,7 +100,8 @@ typedef struct bActionChannel { typedef struct bAction { ID id; - ListBase chanbase; /* Channels in this action */ + ListBase chanbase; /* Action Channels in this action */ + ListBase markers; /* Markers specific to this action */ } bAction; typedef struct SpaceAction { @@ -114,7 +115,7 @@ typedef struct SpaceAction { View2D v2d; bAction *action; int flag; - short pin, actnr, lock, pad; + short pin, actnr, lock, markert; float timeslide; } SpaceAction; @@ -125,7 +126,13 @@ typedef struct SpaceAction { #define ACHAN_MOVED 0x80000000 /* SpaceAction flag */ -#define SACTION_MOVING 1 +#define SACTION_MOVING 1 /* during transform */ +#define SACTION_SLIDERS 2 /* show sliders (if relevant) - limited to shape keys for now */ + +/* SpaceAction Marker Type */ +#define SACTION_NOMARKERS 0 /* no markers */ +#define SACTION_SCMARKERS 1 /* markers for current scene */ +#define SACTION_ACMARKERS 2 /* markers from current action */ /* Pose->flag */ #define POSE_RECALC 1 diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index e628b9ca672..de36b02ec98 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -215,6 +215,92 @@ void draw_cfra_action(void) glLineWidth(1.0); } +/* Aligorith: for now, just draw them as lines (for debugging) */ +static void draw_marker(TimeMarker *marker) +{ + float xpos, xspace, yspace, xpixels, ypixels; + float vec[2]; + + + xpos = marker->frame; + /* no time correction for framelen! space is drawn with old values */ + + xspace= G.v2d->cur.xmax - G.v2d->cur.xmin; + yspace= G.v2d->cur.ymax - G.v2d->cur.ymin; + xpixels= G.v2d->mask.xmax-G.v2d->mask.xmin; + ypixels= G.v2d->mask.ymax-G.v2d->mask.ymin; + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + /* draw line through this point */ + vec[0]= G.scene->r.framelen * xpos; + + vec[1]= G.v2d->cur.ymin; + if (marker->flag & SELECT) + glColor3ub(0xFF, 0xFF, 0x99); + else + glColor3ub(0xAA, 0xAA, 0x55); + glLineWidth(2.0); + + glBegin(GL_LINE_STRIP); + glVertex2fv(vec); + vec[1]= G.v2d->cur.ymax; + glVertex2fv(vec); + glEnd(); + + + /* 5 px to offset icon to align properly, space / pixels corrects for zoom */ + if(marker->flag & SELECT) + BIF_icon_draw(xpos-(5.0*(xspace/xpixels)), (12.0*yspace/ypixels)-CHANNELHEIGHT, ICON_MARKER_HLT); + else + BIF_icon_draw(xpos-(5.0*(xspace/xpixels)), (12.0*yspace/ypixels)-CHANNELHEIGHT, ICON_MARKER); + + glBlendFunc(GL_ONE, GL_ZERO); + glDisable(GL_BLEND); + + /* and the marker name too, shifted slightly to the top-right */ + if(marker->name && marker->name[0]) { + if(marker->flag & SELECT) { + BIF_ThemeColor(TH_TEXT_HI); + glRasterPos2f(xpos+(4.0*(xspace/xpixels)), + ((ypixels<=39.0)?(ypixels-10.0):29.0)*yspace/ypixels); + } + else { + BIF_ThemeColor(TH_TEXT); + if((marker->frame <= G.scene->r.cfra) && (marker->frame+5 > G.scene->r.cfra)) + glRasterPos2f(xpos+(4.0*(xspace/xpixels)), + ((ypixels<=39.0)?(ypixels-10.0):29.0)*yspace/ypixels); + else + glRasterPos2f(xpos+(4.0*(xspace/xpixels)), 17.0*yspace/ypixels); + } + BMF_DrawString(G.font, marker->name); + } +} + +static void draw_markers_action(SpaceAction *saction) +{ + ListBase *markers; + TimeMarker *marker; + + /* try to get markers */ + markers = get_saction_markers(saction); + if (markers == NULL) + return; + + /* unselected markers are drawn at the first time */ + for(marker= markers->first; marker; marker= marker->next) { + if(!(marker->flag & SELECT)) draw_marker(marker); + } + + /* selected markers are drawn later ... selected markers have to cover unselected + * markers laying at the same position as selected markers + * (jiri: it is hack, it could be solved better) */ + for(marker= markers->first; marker; marker= marker->next) { + if(marker->flag & SELECT) draw_marker(marker); + } +} + /* left hand */ static void draw_action_channel_names(bAction *act) { @@ -682,7 +768,7 @@ void drawactionspace(ScrArea *sa, void *spacedata) */ draw_mesh_strips(G.saction, key); } - + /* Draw current frame */ glViewport(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, @@ -694,6 +780,9 @@ void drawactionspace(ScrArea *sa, void *spacedata) ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1); myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax); draw_cfra_action(); + + /* Draw markers */ + draw_markers_action(G.saction); /* Draw scroll */ mywinset(curarea->win); // reset scissor too diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index 14d65d5bf7d..4af44f796b7 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -135,101 +135,6 @@ static void select_poseelement_by_name (char *name, int select) } } -bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance) -{ - bArmature *arm; - bAction *result=NULL; - bActionChannel *achan; - bAction *temp; - bPoseChannel *pchan; - ID *id; - float actstart, actend; - int oldframe; - int curframe; - char newname[64]; - - if (!act) - return NULL; - - arm = get_armature(armob); - - if (G.obedit){ - error ("Actions can't be baked in Edit Mode"); - return NULL; - } - - if (!arm || armob->pose==NULL){ - error ("Select an armature before baking"); - return NULL; - } - - /* Get a new action */ - result = add_empty_action(ID_PO); - id= (ID *)armob; - - /* Assign the new action a unique name */ - sprintf (newname, "%s.BAKED", act->id.name+2); - rename_id(&result->id, newname); - - calc_action_range(act, &actstart, &actend, 1); - - oldframe = G.scene->r.cfra; - - temp = armob->action; - armob->action = result; - - for (curframe=1; curframe<ceil(actend+1.0f); curframe++){ - - /* Apply the old action */ - - G.scene->r.cfra = curframe; - - /* Apply the object ipo */ - extract_pose_from_action(armob->pose, act, curframe); - - where_is_pose(armob); - - /* For each channel: set quats and locs if channel is a bone */ - for (pchan=armob->pose->chanbase.first; pchan; pchan=pchan->next){ - - /* Apply to keys */ - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z); - } - } - - - /* Make another pass to ensure all keyframes are set to linear interpolation mode */ - for (achan = result->chanbase.first; achan; achan=achan->next){ - IpoCurve* icu; - if(achan->ipo) { - for (icu = achan->ipo->curve.first; icu; icu=icu->next){ - icu->ipo= IPO_LIN; - } - } - } - - notice ("Made a new action named \"%s\"", newname); - G.scene->r.cfra = oldframe; - armob->action = temp; - - /* restore */ - extract_pose_from_action(armob->pose, act, G.scene->r.cfra); - where_is_pose(armob); - - allqueue(REDRAWACTION, 1); - - return result; -} - /* apparently within active object context */ /* called extern, like on bone selection */ void select_actionchannel_by_name (bAction *act, char *name, int select) @@ -697,16 +602,20 @@ static void mouse_action(int selectmode) float selx; bActionChannel *chan; bConstraintChannel *conchan; + TimeMarker *marker; + ListBase *markers; short mval[2]; act=G.saction->action; if (!act) return; + markers= get_saction_markers(G.saction); getmouseco_areawin (mval); chan=get_nearest_actionchannel_key(&selx, &sel, &conchan); - + marker=find_nearest_saction_marker(markers); + if (chan){ if (selectmode == SELECT_REPLACE) { selectmode = SELECT_ADD; @@ -734,6 +643,20 @@ static void mouse_action(int selectmode) allqueue(REDRAWOOPS, 0); allqueue(REDRAWBUTSALL, 0); } + else if (marker != NULL) { + /* not channel, so maybe marker */ + if (selectmode == SELECT_REPLACE) { + selectmode = SELECT_ADD; + + deselect_saction_markers(markers, 0); + marker->flag |= SELECT; + } + + std_rmouse_transform(transform_saction_markers); + + allqueue(REDRAWACTION, 0); + allqueue(REDRAWTIME, 0); + } } static void mouse_mesh_action(int selectmode, Key *key) @@ -743,6 +666,8 @@ static void mouse_mesh_action(int selectmode, Key *key) */ IpoCurve *icu; + TimeMarker *marker; + ListBase *markers; short sel; float selx; short mval[2]; @@ -754,6 +679,9 @@ static void mouse_mesh_action(int selectmode, Key *key) * data, etc) */ + markers= get_saction_markers(G.saction); + marker= find_nearest_saction_marker(markers); + /* get the click location, and the cooresponding * ipo curve and selection time value */ @@ -803,12 +731,15 @@ void borderselect_action(void) bActionChannel *chan; bConstraintChannel *conchan; bAction *act; + ListBase *markers; float ymin, ymax; act=G.saction->action; if (!act) return; + + markers = get_saction_markers(G.saction); if ( (val = get_border(&rect, 3)) ){ if (val == LEFTMOUSE) @@ -822,7 +753,7 @@ void borderselect_action(void) mval[0]= rect.xmax; mval[1]= rect.ymax-2; areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax); - + /* if action is mapped in NLA, it returns a correction */ if(G.saction->pin==0 && OBACT) { rectf.xmin= get_action_frame(OBACT, rectf.xmin); @@ -854,31 +785,46 @@ void borderselect_action(void) } } } + + /* do markers first */ + if (markers != NULL) + borderselect_saction_markers(markers, rectf.xmin, rectf.xmax, selectmode); + + BIF_undo_push("Border Select Action"); allqueue(REDRAWNLA, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWIPO, 0); + if (markers != NULL) allqueue(REDRAWTIME, 0); } } void borderselect_mesh(Key *key) { + ListBase *markers; rcti rect; int val, adrcodemax, adrcodemin; short mval[2]; float xmin, xmax; + int selectmode; int (*select_function)(BezTriple *); IpoCurve *icu; + markers = get_saction_markers(G.saction); + if ( (val = get_border(&rect, 3)) ){ /* set the selection function based on what * mouse button had been used in the border * select */ - if (val == LEFTMOUSE) + if (val == LEFTMOUSE) { + selectmode = SELECT_ADD; select_function = select_bezier_add; - else + } + else { + selectmode = SELECT_SUBTRACT; select_function = select_bezier_subtract; + } /* get the minimum and maximum adrcode numbers * for the IpoCurves (this is the number that @@ -909,11 +855,17 @@ void borderselect_mesh(Key *key) } } } + + /* do markers too if any */ + if (markers != NULL) + borderselect_saction_markers(markers, xmin, xmax, selectmode); + /* redraw stuff */ BIF_undo_push("Border select Action Key"); allqueue(REDRAWNLA, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWIPO, 0); + if (markers != NULL) allqueue(REDRAWTIME, 0); } } @@ -2453,6 +2405,7 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) extern void do_actionbuts(unsigned short event); // drawaction.c SpaceAction *saction; bAction *act; + ListBase *markers; Key *key; float dx,dy; int doredraw= 0; @@ -2467,6 +2420,8 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) saction= curarea->spacedata.first; if (!saction) return; + + markers = get_saction_markers(saction); act=saction->action; if(val) { @@ -2635,6 +2590,27 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) allqueue(REDRAWNLA, 0); break; + case MKEY: + /* marker operations */ + if (G.qual == 0) + add_saction_marker(markers, CFRA); + else if (G.qual == LR_ALTKEY) { + if( okee("Erase selected markers")==0 ) + break; + remove_saction_markers(markers); + } + else if (G.qual == LR_CTRLKEY) + rename_saction_markers(markers); + else if (G.qual == LR_SHIFTKEY) + transform_saction_markers('g', 0); + else if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) + duplicate_saction_markers(markers); + else + break; + allqueue(REDRAWACTION, 0); + allqueue(REDRAWTIME, 0); + break; + case NKEY: if(G.qual==0) { numbuts_action(); @@ -2890,7 +2866,256 @@ int get_nearest_key_num(Key *key, short *mval, float *x) { return (num + 1); } +/* ************************************* Action Editor Markers ************************************* */ + +/* returns the current active markers */ +ListBase *get_saction_markers (SpaceAction *saction) +{ + ListBase *markers; + + if (saction->markert == SACTION_SCMARKERS) + markers = &(G.scene->markers); + else if ((saction->markert == SACTION_ACMARKERS) && (saction->action != NULL)) + markers = &(saction->action->markers); + else + markers = NULL; + + return markers; +} + +/* add a TimeMarker - code basically taken from edittime.c */ +void add_saction_marker (ListBase *markers, int frame) +{ + TimeMarker *marker; + + /* two markers can't be at the same place */ + for(marker= markers->first; marker; marker= marker->next) + if(marker->frame == frame) return; + /* deselect all */ + for(marker= markers->first; marker; marker= marker->next) + marker->flag &= ~SELECT; + + marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker"); + marker->flag= SELECT; + marker->frame= frame; + BLI_addtail(markers, marker); + + BIF_undo_push("Add Marker"); +} + +/* remove a TimeMarker - code basically taken from edittime.c */ +void remove_saction_markers(ListBase *markers) +{ + TimeMarker *marker; + + for(marker= markers->first; marker; marker= marker->next) { + if(marker->flag & SELECT){ + BLI_freelinkN(markers, marker); + } + } + + BIF_undo_push("Remove Marker"); +} + +/* rename a TimeMarker - code basically taken from edittime.c */ +void rename_saction_markers(ListBase *markers) +{ + TimeMarker *marker; + char name[64]; + + for(marker= markers->first; marker; marker= marker->next) { + if(marker->flag & SELECT) { + sprintf(name, marker->name); + if (sbutton(name, 0, sizeof(name)-1, "Name: ")) + BLI_strncpy(marker->name, name, sizeof(marker->name)); + break; + } + } + + BIF_undo_push("Rename Marker"); +} + +/* duplicate selected TimeMarkers - code basically taken from edittime.c */ +void duplicate_saction_markers(ListBase *markers) +{ + 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= markers->first; marker; marker= marker->next) { + if(marker->flag & SELECT){ + /* unselect selected marker */ + marker->flag &= ~SELECT; + /* create and set up new marker */ + newmarker = MEM_callocN(sizeof(TimeMarker), "TimeMarker"); + newmarker->flag= SELECT; + newmarker->frame= marker->frame; + BLI_strncpy(newmarker->name, marker->name, sizeof(marker->name)); + /* new marker is added to the begining of list */ + BLI_addhead(markers, newmarker); + } + } + + transform_saction_markers('g', 0); +} + +void transform_saction_markers(int mode, int smode) // mode and smode unused here, for callback +{ + SpaceAction *saction= curarea->spacedata.first; + TimeMarker *marker, *selmarker=NULL; + ListBase *markers; + 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]; + + markers= get_saction_markers(saction); + if (markers == NULL) return; + + for(marker= 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= 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, 1.0, 0.1, U.flag & USER_AUTOGRABGRID); + offs= (int)fac; + + for(a=0, marker= markers->first; marker; marker= marker->next) { + if(marker->flag & SELECT) { + marker->frame= oldframe[a] + offs; + a++; + } + } + + if(totmark==1) // we print current marker value + sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs)); + 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= 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(REDRAWACTION, 0); + allqueue(REDRAWTIME, 0); +} + +TimeMarker *find_nearest_saction_marker(ListBase *markers) +{ + TimeMarker *marker; + float xmin, xmax; + rctf rectf; + short mval[2]; + + getmouseco_areawin (mval); + 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= markers->first; marker; marker= marker->next) { + if ((marker->frame > xmin) && (marker->frame <= xmax)) { + return marker; + } + } + + return NULL; +} + +/* select/deselect all TimeMarkers */ +void deselect_saction_markers(ListBase *markers, int test) +{ + TimeMarker *marker; + + for (marker = markers->first; marker; marker= marker->next) { + if (test) { + if ((marker->flag & SELECT)==0) + marker->flag |= SELECT; + } + else { + if (marker->flag & SELECT) + marker->flag &= ~SELECT; + } + } +} + +void borderselect_saction_markers(ListBase *markers, float xmin, float xmax, int selectmode) +{ + TimeMarker *marker; + + for(marker= markers->first; marker; marker= marker->next) { + 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; + } + } + } +} + +/* ************************************* Action Channel Ordering *********************************** */ void top_sel_action() { @@ -3051,6 +3276,9 @@ void bottom_sel_action() allqueue(REDRAWNLA, 0); } +/* ********************************* BAKING STUFF ********************************** */ +/* NOTE: these functions should probably be moved to their own file sometime - Aligorith */ + void world2bonespace(float boneSpaceMat[][4], float worldSpace[][4], float restPos[][4], float armPos[][4]) { float imatarm[4][4], imatbone[4][4], tmat[4][4], t2mat[4][4]; @@ -3062,6 +3290,101 @@ void world2bonespace(float boneSpaceMat[][4], float worldSpace[][4], float restP Mat4MulMat4(boneSpaceMat, restPos, t2mat); } +bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance) +{ + bArmature *arm; + bAction *result=NULL; + bActionChannel *achan; + bAction *temp; + bPoseChannel *pchan; + ID *id; + float actstart, actend; + int oldframe; + int curframe; + char newname[64]; + + if (!act) + return NULL; + + arm = get_armature(armob); + + if (G.obedit){ + error ("Actions can't be baked in Edit Mode"); + return NULL; + } + + if (!arm || armob->pose==NULL){ + error ("Select an armature before baking"); + return NULL; + } + + /* Get a new action */ + result = add_empty_action(ID_PO); + id= (ID *)armob; + + /* Assign the new action a unique name */ + sprintf (newname, "%s.BAKED", act->id.name+2); + rename_id(&result->id, newname); + + calc_action_range(act, &actstart, &actend, 1); + + oldframe = G.scene->r.cfra; + + temp = armob->action; + armob->action = result; + + for (curframe=1; curframe<ceil(actend+1.0f); curframe++){ + + /* Apply the old action */ + + G.scene->r.cfra = curframe; + + /* Apply the object ipo */ + extract_pose_from_action(armob->pose, act, curframe); + + where_is_pose(armob); + + /* For each channel: set quats and locs if channel is a bone */ + for (pchan=armob->pose->chanbase.first; pchan; pchan=pchan->next){ + + /* Apply to keys */ + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z); + } + } + + + /* Make another pass to ensure all keyframes are set to linear interpolation mode */ + for (achan = result->chanbase.first; achan; achan=achan->next){ + IpoCurve* icu; + if(achan->ipo) { + for (icu = achan->ipo->curve.first; icu; icu=icu->next){ + icu->ipo= IPO_LIN; + } + } + } + + notice ("Made a new action named \"%s\"", newname); + G.scene->r.cfra = oldframe; + armob->action = temp; + + /* restore */ + extract_pose_from_action(armob->pose, act, G.scene->r.cfra); + where_is_pose(armob); + + allqueue(REDRAWACTION, 1); + + return result; +} + bAction* bake_obIPO_to_action (Object *ob) { diff --git a/source/blender/src/edittime.c b/source/blender/src/edittime.c index 266d7bda139..919508aec0d 100644 --- a/source/blender/src/edittime.c +++ b/source/blender/src/edittime.c @@ -452,6 +452,7 @@ void timeline_grab(int mode, int smode) // mode and smode unused here, for callb } MEM_freeN(oldframe); allqueue(REDRAWTIME, 0); + allqueue(REDRAWACTION, 0); } /* copy of this is actually in editscreen.c, but event based */ @@ -642,6 +643,7 @@ void winqreadtimespace(ScrArea *sa, void *spacedata, BWinEvent *evt) else add_timeline_marker(CFRA); allqueue(REDRAWTIME, 0); + allqueue(REDRAWACTION, 0); break; case SKEY: /* set start frame */ G.scene->r.sfra = CFRA; @@ -662,6 +664,7 @@ void winqreadtimespace(ScrArea *sa, void *spacedata, BWinEvent *evt) remove_timeline_marker(); allqueue(REDRAWTIME, 0); + allqueue(REDRAWACTION, 0); break; } } diff --git a/source/blender/src/header_action.c b/source/blender/src/header_action.c index de4cafbe3ec..0bb18014b4e 100644 --- a/source/blender/src/header_action.c +++ b/source/blender/src/header_action.c @@ -83,6 +83,7 @@ #define ACTMENU_VIEW_ALL 4 #define ACTMENU_VIEW_MAXIMIZE 5 #define ACTMENU_VIEW_LOCK 6 +#define ACTMENU_VIEW_SLIDERS 7 #define ACTMENU_SEL_BORDER 0 #define ACTMENU_SEL_ALL_KEYS 1 @@ -118,6 +119,12 @@ #define ACTMENU_KEY_EXTEND_CYCLIC 2 #define ACTMENU_KEY_EXTEND_CYCLICEXTRAPOLATION 3 +#define ACTMENU_MARKERS_ADD 0 +#define ACTMENU_MARKERS_DUPLICATE 1 +#define ACTMENU_MARKERS_DELETE 2 +#define ACTMENU_MARKERS_NAME 3 +#define ACTMENU_MARKERS_MOVE 4 + void do_action_buttons(unsigned short event) { Object *ob= OBACT; @@ -234,6 +241,9 @@ static void do_action_viewmenu(void *arg, int event) if(G.v2d->flag & V2D_VIEWLOCK) view2d_do_locks(curarea, 0); break; + case ACTMENU_VIEW_SLIDERS: /* Show sliders (when applicable) */ + G.saction->flag ^= SACTION_SLIDERS; + break; case ACTMENU_VIEW_MAXIMIZE: /* Maximize Window */ /* using event B_FULL */ break; @@ -262,6 +272,14 @@ static uiBlock *action_viewmenu(void *arg_unused) "Update Automatically|", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_VIEW_AUTOUPDATE, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, + menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, (G.saction->flag & SACTION_SLIDERS)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT, + "Show Sliders|", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 1, + ACTMENU_VIEW_SLIDERS, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -866,6 +884,80 @@ static uiBlock *action_keymenu(void *arg_unused) return block; } +static void do_action_markermenu(void *arg, int event) +{ + SpaceAction *saction; + ListBase *lb = NULL; + + saction= curarea->spacedata.first; + if (!saction) + return; + + /* get set of markers */ + lb= get_saction_markers(saction); + if (lb == NULL) + return; + + switch(event) + { + case ACTMENU_MARKERS_ADD: + add_saction_marker(lb, CFRA); + break; + case ACTMENU_MARKERS_DUPLICATE: + duplicate_saction_markers(lb); + break; + case ACTMENU_MARKERS_DELETE: + remove_saction_markers(lb); + break; + case ACTMENU_MARKERS_NAME: + rename_saction_markers(lb); + break; + case ACTMENU_MARKERS_MOVE: + transform_saction_markers('g', 0); + break; + } + + allqueue(REDRAWACTION, 0); + allqueue(REDRAWTIME, 0); +} + +static uiBlock *action_markermenu(void *arg_unused) +{ + uiBlock *block; + short yco= 0, menuwidth=120; + + block= uiNewBlock(&curarea->uiblocks, "action_markermenu", + UI_EMBOSSP, UI_HELV, curarea->headwin); + uiBlockSetButmFunc(block, do_action_markermenu, NULL); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Marker|M", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_ADD, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate Marker(s)|Ctrl Shift M", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_DUPLICATE, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Marker(s)|Alt M", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_DELETE, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "(Re)Name Marker(s)|Ctrl M", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_NAME, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move Marker(s)|Shift M", 0, yco-=20, + menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_MOVE, ""); + + + if(curarea->headertype==HEADERTOP) { + uiBlockSetDirection(block, UI_DOWN); + } + else { + uiBlockSetDirection(block, UI_TOP); + uiBlockFlipOrder(block); + } + + uiTextBoundsBlock(block, 50); + + return block; +} + void action_buttons(void) { uiBlock *block; @@ -942,6 +1034,11 @@ void action_buttons(void) uiDefPulldownBut(block, action_keymenu, NULL, "Key", xco, -2, xmax-3, 24, ""); xco+= xmax; + + xmax= GetButStringLength("Marker"); + uiDefPulldownBut(block, action_markermenu, NULL, + "Marker", xco, -2, xmax-3, 24, ""); + xco+= xmax; } uiBlockSetEmboss(block, UI_EMBOSS); @@ -955,6 +1052,29 @@ void action_buttons(void) from, &(G.saction->actnr), B_ACTALONE, B_ACTLOCAL, B_ACTIONDELETE, 0, 0); + + /* Draw marker set selection box */ + xco+= 8; + + if (G.saction->action != NULL) { + uiDefButS(block, MENU, B_REDR, + "Markers%t|None%x0|Scene%x1|Action%x2", + xco, 0, 80, 20, &(G.saction->markert), 0, 0, 0, 0, + "What set of markers to display."); + } + else { + if (G.saction->markert == SACTION_ACMARKERS) + G.saction->markert = SACTION_NOMARKERS; + + uiDefButS(block, MENU, B_REDR, + "Markers%t|None%x0|Scene%x1", + xco, 0, 80, 20, &(G.saction->markert), 0, 0, 0, 0, + "What set of markers to display."); + } + + xco+=80; + + /* Draw action baker */ xco+= 8; |