added prototypes for bottom_sel_action and friends.
[blender.git] / source / blender / src / editaction.c
index 335f8ee9c7236431fc29d4c4f2e8b9cdb0276c30..e9081b0fbfced0f078261dd721e1d7c7fb4a2324 100644 (file)
 #include <string.h>
 #include <math.h>
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #include "MEM_guardedalloc.h"
 
 #include "PIL_time.h"
 #include "nla.h"
 
 extern int count_action_levels (bAction *act);
+void top_sel_action();
+void up_sel_action();
+void bottom_sel_action();
+void down_sel_action();
 
 #define BEZSELECTED(bezt)   (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
 
 /* Local Function prototypes, are forward needed */
 static void hilight_channel (bAction *act, bActionChannel *chan, short hilight);
 
-static void up_sel_action(void);
-static void down_sel_action(void);
-static void top_sel_action(void);
-static void bottom_sel_action(void);
-
 /* Implementation */
 
 short showsliders = 0;
@@ -146,7 +141,7 @@ bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance)
        bAction                 *temp;
        bPoseChannel    *pchan;
        ID                              *id;
-       float                   actlen;
+       float                   actstart, actend;
        int                             oldframe;
        int                             curframe;
        char                    newname[64];
@@ -174,14 +169,14 @@ bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance)
        sprintf (newname, "%s.BAKED", act->id.name+2);
        rename_id(&result->id, newname);
 
-       actlen = calc_action_end(act);
+       calc_action_range(act, &actstart, &actend);
 
        oldframe = G.scene->r.cfra;
 
        temp = armob->action;
        armob->action = result;
        
-       for (curframe=1; curframe<ceil(actlen+1); curframe++){
+       for (curframe=1; curframe<ceil(actend+1.0f); curframe++){
 
                /* Apply the old action */
                
@@ -847,9 +842,9 @@ void transform_actionchannel_keys(int mode, int dummy)
        bConstraintChannel *conchan;
        bActionChannel  *chan;
        float   deltax, startx;
-       float   cenf[2];
+       float   minx, maxx, cenf[2];
        float   sval[2], cval[2], lastcval[2];
-       float   fac=0.0F;
+       float   fac=0.0f;
        int             loop=1;
        int             tvtot=0;
        int             invert=0, firsttime=1;
@@ -875,6 +870,7 @@ void transform_actionchannel_keys(int mode, int dummy)
        
        /* Build the transvert structure */
        tv = MEM_callocN (sizeof(TransVert) * tvtot, "transVert");
+       
        tvtot=0;
        for (chan=act->chanbase.first; chan; chan=chan->next){
                /* Add the actionchannel */
@@ -882,7 +878,14 @@ void transform_actionchannel_keys(int mode, int dummy)
                for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
                        tvtot = add_trans_ipo_keys(conchan->ipo, tv, tvtot);
        }
-
+       
+       /* min max, only every other three */
+       minx= maxx= tv[1].loc[0];
+       for (i=1; i<tvtot; i+=3){
+               if(minx>tv[i].loc[0]) minx= tv[i].loc[0];
+               if(maxx<tv[i].loc[0]) maxx= tv[i].loc[0];
+       }
+       
        /* Do the event loop */
        cent[0] = curarea->winx + (G.saction->v2d.hor.xmax)/2;
        cent[1] = curarea->winy + (G.saction->v2d.hor.ymax)/2;
@@ -891,8 +894,21 @@ void transform_actionchannel_keys(int mode, int dummy)
        getmouseco_areawin (mvals);
        areamouseco_to_ipoco(G.v2d, mvals, &sval[0], &sval[1]);
 
+       if(G.saction->pin==0 && OBACT)
+               sval[0]= get_action_frame(OBACT, sval[0]);
+       
+       /* used for drawing */
+       if(mode=='t') {
+               G.saction->flag |= SACTION_MOVING;
+               G.saction->timeslide= sval[0];
+       }
+       
        startx=sval[0];
        while (loop) {
+               
+               if(mode=='t' && minx==maxx)
+                       break;
+               
                /*              Get the input */
                /*              If we're cancelling, reset transformations */
                /*                      Else calc new transformation */
@@ -930,14 +946,36 @@ void transform_actionchannel_keys(int mode, int dummy)
                } else {
                        getmouseco_areawin (mvalc);
                        areamouseco_to_ipoco(G.v2d, mvalc, &cval[0], &cval[1]);
+                       
+                       if(G.saction->pin==0 && OBACT)
+                               cval[0]= get_action_frame(OBACT, cval[0]);
 
+                       if(mode=='t')
+                               G.saction->timeslide= cval[0];
+                       
                        if (!firsttime && lastcval[0]==cval[0] && lastcval[1]==cval[1]) {
                                PIL_sleep_ms(1);
                        } else {
+                               
                                for (i=0; i<tvtot; i++){
                                        tv[i].loc[0]=tv[i].oldloc[0];
 
                                        switch (mode){
+                                       case 't':
+                                               if( sval[0] > minx && sval[0] < maxx) {
+                                                       float timefac, cvalc= CLAMPIS(cval[0], minx, maxx);
+                                                       
+                                                       /* left half */
+                                                       if(tv[i].oldloc[0] < sval[0]) {
+                                                               timefac= ( sval[0] - tv[i].oldloc[0])/(sval[0] - minx);
+                                                               tv[i].loc[0]= cvalc - timefac*( cvalc - minx);
+                                                       }
+                                                       else {
+                                                               timefac= (tv[i].oldloc[0] - sval[0])/(maxx - sval[0]);
+                                                               tv[i].loc[0]= cvalc + timefac*(maxx- cvalc);
+                                                       }
+                                               }
+                                               break;
                                        case 'g':
                                                deltax = cval[0]-sval[0];
                                                fac= deltax;
@@ -964,7 +1002,9 @@ void transform_actionchannel_keys(int mode, int dummy)
                                                        fac*=-1;
                                                }
                                                startx= (G.scene->r.cfra);
-                                       
+                                               if(G.saction->pin==0 && OBACT)
+                                                       startx= get_action_frame(OBACT, startx);
+                                                       
                                                tv[i].loc[0]-= startx;
                                                tv[i].loc[0]*=fac;
                                                tv[i].loc[0]+= startx;
@@ -972,29 +1012,35 @@ void transform_actionchannel_keys(int mode, int dummy)
                                                break;
                                        }
                                }
-                       }
        
-                       if (mode=='s'){
-                               sprintf(str, "sizeX: %.3f", fac);
-                               headerprint(str);
-                       }
-                       else if (mode=='g'){
-                               sprintf(str, "deltaX: %.3f", fac);
-                               headerprint(str);
-                       }
-       
-                       if (G.saction->lock) {
-                               if(ob) {
-                                       ob->ctime= -1234567.0f;
-                                       if(ob->pose || ob_get_key(ob))
-                                               DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
-                                       else
-                                               DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
+                               if (mode=='s'){
+                                       sprintf(str, "sizeX: %.3f", fac);
+                                       headerprint(str);
+                               }
+                               else if (mode=='g'){
+                                       sprintf(str, "deltaX: %.3f", fac);
+                                       headerprint(str);
+                               }
+                               else if (mode=='t') {
+                                       float fac= 2.0*(cval[0]-sval[0])/(maxx-minx);
+                                       CLAMP(fac, -1.0f, 1.0f);
+                                       sprintf(str, "TimeSlide: %.3f", fac);
+                                       headerprint(str);
+                               }
+               
+                               if (G.saction->lock) {
+                                       if(ob) {
+                                               ob->ctime= -1234567.0f;
+                                               if(ob->pose || ob_get_key(ob))
+                                                       DAG_object_flush_update(G.scene, ob, OB_RECALC);
+                                               else
+                                                       DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
+                                       }
+                                       force_draw_plus(SPACE_VIEW3D, 0);
+                               }
+                               else {
+                                       force_draw(0);
                                }
-                               force_draw_plus(SPACE_VIEW3D, 0);
-                       }
-                       else {
-                               force_draw(0);
                        }
                }
                
@@ -1010,12 +1056,15 @@ void transform_actionchannel_keys(int mode, int dummy)
                ob->ctime= -1234567.0f;
 
                if(ob->pose || ob_get_key(ob))
-                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+                       DAG_object_flush_update(G.scene, ob, OB_RECALC);
                else
                        DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
        }
+       
        remake_action_ipos(act);
 
+       G.saction->flag &= ~SACTION_MOVING;
+       
        if(cancel==0) BIF_undo_push("Transform Action");
        allqueue (REDRAWVIEW3D, 0);
        allqueue (REDRAWACTION, 0);
@@ -1180,7 +1229,7 @@ void transform_meshchannel_keys(char mode, Key *key)
                                 * future
                                 */
                                 
-                               DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
+                               DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB|OB_RECALC_DATA);
                 allqueue (REDRAWVIEW3D, 0);
                 allqueue (REDRAWACTION, 0);
                 allqueue (REDRAWIPO, 0);
@@ -1542,6 +1591,7 @@ void delete_actionchannel_keys(void)
        allqueue(REDRAWNLA, 0);
 
 }
+
 static void delete_actionchannels (void)
 {
        bConstraintChannel *conchan=NULL, *nextconchan;
@@ -1606,6 +1656,7 @@ static void delete_actionchannels (void)
 
 void sethandles_meshchannel_keys(int code, Key *key)
 {
+       
     sethandles_ipo_keys(key->ipo, code);
 
        BIF_undo_push("Set handles Action keys");
@@ -1640,7 +1691,8 @@ void sethandles_actionchannel_keys(int code)
        allqueue(REDRAWNLA, 0);
 }
 
-void set_ipotype_actionchannels(int ipotype) {
+void set_ipotype_actionchannels(int ipotype) 
+{
 
        bAction *act; 
        bActionChannel *chan;
@@ -1686,6 +1738,96 @@ void set_ipotype_actionchannels(int ipotype) {
        allqueue(REDRAWNLA, 0);
 }
 
+void set_extendtype_actionchannels(int extendtype)
+{
+       bAction *act; 
+       bActionChannel *chan;
+       short event;
+
+       /* Get the selected action, exit if none are selected 
+        */
+       act = G.saction->action;
+       if (!act)
+               return;
+
+       if (extendtype == SET_EXTEND_POPUP) {
+               /* Present a popup menu asking the user what type
+                * of IPO curve he/she/GreenBTH wants. ;)
+                */
+               event
+                       =  pupmenu("Channel Extending Type %t|"
+                                          "Constant %x1|"
+                                          "Extrapolation %x2|"
+                                          "Cyclic %x3|"
+                                          "Cyclic extrapolation %x4");
+               if(event < 1) return;
+               extendtype = event;
+       }
+       
+       /* Loop through the channels and for the selected ones set
+        * the type for each Ipo curve in the channel Ipo (based on
+        * the value from the popup).
+        */
+       for (chan = act->chanbase.first; chan; chan=chan->next){
+               if (chan->flag & ACHAN_SELECTED) {
+                       if (chan->ipo) {
+                               switch (extendtype) {
+                               case SET_EXTEND_CONSTANT:
+                                       setexprap_ipoloop(chan->ipo, IPO_HORIZ);
+                                       break;
+                               case SET_EXTEND_EXTRAPOLATION:
+                                       setexprap_ipoloop(chan->ipo, IPO_DIR);
+                                       break;
+                               case SET_EXTEND_CYCLIC:
+                                       setexprap_ipoloop(chan->ipo, IPO_CYCL);
+                                       break;
+                               case SET_EXTEND_CYCLICEXTRAPOLATION:
+                                       setexprap_ipoloop(chan->ipo, IPO_CYCLX);
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       /* Clean up and redraw stuff
+        */
+       remake_action_ipos (act);
+       BIF_undo_push("Set Ipo type Action channel");
+       allspace(REMAKEIPO, 0);
+       allqueue(REDRAWACTION, 0);
+       allqueue(REDRAWIPO, 0);
+       allqueue(REDRAWNLA, 0);
+}
+
+void set_snap_actionchannels(void) 
+{
+       
+       bAction *act; 
+       bActionChannel *chan;
+       
+       /* Get the selected action, exit if none are selected 
+               */
+       act = G.saction->action;
+       if (!act)
+               return;
+       
+       /* Loop through the channels */
+       for (chan = act->chanbase.first; chan; chan=chan->next){
+               if (chan->ipo) {
+                       snap_ipo_keys(chan->ipo);
+               }
+       }
+       
+       /* Clean up and redraw stuff */
+       remake_action_ipos (act);
+       BIF_undo_push("Snap Ipo Action channel");
+       allspace(REMAKEIPO, 0);
+       allqueue(REDRAWACTION, 0);
+       allqueue(REDRAWIPO, 0);
+       allqueue(REDRAWNLA, 0);
+}
+
+
 static void select_all_keys_frames(bAction *act, short *mval, 
                                                        short *mvalo, int selectmode) {
        
@@ -2121,20 +2263,20 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                        break;
 
                case HKEY:
-                       if (key) {
-                               if(G.qual & LR_SHIFTKEY) {
-                                       sethandles_meshchannel_keys(HD_AUTO, key);
-                               }
-                               else { 
-                                       sethandles_meshchannel_keys(HD_ALIGN, key);
+                       if(G.qual & LR_SHIFTKEY) {
+                               if(okee("Set Keys to Auto Handle")) {
+                                       if (key)
+                                               sethandles_meshchannel_keys(HD_AUTO, key);
+                                       else
+                                               sethandles_actionchannel_keys(HD_AUTO);
                                }
                        }
                        else {
-                               if(G.qual & LR_SHIFTKEY) {
-                                       sethandles_actionchannel_keys(HD_AUTO);
-                               }
-                               else { 
-                                       sethandles_actionchannel_keys(HD_ALIGN);
+                               if(okee("Toggle Keys Aligned Handle")) {
+                                       if (key)
+                                               sethandles_meshchannel_keys(HD_ALIGN, key);
+                                       else
+                                               sethandles_actionchannel_keys(HD_ALIGN);
                                }
                        }
                        break;
@@ -2151,11 +2293,15 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                        
                case SKEY: 
                        if (mval[0]>=ACTWIDTH) {
-                               if (key) {
-                                       transform_meshchannel_keys('s', key);
+                               if(G.qual & LR_SHIFTKEY) {
+                                       if(okee("Snap to frame"))
+                                               set_snap_actionchannels();
                                }
-                               else if (act) {
-                                       transform_actionchannel_keys ('s', 0);
+                               else {
+                                       if (key)
+                                               transform_meshchannel_keys('s', key);
+                                       else if (act)
+                                               transform_actionchannel_keys ('s', 0);
                                }
                        }
                        break;
@@ -2166,17 +2312,19 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                /* to do */
                        }
                        else {
-                               set_ipotype_actionchannels(SET_IPO_POPUP);
+                               if(G.qual & LR_SHIFTKEY)
+                                       set_ipotype_actionchannels(SET_IPO_POPUP);
+                               else
+                                       transform_actionchannel_keys ('t', 0);
                        }
                        break;
 
                case VKEY:
-                       if (key) {
-                               sethandles_meshchannel_keys(HD_VECT, key);
-                               /* to do */
-                       }
-                       else {
-                               sethandles_actionchannel_keys(HD_VECT);
+                       if(okee("Set Keys to Vector Handle")) {
+                               if (key)
+                                       sethandles_meshchannel_keys(HD_VECT, key);
+                               else
+                                       sethandles_actionchannel_keys(HD_VECT);
                        }
                        break;