Autohandles in Ipo Window still could overshoot. Added a new clamping to
authorTon Roosendaal <ton@blender.org>
Sun, 23 Oct 2005 21:36:24 +0000 (21:36 +0000)
committerTon Roosendaal <ton@blender.org>
Sun, 23 Oct 2005 21:36:24 +0000 (21:36 +0000)
ensure the handles never result in a curve that goes beyond the neighbour
control points.

http://www.blender.org/cms/Animation_Curve_Handle.717.0.html

source/blender/blenkernel/intern/curve.c
source/blender/makesdna/DNA_curve_types.h
source/blender/src/editipo_mods.c
source/blender/src/header_ipo.c
source/blender/src/space.c

index 7cf12b807dd5336ad398af1e07a3ecbcdc26a9b7..9cdc8be9e57ba3aeee686a3567cd667c1bb364d1 100644 (file)
@@ -1980,7 +1980,8 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
                vz= dz1/len2 + dz/len1;
                len= 2.5614f*(float)sqrt(vx*vx + vy*vy + vz*vz);
                if(len!=0.0f) {
-               
+                       int leftviolate=0, rightviolate=0;      /* for mode==2 */
+                       
                        if(len1>5.0f*len2) len1= 5.0f*len2;     
                        if(len2>5.0f*len1) len2= 5.0f*len1;
                        
@@ -1996,6 +1997,20 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
                                        if( (ydiff1<=0.0 && ydiff2<=0.0) || (ydiff1>=0.0 && ydiff2>=0.0) ) {
                                                bezt->vec[0][1]= bezt->vec[1][1];
                                        }
+                                       else {                                          // handles should not be beyond y coord of two others
+                                               if(ydiff1<=0.0) { 
+                                                       if(prev->vec[1][1] > bezt->vec[0][1]) {
+                                                               bezt->vec[0][1]= prev->vec[1][1]; 
+                                                               leftviolate= 1;
+                                                       }
+                                               }
+                                               else {
+                                                       if(prev->vec[1][1] < bezt->vec[0][1]) {
+                                                               bezt->vec[0][1]= prev->vec[1][1]; 
+                                                               leftviolate= 1;
+                                                       }
+                                               }
+                                       }
                                }
                        }
                        if(bezt->h2==HD_AUTO) {
@@ -2010,6 +2025,41 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
                                        if( (ydiff1<=0.0 && ydiff2<=0.0) || (ydiff1>=0.0 && ydiff2>=0.0) ) {
                                                bezt->vec[2][1]= bezt->vec[1][1];
                                        }
+                                       else {                                          // handles should not be beyond y coord of two others
+                                               if(ydiff1<=0.0) { 
+                                                       if(next->vec[1][1] < bezt->vec[2][1]) {
+                                                               bezt->vec[2][1]= next->vec[1][1]; 
+                                                               rightviolate= 1;
+                                                       }
+                                               }
+                                               else {
+                                                       if(next->vec[1][1] > bezt->vec[2][1]) {
+                                                               bezt->vec[2][1]= next->vec[1][1]; 
+                                                               rightviolate= 1;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       if(leftviolate || rightviolate) {       /* align left handle */
+                               float h1[3], h2[3];
+                               
+                               VecSubf(h1, p2-3, p2);
+                               VecSubf(h2, p2, p2+3);
+                               len1= Normalise(h1);
+                               len2= Normalise(h2);
+                               
+                               vz= INPR(h1, h2);
+                               
+                               if(leftviolate) {
+                                       *(p2+3)= *(p2)   - vz*len2*h1[0];
+                                       *(p2+4)= *(p2+1) - vz*len2*h1[1];
+                                       *(p2+5)= *(p2+2) - vz*len2*h1[2];
+                               }
+                               else {
+                                       *(p2-3)= *(p2)   + vz*len1*h2[0];
+                                       *(p2-2)= *(p2+1) + vz*len1*h2[1];
+                                       *(p2-1)= *(p2+2) + vz*len1*h2[2];
                                }
                        }
                        
index 2078875215f24c659e69c71aa2280a3fe809eed5..b5ed8c9102afc54aea990bc610521b96846eef42 100644 (file)
@@ -237,10 +237,11 @@ typedef struct IpoCurve {
 #define CU_CYCLIC              1
 
 /* h1 h2 (beztriple) */
-#define HD_FREE                0
-#define HD_AUTO                1
-#define HD_VECT                2
-#define HD_ALIGN       3
+#define HD_FREE                        0
+#define HD_AUTO                        1
+#define HD_VECT                        2
+#define HD_ALIGN               3
+#define HD_AUTO_ANIM   4
 
 /* *************** CHARINFO **************** */
 
index 91698300ef5f88ceb905c180de21968f1b15dbf5..468e49b3ec8b541d51df33663647ab55804947ef 100644 (file)
@@ -588,17 +588,17 @@ void sethandles_ipo(int code)
        if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
 
        switch(code) {
-       case 1:
+       case HD_AUTO:
                /*** Set to auto ***/
                selected_bezier_loop(vis_edit_icu_bez, set_bezier_auto,
                          calchandles_ipocurve);
                break;
-       case 2:
+       case HD_VECT:
                /*** Set to vector ***/
                selected_bezier_loop(vis_edit_icu_bez, set_bezier_vector,
                          calchandles_ipocurve);
                break;
-       case 4:
+       case HD_AUTO_ANIM:
                /* set to enforce autohandles to be horizontal on extremes */
                ipo_curves_auto_horiz();
                
index 1508c61830dd32a94927fb6feb71ef934bc5560e..73439ec22bf62657f258f6fdefa124b33cc71796 100644 (file)
@@ -390,6 +390,9 @@ static void do_ipo_editmenu_handlemenu(void *arg, int event)
        case 3:
                sethandles_ipo(HD_VECT);
                break;
+       case 4:
+               sethandles_ipo(HD_AUTO_ANIM);
+               break;
        }
 }
 
@@ -402,6 +405,7 @@ static uiBlock *ipo_editmenu_handlemenu(void *arg_unused)
        uiBlockSetButmFunc(block, do_ipo_editmenu_handlemenu, NULL);
 
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto|Shift H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Clamped|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Aligned|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Free|H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector|V", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
@@ -531,6 +535,10 @@ static void do_ipo_editmenu(void *arg, int event)
        case 6:
                /*IPO Editmode*/
                set_editflag_editipo();
+               break;
+       case 7:
+               sethandles_ipo(HD_AUTO_ANIM);
+               break;
        }
 }
 
@@ -587,9 +595,10 @@ static uiBlock *ipo_editmenu(void *arg_unused)
        uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete|X", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
        uiDefIconTextBlockBut(block, ipo_editmenu_joinmenu, NULL, ICON_RIGHTARROW_THIN, "Join", 0, yco-=20, 120, 19, "");       
 
+       uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Clamped Handles|ALT H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, "");
+       
        if (!G.sipo->showkey){
-               uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
-               
                uiDefIconTextBlockBut(block, ipo_editmenu_extendmenu, NULL, ICON_RIGHTARROW_THIN, "Extend Mode", 0, yco-=20, 120, 19, "");      
                uiDefIconTextBlockBut(block, ipo_editmenu_intpolmenu, NULL, ICON_RIGHTARROW_THIN, "Interpolation Mode", 0, yco-=20, 120, 20, "");
                if(ei != NULL && (ei->flag & IPO_EDIT))
index db2ae93cb0add386b04e052e1d5f2c964c4346f7..17722bb090edf81ff199fd846a10c6e78f636831 100644 (file)
@@ -2076,7 +2076,7 @@ static void winqreadipospace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                        break;
                case HKEY:
                        if(G.qual==LR_ALTKEY)
-                               sethandles_ipo(4);              // tsk tsk ton!
+                               sethandles_ipo(HD_AUTO_ANIM);
                        if(G.qual==LR_SHIFTKEY)
                                sethandles_ipo(HD_AUTO);
                        else if(G.qual==0)