For long on the wanna-have list;
authorTon Roosendaal <ton@blender.org>
Sun, 10 Jul 2005 12:50:14 +0000 (12:50 +0000)
committerTon Roosendaal <ton@blender.org>
Sun, 10 Jul 2005 12:50:14 +0000 (12:50 +0000)
Ipocurves with "Auto" handles now have option to remain horizontal on the
extrema (tops & valleys). Use ALT+H to set this per selected curve.
Note this is a per-curve feature, not per-handle.

If it works satisfying I can check on making this the default new added
curve.

source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/ipo.c
source/blender/makesdna/DNA_ipo_types.h
source/blender/src/editipo.c
source/blender/src/space.c

index 5078c61c7887c35e2341c15750c5fb0870fa39f9..4f2b5eac15c28e0add4d6101cb9f35a623df2a9d 100644 (file)
@@ -166,15 +166,17 @@ bAction* copy_action(bAction *src)
 
 /* ************************ Pose channels *************** */
 
+/* usually used within a loop, so we got a N^2 slowdown */
 bPoseChannel *get_pose_channel(const bPose *pose, const char *name)
 {
        bPoseChannel *chan;
 
        if(pose==NULL) return NULL;
        
-       for (chan=pose->chanbase.first; chan; chan=chan->next){
-               if (!strcmp (chan->name, name))
-                       return chan;
+       for (chan=pose->chanbase.first; chan; chan=chan->next) {
+               if(chan->name[0] == name[0])
+                       if (!strcmp (chan->name, name))
+                               return chan;
        }
 
        return NULL;
index c118a109b8fc605f106090b7bacfa31b5ee42d43..c53a70156c4af72ce9b6ae57af76c7e855bcd53c 100644 (file)
@@ -1936,8 +1936,8 @@ void makeBevelList(Object *ob)
  *             1: nothing,  1:auto,  2:vector,  3:aligned
  */
 
-
-void calchandleNurb(BezTriple *bezt,BezTriple *prev, BezTriple *next, int mode)
+/* mode: is not zero when IpoCurve, is 2 when forced horizontal for autohandles */
+void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
 {
        float *p1,*p2,*p3,pt[3];
        float dx1,dy1,dz1,dx,dy,dz,vx,vy,vz,len,len1,len2;
@@ -2006,13 +2006,30 @@ void calchandleNurb(BezTriple *bezt,BezTriple *prev, BezTriple *next, int mode)
                                *(p2-3)= *p2-vx*len1;
                                *(p2-2)= *(p2+1)-vy*len1;
                                *(p2-1)= *(p2+2)-vz*len1;
+                               
+                               if(mode==2 && next && prev) {   // keep horizontal if extrema
+                                       float ydiff1= prev->vec[1][1] - bezt->vec[1][1];
+                                       float ydiff2= next->vec[1][1] - bezt->vec[1][1];
+                                       if( (ydiff1<0.0 && ydiff2<0.0) || (ydiff1>0.0 && ydiff2>0.0) ) {
+                                               bezt->vec[0][1]= bezt->vec[1][1];
+                                       }
+                               }
                        }
                        if(bezt->h2==HD_AUTO) {
                                len2/=len;
                                *(p2+3)= *p2+vx*len2;
                                *(p2+4)= *(p2+1)+vy*len2;
                                *(p2+5)= *(p2+2)+vz*len2;
+                               
+                               if(mode==2 && next && prev) {   // keep horizontal if extrema
+                                       float ydiff1= prev->vec[1][1] - bezt->vec[1][1];
+                                       float ydiff2= next->vec[1][1] - bezt->vec[1][1];
+                                       if( (ydiff1<0.0 && ydiff2<0.0) || (ydiff1>0.0 && ydiff2>0.0) ) {
+                                               bezt->vec[2][1]= bezt->vec[1][1];
+                                       }
+                               }
                        }
+                       
                }
        }
 
@@ -2037,6 +2054,7 @@ void calchandleNurb(BezTriple *bezt,BezTriple *prev, BezTriple *next, int mode)
        len1= VecLenf(p2, p2-3);
        if(len1==0.0) len1=1.0;
        if(len2==0.0) len2=1.0;
