Added support for manipulating Ipo bezier handles through
authorChris Want <cwant@ualberta.ca>
Tue, 28 Jan 2003 03:11:27 +0000 (03:11 +0000)
committerChris Want <cwant@ualberta.ca>
Tue, 28 Jan 2003 03:11:27 +0000 (03:11 +0000)
the action window. Selecting action keys and pressing VKEY,
HKEY, or shift-HKEY modifies the handles of the keys in
the same way it does in the IPO window. (suggested by Lyubomir)

source/blender/include/BSE_editipo.h
source/blender/src/editaction.c
source/blender/src/editipo.c

index 69fb9dd65ac30fa911c0b6a96a2fa6ac0c76ffbb..afafcf7242800ad793169a1a8a0992168db36fbd 100644 (file)
@@ -130,6 +130,7 @@ void filter_sampledata(float *data, int sfra, int efra);
 void sampledata_to_ipocurve(float *data, int sfra, int efra, struct IpoCurve *icu);
 void ipo_record(void);    
 
+void sethandles_ipo_keys(struct Ipo *ipo, int code);
 void set_ipo_key_selection(struct Ipo *ipo, int sel);
 int is_ipo_key_selected(struct Ipo *ipo);
 void delete_ipo_keys(struct Ipo *ipo);
index 28234042c939167c77a02d11c342dc4b5e9f49c3..c9ee8c546b452072c1cfeaa0820ca55519e1e5f3 100644 (file)
@@ -1310,6 +1310,35 @@ static void delete_actionchannels (void)
        allqueue(REDRAWNLA, 0);
 
 }
+
+static void sethandles_actionchannel_keys(int code)
+{
+       bAction *act;
+       bActionChannel *chan;
+
+       /* Get the selected action, exit if none are selected 
+        */
+       act = G.saction->action;
+       if (!act)
+               return;
+
+       /* Loop through the channels and set the beziers
+        * of the selected keys based on the integer code
+        */
+       for (chan = act->chanbase.first; chan; chan=chan->next){
+               sethandles_ipo_keys(chan->ipo, code);
+       }
+
+       /* Clean up and redraw stuff
+        */
+       remake_action_ipos (act);
+       allspace(REMAKEIPO, 0);
+       allqueue(REDRAWACTION, 0);
+       allqueue(REDRAWIPO, 0);
+       allqueue(REDRAWNLA, 0);
+}
+
+
 void winqreadactionspace(unsigned short event, short val, char ascii)
 {
        SpaceAction *saction;
@@ -1375,6 +1404,16 @@ void winqreadactionspace(unsigned short event, short val, char ascii)
                                allqueue (REDRAWIPO, 0);
                        }
                        break;
+
+                       /*** set the Ipo handles ***/
+               case VKEY:
+                       sethandles_actionchannel_keys(HD_VECT);
+                       break;
+               case HKEY:
+                       if(G.qual & LR_SHIFTKEY) sethandles_actionchannel_keys(HD_AUTO);
+                       else sethandles_actionchannel_keys(HD_ALIGN);
+                       break;
                case BKEY:
                        borderselect_action();
                        break;
index ba9a9ae8e4c1f2be9b4bd636d62ad5439fb1499d..c5923cbe83c91dc63698170c16e7167a16d85fa9 100644 (file)
@@ -2663,76 +2663,301 @@ void mouse_select_ipo()
        }
 }
 
-void sethandles_ipo(int code)
+int icu_keys_bezier_loop(IpoCurve *icu,
+                         int (*bezier_function)(BezTriple *),
+                         void (ipocurve_function)(struct IpoCurve *icu)) 
 {
-       /* code==1: set autohandle */
-       /* code==2: set vectorhandle */
-       /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
+    /*  This loops through the beziers in the Ipocurve, and executes 
+     *  the generic user provided 'bezier_function' on each one. 
+     *  Optionally executes the generic function ipocurve_function on the 
+     *  IPO curve after looping (eg. calchandles_ipocurve)
+     */
+
+    int b;
+    BezTriple *bezt;
+
+    b    = icu->totvert;
+    bezt = icu->bezt;
+
+    /* if bezier_function has been specified
+     * then loop through each bezier executing
+     * it.
+     */
+
+    if (bezier_function != NULL) {
+        while(b--) {
+            /* exit with return code 1 if the bezier function 
+             * returns 1 (good for when you are only interested
+             * in finding the first bezier that
+             * satisfies a condition).
+             */
+            if (bezier_function(bezt)) return 1;
+            bezt++;
+        }
+    }
+
+    /* if ipocurve_function has been specified 
+     * then execute it
+     */
+    if (ipocurve_function != NULL)
+        ipocurve_function(icu);
+
+    return 0;
+
+}
+
+int ipo_keys_bezier_loop(Ipo *ipo,
+                         int (*bezier_function)(BezTriple *),
+                         void (ipocurve_function)(struct IpoCurve *icu))
+{
+    /*  This loops through the beziers that are attached to
+     *  the selected keys on the Ipocurves of the Ipo, and executes 
+     *  the generic user provided 'bezier_function' on each one. 
+     *  Optionally executes the generic function ipocurve_function on a 
+     *  IPO curve after looping (eg. calchandles_ipocurve)
+     */
+
+    IpoCurve *icu;
+
+    /* Loop through each curve in the Ipo
+     */
+    for (icu=ipo->curve.first; icu; icu=icu->next){
+        if (icu_keys_bezier_loop(icu,bezier_function, ipocurve_function))
+            return 1;
+    }
+
+    return 0;
+}
+
+int selected_bezier_loop(int (*looptest)(EditIpo *),
+                         int (*bezier_function)(BezTriple *),
+                         void (ipocurve_function)(struct IpoCurve *icu))
+{
+       /*  This loops through the beziers that are attached to
+        *  selected keys in editmode in the IPO window, and executes 
+        *  the generic user-provided 'bezier_function' on each one 
+        *  that satisfies the 'looptest' function. Optionally executes
+        *  the generic function ipocurve_function on a IPO curve
+        *  after looping (eg. calchandles_ipocurve)
+        */
+
        EditIpo *ei;
        BezTriple *bezt;
-       int a, b, ok=0;
+       int a, b;
 
-       if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+       /* Get the first Edit Ipo from the selected Ipos
+        */
+       ei= G.sipo->editipo;
 
-       if(code==1 || code==2) {
-               ei= G.sipo->editipo;
-               for(a=0; a<G.sipo->totipo; a++, ei++) {
-                       if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt) {
-                               bezt= ei->icu->bezt;
-                               b= ei->icu->totvert;
+       /* Loop throught all of the selected Ipo's
+        */
+       for(a=0; a<G.sipo->totipo; a++, ei++) {
+               /* Do a user provided test on the Edit Ipo
+                * to determine whether we want to process it
+                */
+               if (looptest(ei)) {
+                       /* Loop through the selected
+                        * beziers on the Edit Ipo
+                        */
+                       bezt = ei->icu->bezt;
+                       b    = ei->icu->totvert;
+                       
+                       /* if bezier_function has been specified
+                        * then loop through each bezier executing
+                        * it.
+                        */
+                       if (bezier_function != NULL) {
                                while(b--) {
-                                       if(bezt->f1 || bezt->f3) {
-                                               if(bezt->f1) bezt->h1= code;
-                                               if(bezt->f3) bezt->h2= code;
-                                               
-                                               if(bezt->h1!=bezt->h2) {
-                                                       if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
-                                                       if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
-                                               }
-                                       }
+                                       /* exit with return code 1 if the bezier function 
+                                        * returns 1 (good for when you are only interested
+                                        * in finding the first bezier that
+                                        * satisfies a condition).
+                                        */
+                                       if (bezier_function(bezt)) return 1;
                                        bezt++;
                                }
-                               calchandles_ipocurve(ei->icu);
                        }
+
+                       /* if ipocurve_function has been specified 
+                        * then execute it
+                        */
+                       if (ipocurve_function != NULL)
+                               ipocurve_function(ei->icu);
                }
+               /* nufte flourdje zim ploopydu <-- random dutch looking comment ;) */
        }
-       else {
-               /* is er 1 handle NIET vrij: alles vrijmaken, else ALIGNED maken */
-               
-               ei= G.sipo->editipo;
-               for(a=0; a<G.sipo->totipo; a++, ei++) {
-                       if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt) {
-                               bezt= ei->icu->bezt;
-                               b= ei->icu->totvert;
-                               while(b--) {
-                                       if(bezt->f1 && bezt->h1) ok= 1;
-                                       if(bezt->f3 && bezt->h2) ok= 1;
-                                       if(ok) break;
-                                       bezt++;
-                               }
-                       }
+
+       return 0;
+}
+
+int set_bezier_auto(BezTriple *bezt) 
+{
+       /* Sets the selected bezier handles to type 'auto' 
+        */
+
+       /* is a handle selected? If so
+        * set it to type auto
+        */
+       if(bezt->f1 || bezt->f3) {
+               if(bezt->f1) bezt->h1= 1; /* the secret code for auto */
+               if(bezt->f3) bezt->h2= 1;
+
+               /* if the handles are not of the same type, set them
+                * to type free
+                */
+               if(bezt->h1!=bezt->h2) {
+                       if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
+                       if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
                }
-               if(ok) ok= HD_FREE;
-               else ok= HD_ALIGN;
-               
-               ei= G.sipo->editipo;
-               for(a=0; a<G.sipo->totipo; a++, ei++) {
-                       if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt) {
-                               bezt= ei->icu->bezt;
-                               b= ei->icu->totvert;
-                               while(b--) {
-                                       if(bezt->f1) bezt->h1= ok;
-                                       if(bezt->f3 ) bezt->h2= ok;
+       }
+       return 0;
+}
+
+int set_bezier_vector(BezTriple *bezt) 
+{
+       /* Sets the selected bezier handles to type 'vector' 
+        */
+
+       /* is a handle selected? If so
+        * set it to type vector
+        */
+       if(bezt->f1 || bezt->f3) {
+               if(bezt->f1) bezt->h1= 2; /* the code for vector */
+               if(bezt->f3) bezt->h2= 2;
+    
+               /* if the handles are not of the same type, set them
+                * to type free
+                */
+               if(bezt->h1!=bezt->h2) {
+                       if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
+                       if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
+               }
+       }
+       return 0;
+}
+
+int bezier_isfree(BezTriple *bezt) 
+{
+       /* queries whether the handle should be set
+        * to type 'free' (I think)
+        */
+       if(bezt->f1 && bezt->h1) return 1;
+       if(bezt->f3 && bezt->h2) return 1;
+       return 0;
+}
+
+int set_bezier_free(BezTriple *bezt) 
+{
+       /* Sets selected bezier handles to type 'free' 
+        */
+       if(bezt->f1) bezt->h1= HD_FREE;
+       if(bezt->f3) bezt->h2= HD_FREE;
+       return 0;
+}
+
+int set_bezier_align(BezTriple *bezt) 
+{
+       /* Sets selected bezier handles to type 'align' 
+        */
+       if(bezt->f1) bezt->h1= HD_ALIGN;
+       if(bezt->f3) bezt->h2= HD_ALIGN;
+       return 0;
+}
+
+int vis_edit_icu_bez(EditIpo *ei) {
+       /* A 4 part test for an EditIpo :
+        *   is it a) visible
+        *         b) in edit mode
+        *         c) does it contain an Ipo Curve
+        *         d) does that ipo curve have a bezier
+        *
+        * (The reason why I don't just use the macro
+        * is I need a pointer to a function.)
+        */
+       return ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt);
+}
+
+void sethandles_ipo_keys(Ipo *ipo, int code)
+{
+       /* this function lets you set bezier handles all to
+        * one type for some Ipo's (e.g. with hotkeys through
+        * the action window).
+        */ 
+
+       /* code==1: set autohandle */
+       /* code==2: set vectorhandle */
+       /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
        
-                                       bezt++;
-                               }
-                               calchandles_ipocurve(ei->icu);
-                       }
+       switch(code) {
+       case 1:
+               /*** Set to auto ***/
+               ipo_keys_bezier_loop(ipo, set_bezier_auto,
+                                                        calchandles_ipocurve);
+               break;
+       case 2:
+               /*** Set to vector ***/
+               ipo_keys_bezier_loop(ipo, set_bezier_vector,
+                         calchandles_ipocurve);
+               break;
+       default:
+               if ( ipo_keys_bezier_loop(ipo, bezier_isfree, NULL) ) {
+                       /*** Set to free ***/
+                       ipo_keys_bezier_loop(ipo, set_bezier_free,
+                           calchandles_ipocurve);
+               }
+               else {
+                       /*** Set to align ***/
+                       ipo_keys_bezier_loop(ipo, set_bezier_align,
+                           calchandles_ipocurve);
                }
+               break;
        }
+
+
+}
+
+void sethandles_ipo(int code)
+{
+       /* this function lets you set bezier handles all to
+        * one type for some selected keys in edit mode in the
+        * IPO window (e.g. with hotkeys)
+        */ 
+
+       /* code==1: set autohandle */
+       /* code==2: set vectorhandle */
+       /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
+
+       if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+
+       switch(code) {
+       case 1:
+               /*** Set to auto ***/
+               selected_bezier_loop(vis_edit_icu_bez, set_bezier_auto,
+                         calchandles_ipocurve);
+               break;
+       case 2:
+               /*** Set to vector ***/
+               selected_bezier_loop(vis_edit_icu_bez, set_bezier_vector,
+                         calchandles_ipocurve);
+               break;
+       default:
+               if (selected_bezier_loop(vis_edit_icu_bez, bezier_isfree, NULL) ) {
+                       /*** Set to free ***/
+                       selected_bezier_loop(vis_edit_icu_bez, set_bezier_free,
+                                                                calchandles_ipocurve);
+               }
+               else {
+                       /*** Set to align ***/
+                       selected_bezier_loop(vis_edit_icu_bez, set_bezier_align,
+                                                                calchandles_ipocurve);
+               }
+               break;
+       }
+
        editipo_changed(G.sipo, 1);
 }
 
+
 void set_ipotype()
 {
        EditIpo *ei;