+
        if(bezt->f1 & 1) { /* order of calculation */
                if(bezt->h2==HD_ALIGN) {        /* aligned */
                        len= len2/len1;
@@ -2224,7 +2242,8 @@ void sethandlesNurb(short code)
 {
        /* code==1: set autohandle */
        /* code==2: set vectorhandle */
-       /* if code==3 (HD_ALIGN) it toggle, vectorhandles become HD_FREE */
+       /* code==3 (HD_ALIGN) it toggle, vectorhandles become HD_FREE */
+       /* code==4: sets icu flag to become IPO_AUTO_HORIZ, horizontal extremes on auto-handles */
        Nurb *nu;
        BezTriple *bezt;
        short a, ok=0;
index a03eb0e35c40f186d875571f1d3ef1df84d8bd6a..d7cde3deae73efbb06e53d148041281495facce9 100644 (file)
@@ -404,8 +404,11 @@ void calchandles_ipocurve(IpoCurve *icu)
                if(bezt->vec[0][0]>bezt->vec[1][0]) bezt->vec[0][0]= bezt->vec[1][0];
                if(bezt->vec[2][0]<bezt->vec[1][0]) bezt->vec[2][0]= bezt->vec[1][0];
 
-               calchandleNurb(bezt, prev, next, 1);    /* 1==special autohandle */
-
+               if(icu->flag & IPO_AUTO_HORIZ) 
+                       calchandleNurb(bezt, prev, next, 2);    /* 2==special autohandle && keep extrema horizontal */
+               else
+                       calchandleNurb(bezt, prev, next, 1);    /* 1==special autohandle */
+       
                prev= bezt;
                if(a==1) {
                        next= 0;
index 352a2589c14f1c17eac2f779318b79bc014bcc52..c658d40db79034efc7926be6df7f818967ae78c8 100644 (file)
@@ -320,10 +320,10 @@ typedef short IPO_Channel;
 #define CO_ROLL                9
 */
 
-/* these are ipo-specific */
+/* these are IpoCurve specific */
 /* **************** IPO ********************* */
 
-/* vartype */
+/* icu->vartype */
 #define IPO_CHAR               0
 #define IPO_SHORT              1
 #define IPO_INT                        2
@@ -331,33 +331,34 @@ typedef short IPO_Channel;
 #define IPO_FLOAT              4
 #define IPO_DOUBLE             5
 #define IPO_FLOAT_DEGR 6
-/* very special case, in keys */
+       /* very special case, in keys */
 #define IPO_BEZTRIPLE  100
 #define IPO_BPOINT             101
 
-
+/* icu->vartype */
 #define IPO_BITS               16
 #define IPO_CHAR_BIT   16
 #define IPO_SHORT_BIT  17
 #define IPO_INT_BIT            18
 
-/* ipo */
+/* icu->ipo */
 #define IPO_CONST              0
 #define IPO_LIN                        1
 #define IPO_BEZ                        2
 #define IPO_MIXED              3
 
-/* extrap */
+/* icu->extrap */
 #define IPO_HORIZ              0
 #define IPO_DIR                        1
 #define IPO_CYCL               2
 #define IPO_CYCLX              3
 
-/* flag */
+/* icu->flag */
 #define IPO_VISIBLE            1
 #define IPO_SELECT             2
 #define IPO_EDIT               4
 #define IPO_LOCK               8
+#define IPO_AUTO_HORIZ 16
 
 #endif
 
index d26475340167ffa34e4eb442604e96ed69ff6387..63e48d1d760fca34f1b84fa0c710a7322bdc000a 100644 (file)
@@ -2926,6 +2926,27 @@ void sethandles_ipo_keys(Ipo *ipo, int code)
 
 }
 
+static void ipo_curves_auto_horiz(void)
+{
+    EditIpo *ei;
+       int a, set= 1;
+       
+       ei= G.sipo->editipo;
+       for(a=0; a<G.sipo->totipo; a++, ei++) {
+               if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu)
+                       if(ei->flag & IPO_AUTO_HORIZ) set= 0;
+       }
+       
+       ei= G.sipo->editipo;
+       for(a=0; a<G.sipo->totipo; a++, ei++) {
+               if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
+                       if(set) ei->flag |= IPO_AUTO_HORIZ;
+                       else ei->flag &= ~IPO_AUTO_HORIZ;
+               }
+       }
+       update_editipo_flags();
+}
+
 void sethandles_ipo(int code)
 {
        /* this function lets you set bezier handles all to
@@ -2950,6 +2971,11 @@ void sethandles_ipo(int code)
                selected_bezier_loop(vis_edit_icu_bez, set_bezier_vector,
                          calchandles_ipocurve);
                break;
+       case 4:
+               /* set to enforce autohandles to be horizontal on extremes */
+               ipo_curves_auto_horiz();
+               
+               break;
        default:
                if (selected_bezier_loop(vis_edit_icu_bez, bezier_isfree, NULL) ) {
                        /*** Set to free ***/
@@ -3156,7 +3182,7 @@ void del_ipo()
        
        if( okee("Erase selected")==0 ) return;
 
-       // eerste doorloop, kunnen hele stukken weg
+       // first round, can we delete entire parts
        ei= G.sipo->editipo;
        for(a=0; a<G.sipo->totipo; a++, ei++) {
        
@@ -3197,7 +3223,7 @@ void del_ipo()
                }
        }
        
-       // tweede doorloop, kleine stukken weg: alleen curves 
+       // 2nd round, small parts: just curves 
        ei= G.sipo->editipo;
        for(b=0; b<G.sipo->totipo; b++, ei++) {
                if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
index 0b29c47f2b1dd0a6ff3bc7b5c25296d2711fd782..906f4c61eee3e75d9c05e77a4dda680101268518 100644 (file)
@@ -2015,9 +2015,11 @@ static void winqreadipospace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                transform_ipo('g');
                        break;
                case HKEY:
-                       if((G.qual==LR_SHIFTKEY))
+                       if(G.qual==LR_ALTKEY)
+                               sethandles_ipo(4);              // tsk tsk ton!
+                       if(G.qual==LR_SHIFTKEY)
                                sethandles_ipo(HD_AUTO);
-                       else if((G.qual==0))
+                       else if(G.qual==0)
                                sethandles_ipo(HD_ALIGN);
                        break;
                case JKEY: