* Shrink/Fatten for bevelled curves
authorMatt Ebb <matt@mke3.net>
Sun, 13 Aug 2006 07:37:51 +0000 (07:37 +0000)
committerMatt Ebb <matt@mke3.net>
Sun, 13 Aug 2006 07:37:51 +0000 (07:37 +0000)
This is a much faster and easier way to give a bevelled curve a taper, without
using taper curves. Each point on a curve now has a 'radius' value that you can
shrink and fatten using Alt S, which will influence the taper when the curve is
bevelled (either with a bevob, or with front/back turned off and a bevel dept
set). Alt S shrinks and fattens the selected points in an interactive transform,
and you can set an absolute radius for selected points with 'Set Radius' in the
curve specials menu.

See demo: http://mke3.net/blender/etc/curve_shrinkfatten-h264.mov

This can be a quick way to create revolved surfaces (eg.
http://mke3.net/blender/etc/wineglass-h264.mov ) and it would be very
interesting to use this radius value in other tools, such as a 'freehand curve'
tool that would let you draw a curve freehand, with the radius affected by pen
pressure, or even using the radius at each point to control curve guides for
particles more precisely, rather than the continous maxdist.

12 files changed:
source/blender/blenkernel/intern/displist.c
source/blender/include/BIF_transform.h
source/blender/include/transform.h
source/blender/makesdna/DNA_curve_types.h
source/blender/src/buttons_editing.c
source/blender/src/drawview.c
source/blender/src/editcurve.c
source/blender/src/editobject.c
source/blender/src/space.c
source/blender/src/transform.c
source/blender/src/transform_conversions.c
source/blender/src/transform_generics.c

index 2930203e0dae76d6bbda5fd9202a14d269ab37a7..5ae7ffa6b3638330cd163f50eff255fd1c5fbda9 100644 (file)
@@ -821,17 +821,17 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase)
                                /* count */
                                len= 0;
                                a= nu->pntsu-1;
-                               if(nu->flagu & 1) a++;
+                               if(nu->flagu & CU_CYCLIC) a++;
 
                                prevbezt= nu->bezt;
                                bezt= prevbezt+1;
                                while(a--) {
-                                       if(a==0 && (nu->flagu & 1)) bezt= nu->bezt;
+                                       if(a==0 && (nu->flagu & CU_CYCLIC)) bezt= nu->bezt;
                                        
                                        if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) len++;
                                        else len+= resolu;
                                        
-                                       if(a==0 && (nu->flagu & 1)==0) len++;
+                                       if(a==0 && (nu->flagu & CU_CYCLIC)==0) len++;
                                        
                                        prevbezt= bezt;
                                        bezt++;
@@ -1119,6 +1119,133 @@ void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase)
        }
 }
 
+/* calculates a bevel width (radius) for a particular subdivided curve part,
+ * based on the radius value of the surrounding CVs */
+static float calc_manual_taper(Curve *cu, Nurb *nu, int cursubdiv)
+{
+       BezTriple *bezt, *beztfirst, *beztlast, *beztnext, *beztprev;
+       BPoint *bp, *bpfirst, *bplast;
+       int resolu;
+       float prevrad=0.0, nextrad=0.0, rad=0.0, ratio=0.0;
+       int vectseg=0, subdivs=0;
+       
+       if((nu==NULL) || (nu->pntsu<=1)) return 1.0; 
+       bezt= nu->bezt;
+       bp = nu->bp;
+       
+       if(G.rendering && cu->resolu_ren!=0) resolu= cu->resolu_ren;
+       else resolu= nu->resolu;
+       
+       if(((nu->type & 7)==CU_BEZIER) && (bezt != NULL)) {
+               beztfirst = nu->bezt;
+               beztlast = nu->bezt + (nu->pntsu - 1);
+               
+               /* loop through the CVs to end up with a pointer to the CV before the subdiv in question, and a ratio
+                * of how far that subdiv is between this CV and the next */
+               while(bezt<=beztlast) {
+                       beztnext = bezt+1;
+                       beztprev = bezt-1;
+                       vectseg=0;
+                       
+                       if (subdivs==cursubdiv) {
+                               ratio= 0.0;
+                               break;
+                       }
+
+                       /* check to see if we're looking at a vector segment (no subdivisions) */
+                       if (nu->flagu & CU_CYCLIC) {
+                               if (bezt == beztfirst) {
+                                       if ((beztlast->h2==HD_VECT) && (bezt->h1==HD_VECT)) vectseg = 1;
+                               } else {
+                                       if ((beztprev->h2==HD_VECT) && (bezt->h1==HD_VECT)) vectseg = 1;
+                               }
+                       } else if ((bezt->h2==HD_VECT) && (beztnext->h1==HD_VECT)) vectseg = 1;
+                       
+                       
+                       if (vectseg==0) {
+                               /* if it's NOT a vector segment, check to see if the subdiv falls within the segment */
+                               subdivs += resolu;
+                               
+                               if (cursubdiv < subdivs) {
+                                       ratio = 1.0 - ((subdivs - cursubdiv)/(float)resolu);
+                                       break;
+                               }
+                       } else {
+                               /* must be a vector segment.. loop again! */
+                               subdivs += 1;
+                       } 
+                       
+                       bezt++;
+               }
+               
+               /* Now we have a nice bezt pointer to the CV that we want. But cyclic messes it up, so must correct for that..
+                * (cyclic goes last-> first -> first+1 -> first+2 -> ...) */
+               if (nu->flagu & CU_CYCLIC) {
+                       if (bezt == beztfirst) bezt = beztlast;
+                       else bezt--;
+               }
+                
+               /* find the radii at the bounding CVs and interpolate between them based on ratio */
+               rad = prevrad = bezt->radius;
+               
+               if ((bezt == beztlast) && (nu->flagu & CU_CYCLIC)) { /* loop around */
+                       bezt= beztfirst;
+               } else if (bezt != beztlast) {
+                       bezt++;
+               }
+               nextrad = bezt->radius;
+               
+       }
+       else if( ( ((nu->type & 7)==CU_NURBS) || ((nu->type & 7)==CU_POLY)) && (bp != NULL)) {
+               /* follows similar algo as for bezt above */
+               bpfirst = nu->bp;
+               bplast = nu->bp + (nu->pntsu - 1);
+               
+               if ((nu->type & 7)==CU_POLY) resolu=1;
+               
+               while(bp<=bplast) {
+                       if (subdivs==cursubdiv) {
+                               ratio= 0.0;
+                               break;
+                       }
+                       
+                       subdivs += resolu;
+
+                       if (cursubdiv < subdivs) {
+                               ratio = 1.0 - ((subdivs - cursubdiv)/(float)resolu);
+                               break;
+                       }
+
+                       bp++;
+               }
+               
+               if ( ((nu->type & 7)==CU_NURBS) && (nu->flagu & CU_CYCLIC)) {
+                       if (bp == bplast) bp = bpfirst;
+                       else bp++;
+               }
+               
+               rad = prevrad = bp->radius;
+               
+               if ((bp == bplast) && (nu->flagu & CU_CYCLIC)) { /* loop around */
+                       bp= bpfirst;
+               } else if (bp != bplast) {
+                       bp++;
+               }
+               nextrad = bp->radius;
+               
+       }
+       
+       
+       if (nextrad != prevrad) {
+               /* smooth interpolation */
+               rad = prevrad + (nextrad-prevrad)*(3.0f*ratio*ratio - 2.0f*ratio*ratio*ratio);
+       }
+
+       if (rad > 0.0) 
+               return rad;
+       else
+               return 1.0;
+}
 
 /* taper rules:
   - only 1 curve
@@ -1389,7 +1516,7 @@ void makeDispListCurveTypes(Object *ob, int forOrco)
 
                makeBevelList(ob);
 
-                       /* If curve has no bevel will return nothing */
+               /* If curve has no bevel will return nothing */
                makebevelcurve(ob, &dlbev);
 
                /* no bevel or extrude, and no width correction? */
@@ -1461,7 +1588,12 @@ void makeDispListCurveTypes(Object *ob, int forOrco)
                                                        /* for each point of poly make a bevel piece */
                                                bevp= (BevPoint *)(bl+1);
                                                for(a=0; a<bl->nr; a++,bevp++) {
-                                                       float fac = calc_taper(cu->taperobj, a, bl->nr);
+                                                       float fac;
+                                                       if (cu->taperobj==NULL) {
+                                                               fac = calc_manual_taper(cu, nu, a);
+                                                       } else {
+                                                               fac = calc_taper(cu->taperobj, a, bl->nr);
+                                                       }
                                                        
                                                        if (bevp->f1) {
                                                                dl->bevelSplitFlag[a>>5] |= 1<<(a&0x1F);
index fc67aaf0f9b399d64e49463319f5481ddbd5cc8b..2582920b697d66a31db57bf8814bebf88f4d5aed 100755 (executable)
@@ -52,6 +52,7 @@
 #define TFM_MIRROR                     14
 #define TFM_BONESIZE           15
 #define TFM_BONE_ENVELOPE      16
+#define TFM_CURVE_SHRINKFATTEN         17
 
 /* TRANSFORM CONTEXTS */
 #define CTX_NONE                       0
index ab0b16e46a4b77a8623cd34cf2fa3c22e93cda38..c17d920693f917552eb872309c4fcbd79dbd071b 100755 (executable)
@@ -267,6 +267,9 @@ int ShrinkFatten(TransInfo *t, short mval[2]);
 void initTilt(TransInfo *t);
 int Tilt(TransInfo *t, short mval[2]);
 
+void initCurveShrinkFatten(TransInfo *t);
+int CurveShrinkFatten(TransInfo *t, short mval[2]);
+
 void initTrackball(TransInfo *t);
 int Trackball(TransInfo *t, short mval[2]);
 
index 4d0cca68ad3bb9582330fa345e7a3a1597b76a5c..04b7b4804b7f39fca89dce63b6634ebe5daea478 100644 (file)
@@ -89,7 +89,7 @@ typedef struct BevPoint {
 */
 typedef struct BezTriple {
        float vec[3][3];
-       float alfa, weight, pad;
+       float alfa, weight, radius;     /* alfa: tilt in 3D View, weight: used for softbody goal weight, radius: for bevel tapering */
        short h1, h2;
        char f1, f2, f3, hide;
 } BezTriple;
@@ -97,17 +97,18 @@ typedef struct BezTriple {
 /* note; alfa location in struct is abused by Key system */
 typedef struct BPoint {
        float vec[4];
-       float alfa, weight;
+       float alfa, weight;             /* alfa: tilt in 3D View, weight: used for softbody goal weight */
        short f1, hide;
+       float radius, pad;              /* user-set radius per point for bevelling etc */
 } BPoint;
 
 typedef struct Nurb {
-       struct Nurb *next, *prev;
+       struct Nurb *next, *prev;       /* multiple nurbs per curve object are allowed */
        short type;
-       short mat_nr;          /* index into material list */
+       short mat_nr;           /* index into material list */
        short hide, flag;
-       short pntsu, pntsv;
-       short resolu, resolv;
+       short pntsu, pntsv;             /* number of points in the U or V directions */
+       short resolu, resolv;   /* tesselation resolution in the U or V directions */
        short orderu, orderv;
        short flagu, flagv;
        
index cf2edc8d28b6800fae16aa31e51efa04d92a87c7..28d35b979e2b67be888742750226252e4ac7f95c 100644 (file)
@@ -2412,7 +2412,7 @@ static void editing_panel_curve_type(Object *ob, Curve *cu)
                uiDefButF(block, NUM, B_MAKEDISP, "Width:",             760,90,150,19, &cu->width, 0.0, 2.0, 1, 0, "Make interpolated result thinner or fatter");
                uiDefButF(block, NUM, B_MAKEDISP, "Extrude:",           760,70,150,19, &cu->ext1, 0.0, 5.0, 10, 0, "Curve extrusion size when not using a bevel object");
                uiDefButF(block, NUM, B_MAKEDISP, "Bevel Depth:",               760,50,150,19, &cu->ext2, 0.0, 2.0, 1, 0, "Bevel depth when not using a bevel object");
-               uiDefButS(block, NUM, B_MAKEDISP, "BevResol:",  760,30,150,19, &cu->bevresol, 0.0, 10.0, 0, 0, "Bevel resolution when depth is non-zero and not using a bevel object");
+               uiDefButS(block, NUM, B_MAKEDISP, "BevResol:",  760,30,150,19, &cu->bevresol, 0.0, 32.0, 0, 0, "Bevel resolution when depth is non-zero and not using a bevel object");
                uiDefIDPoinBut(block, test_obcurpoin_but, ID_OB, B_CHANGEDEP, "BevOb:",         760,10,150,19, &cu->bevobj, "Curve object name that defines the bevel shape");
                uiDefIDPoinBut(block, test_obcurpoin_but, ID_OB, B_CHANGEDEP, "TaperOb:",               760,-10,150,19, &cu->taperobj, "Curve object name that defines the taper (width)");
 
index dc7b0d0f2d0db2d8d0b4088350afddcdf8823cdf..8368d69d30ee16ff126a622afced2ecc9a494e71 100644 (file)
@@ -1573,7 +1573,7 @@ static void v3d_editvertex_buts(uiBlock *block, Object *ob, float lim)
                
                nu= editNurb.first;
                while(nu) {
-                       if((nu->type & 7)==1) {
+                       if((nu->type & 7)==CU_BEZIER) {
                                bezt= nu->bezt;
                                a= nu->pntsu;
                                while(a--) {
@@ -2388,17 +2388,6 @@ static void view3d_panel_background(short cntrl) // VIEW3D_HANDLER_BACKGROUND
                uiDefButF(block, NUM, REDRAWVIEW3D, "X Offset:",        0, 6, 140, 19, &vd->bgpic->xof, -250.0*vd->grid,250.0*vd->grid, 10, 2, "Set the horizontal offset of the background image");
                uiDefButF(block, NUM, REDRAWVIEW3D, "Y Offset:",        150, 6, 140, 19, &vd->bgpic->yof, -250.0*vd->grid,250.0*vd->grid, 10, 2, "Set the vertical offset of the background image");
 
-       
-               
-               // uiDefButF(block, NUM, REDRAWVIEW3D, "Size:",                 160,160,150,20, &vd->bgpic->size, 0.1, 250.0, 100, 0, "Set the size for the width of the BackGroundPic");
-               
-
-
-//             uiDefButF(block, NUMSLI, B_BLENDBGPIC, "Blend:",        120,100,190,20,&vd->bgpic->blend, 0.0,1.0, 0, 0, "Set the BackGroundPic transparency");
-               
-//             uiDefButF(block, NUM, B_DIFF, "Center X: ",     10,70,140,20,&vd->bgpic->xof, -20.0,20.0, 10, 2, "Set the BackGroundPic X Offset");
-//             uiDefButF(block, NUM, B_DIFF, "Center Y: ",     160,70,140,20,&vd->bgpic->yof, -20.0,20.0, 10, 2, "Set the BackGroundPic Y Offset");
-
        }
 }
 
index 351ecc2927a194a17de08d450653dd5b8a61237a..a899cee70d9f147b07c98340dff21795d585d136 100644 (file)
@@ -1367,6 +1367,9 @@ void subdivideNurb()
                                                if(a==0 && (nu->flagu & 1)) {VECCOPY(beztnew->vec[0], vec+6);}
                                                else {VECCOPY(bezt->vec[0], vec+6);}
                                                
+                                               beztn->radius = (prevbezt->radius + bezt->radius)/2.0f;
+                                               beztn->weight = (prevbezt->weight + bezt->weight)/2.0f;
+                                               
                                                beztn++;
                                        }
 
@@ -1801,6 +1804,8 @@ int convertspline(short type, Nurb *nu)
                                VECCOPY(bezt->vec[1], bp->vec);
                                bezt->f1=bezt->f2=bezt->f3= bp->f1;
                                bezt->h1= bezt->h2= HD_VECT;
+                               bezt->weight= bp->weight;
+                               bezt->radius= bp->radius;
                                bp++;
                                bezt++;
                        }
@@ -1840,6 +1845,8 @@ int convertspline(short type, Nurb *nu)
                                        bp->vec[3]= 1.0;
                                        bp->f1= bezt->f2;
                                        nr-= 2;
+                                       bp->radius= bezt->radius;
+                                       bp->weight= bezt->weight;
                                        bp++;
                                }
                                else {
@@ -1849,6 +1856,8 @@ int convertspline(short type, Nurb *nu)
                                                if(c==0) bp->f1= bezt->f1;
                                                else if(c==1) bp->f1= bezt->f2;
                                                else bp->f1= bezt->f3;
+                                               bp->radius= bezt->radius;
+                                               bp->weight= bezt->weight;
                                                bp++;
                                        }
                                }
@@ -1898,6 +1907,8 @@ int convertspline(short type, Nurb *nu)
                                        bp++;
                                        VECCOPY(bezt->vec[2], bp->vec);
                                        bezt->f3= bp->f1;
+                                       bezt->radius= bp->radius;
+                                       bezt->weight= bp->weight;
                                        bp++;
                                        bezt++;
                                }
@@ -2769,7 +2780,7 @@ void makecyclicNurb()
                                bp= nu->bp;
                                while(a--) {
                                        if( bp->f1 & 1 ) {
-                                               if(nu->flagu & 1) nu->flagu--;
+                                               if(nu->flagu & CU_CYCLIC) nu->flagu--;
                                                else nu->flagu++;
                                                break;
                                        }
@@ -2781,7 +2792,7 @@ void makecyclicNurb()
                                bezt= nu->bezt;
                                while(a--) {
                                        if( BEZSELECTED(bezt) ) {
-                                               if(nu->flagu & 1) nu->flagu--;
+                                               if(nu->flagu & CU_CYCLIC) nu->flagu--;
                                                else nu->flagu++;
                                                break;
                                        }
@@ -2794,7 +2805,7 @@ void makecyclicNurb()
                                bp= nu->bp;
                                while(a--) {
                                        if( bp->f1 & 1 ) {
-                                               if(nu->flagu & 1) nu->flagu--;
+                                               if(nu->flagu & CU_CYCLIC) nu->flagu--;
                                                else {
                                                        nu->flagu++;
                                                        nu->flagu &= ~2;        /* endpoint flag, fixme */
@@ -2823,7 +2834,7 @@ void makecyclicNurb()
        
                                        if( bp->f1 & 1) {
                                                if(cyclmode==1 && nu->pntsu>1) {
-                                                       if(nu->flagu & 1) nu->flagu--;
+                                                       if(nu->flagu & CU_CYCLIC) nu->flagu--;
                                                        else {
                                                                nu->flagu++;
                                                                fp= MEM_mallocN(sizeof(float)*KNOTSU(nu), "makecyclicN");
@@ -3415,6 +3426,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
                        bezt= nu->bezt;
                        bezt->h1= bezt->h2= HD_ALIGN;
                        bezt->f1= bezt->f2= bezt->f3= 1;
+                       bezt->radius = 1.0;
 
                        for(a=0;a<3;a++) {
                                VECCOPY(bezt->vec[a], cent);
@@ -3429,6 +3441,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
                        bezt++;
                        bezt->h1= bezt->h2= HD_ALIGN;
                        bezt->f1= bezt->f2= bezt->f3= 1;
+                       bezt->radius = bezt->weight = 1.0;
 
                        for(a=0;a<3;a++) {
                                VECCOPY(bezt->vec[a], cent);
@@ -3449,6 +3462,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
                                VECCOPY(bp->vec, cent);
                                bp->vec[3]= 1.0;
                                bp->f1= 1;
+                               bp->radius = bp->weight = 1.0;
                        }
 
                        bp= nu->bp;
@@ -3472,7 +3486,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
 
                }
                break;
-       case 6: /* 5 point pad */
+       case 6: /* 5 point path */
                nu->pntsu= 5;
                nu->pntsv= 1;
                nu->orderu= 5;
@@ -3485,6 +3499,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
                        VECCOPY(bp->vec, cent);
                        bp->vec[3]= 1.0;
                        bp->f1= 1;
+                       bp->radius = bp->weight = 1.0;
                }
 
                bp= nu->bp;
@@ -3523,7 +3538,8 @@ Nurb *addNurbprim(int type, int stype, int newname)
                        bezt->f1= bezt->f2= bezt->f3= 1;
                        bezt->vec[1][0]+= -G.vd->grid;
                        for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
-
+                       bezt->radius = bezt->weight = 1.0;
+                       
                        bezt++;
                        for(a=0;a<3;a++) {
                                VECCOPY(bezt->vec[a], cent);
@@ -3532,6 +3548,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
                        bezt->f1= bezt->f2= bezt->f3= 1;
                        bezt->vec[1][1]+= G.vd->grid;
                        for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
+                       bezt->radius = bezt->weight = 1.0;
 
                        bezt++;
                        for(a=0;a<3;a++) {
@@ -3541,6 +3558,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
                        bezt->f1= bezt->f2= bezt->f3= 1;
                        bezt->vec[1][0]+= G.vd->grid;
                        for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
+                       bezt->radius = bezt->weight = 1.0;
 
                        bezt++;
                        for(a=0;a<3;a++) {
@@ -3550,6 +3568,7 @@ Nurb *addNurbprim(int type, int stype, int newname)
                        bezt->f1= bezt->f2= bezt->f3= 1;
                        bezt->vec[1][1]+= -G.vd->grid;
                        for(a=0;a<3;a++) Mat3MulVecfl(imat,bezt->vec[a]);
+                       bezt->radius = bezt->weight = 1.0;
 
                        calchandlesNurb(nu);
                }
@@ -3576,6 +3595,8 @@ Nurb *addNurbprim(int type, int stype, int newname)
                                if(a & 1) bp->vec[3]= 0.25*sqrt(2.0);
                                else bp->vec[3]= 1.0;
                                Mat3MulVecfl(imat,bp->vec);
+                               bp->radius = bp->weight = 1.0;
+                               
                                bp++;
                        }
 
index 27960db88906afdd67fb4d735f13f2fb74865ceb..4ab9005e8756e8c924bdbac18a43345f1eda25e2 100644 (file)
@@ -2174,7 +2174,7 @@ void special_editmenu(void)
        }
        else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
 
-               nr= pupmenu("Specials%t|Subdivide%x1|Switch Direction%x2|Set Goal Weight %x3");
+               nr= pupmenu("Specials%t|Subdivide%x1|Switch Direction%x2|Set Goal Weight %x3|Set Radius %x4");
                
                switch(nr) {
                case 1:
@@ -2210,6 +2210,39 @@ void special_editmenu(void)
                                }
                        }
                        break;
+               case 4:
+                       {
+                               static float radius= 1.0f;
+                               extern ListBase editNurb;
+                               Nurb *nu;
+                               BezTriple *bezt;
+                               BPoint *bp;
+                               int a;
+                               
+                               if(fbutton(&radius, 0.0001f, 10.0f, 10, 10, "Set Radius")) {
+                                       for(nu= editNurb.first; nu; nu= nu->next) {
+                                               if(nu->bezt) {
+                                                       for(bezt=nu->bezt, a=0; a<nu->pntsu; a++, bezt++) {
+                                                               if(bezt->f2 & SELECT)
+                                                                       bezt->radius= radius;
+                                                       }
+                                               }
+                                               else if(nu->bp) {
+                                                       for(bp=nu->bp, a=0; a<nu->pntsu*nu->pntsv; a++, bp++) {
+                                                               if(bp->f1 & SELECT)
+                                                                       bp->radius= radius;
+                                                       }
+                                               }
+                                       }       
+                               }
+                               
+                               DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+                               allqueue(REDRAWVIEW3D, 0);
+                               allqueue(REDRAWBUTSALL, 0);
+                               allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
+                               
+                       }
+                       break;
                }
                
                DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
index 99ec49961c5c90511e0385f4184656e96446321d..8ce07779d842cc57cb3ebc334705e57291b4c67f 100644 (file)
@@ -1737,8 +1737,11 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                                if(G.obedit->type==OB_ARMATURE) {
                                                        initTransform(TFM_BONESIZE, CTX_NONE);
                                                }
-                                               else
+                                               else if (G.obedit->type==OB_CURVE) {
+                                                       initTransform(TFM_CURVE_SHRINKFATTEN, CTX_NONE);
+                                               } else {
                                                        initTransform(TFM_SHRINKFATTEN, CTX_NONE);
+                                               }
                                                Transform();
                                        }
                                        else if(G.qual==LR_CTRLKEY) {
index 76e6c7eaf51c12e70952c7ea73bf4a4173156617..a99482c426131ff298f2aed696451edabcc9f286 100755 (executable)
@@ -786,6 +786,9 @@ void initTransform(int mode, int context) {
        case TFM_TILT:
                initTilt(&Trans);
                break;
+       case TFM_CURVE_SHRINKFATTEN:
+               initCurveShrinkFatten(&Trans);
+               break;
        case TFM_TRACKBALL:
                initTrackball(&Trans);
                break;
@@ -2329,6 +2332,85 @@ int Tilt(TransInfo *t, short mval[2])
        return 1;
 }
 
+
+/* ******************** Curve Shrink/Fatten *************** */
+
+int CurveShrinkFatten(TransInfo *t, short mval[2]) 
+{
+       TransData *td = t->data;
+       float ratio;
+       int i;
+       char str[50];
+       
+       if(t->flag & T_SHIFT_MOD) {
+               /* calculate ratio for shiftkey pos, and for total, and blend these for precision */
+               float dx= (float)(t->center2d[0] - t->shiftmval[0]);
+               float dy= (float)(t->center2d[1] - t->shiftmval[1]);
+               ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
+               
+               dx= (float)(t->center2d[0] - mval[0]);
+               dy= (float)(t->center2d[1] - mval[1]);
+               ratio+= 0.1f*(float)(sqrt( dx*dx + dy*dy)/t->fac -ratio);
+               
+       }
+       else {
+               float dx= (float)(t->center2d[0] - mval[0]);
+               float dy= (float)(t->center2d[1] - mval[1]);
+               ratio = (float)sqrt( dx*dx + dy*dy)/t->fac;
+       }
+       
+       snapGrid(t, &ratio);
+       
+       applyNumInput(&t->num, &ratio);
+       
+       /* header print for NumInput */
+       if (hasNumInput(&t->num)) {
+               char c[20];
+               
+               outputNumInput(&(t->num), c);
+               sprintf(str, "Shrink/Fatten: %s", c);
+       }
+       else {
+               sprintf(str, "Shrink/Fatten: %3f", ratio);
+       }
+       
+       for(i = 0 ; i < t->total; i++, td++) {
+               if (td->flag & TD_NOACTION)
+                       break;
+               
+               if(td->val) {
+                       //*td->val= ratio;
+                       *td->val= td->ival*ratio;
+                       if (*td->val <= 0.0f) *td->val = 0.0001f;
+               }
+       }
+       
+       recalcData(t);
+       
+       headerprint(str);
+       
+       viewRedrawForce(t);
+       
+       if(!(t->flag & T_USES_MANIPULATOR)) helpline (t, t->center);
+       
+       return 1;
+}
+
+void initCurveShrinkFatten(TransInfo *t)
+{
+       t->idx_max = 0;
+       t->num.idx_max = 0;
+       t->snap[0] = 0.0f;
+       t->snap[1] = 0.1f;
+       t->snap[2] = t->snap[1] * 0.1f;
+       t->transform = CurveShrinkFatten;
+       t->fac = (float)sqrt( (
+                  ((float)(t->center2d[1] - t->imval[1]))*((float)(t->center2d[1] - t->imval[1]))
+                  +
+                  ((float)(t->center2d[0] - t->imval[0]))*((float)(t->center2d[0] - t->imval[0]))
+                  ) );
+}
+
 /* ************************** PUSH/PULL *************************** */
 
 void initPushPull(TransInfo *t) 
index 577b4966c8f40c4557ad3870db9d43f5f74a9f87..572bde118d531dc056867c3fa292c0576668b29f 100755 (executable)
@@ -1139,8 +1139,14 @@ static void createTransCurveVerts(TransInfo *t)
                                                else td->flag= 0;
                                                td->ext = NULL;
                                                td->tdi = NULL;
-                                               td->val = &(bezt->alfa);
-                                               td->ival = bezt->alfa;
+                                               
+                                               if (t->mode==TFM_CURVE_SHRINKFATTEN) {
+                                                       td->val = &(bezt->radius);
+                                                       td->ival = bezt->radius;
+                                               } else {
+                                                       td->val = &(bezt->alfa);
+                                                       td->ival = bezt->alfa;
+                                               }
 
                                                Mat3CpyMat3(td->smtx, smtx);
                                                Mat3CpyMat3(td->mtx, mtx);
@@ -1188,8 +1194,14 @@ static void createTransCurveVerts(TransInfo *t)
                                                else td->flag= 0;
                                                td->ext = NULL;
                                                td->tdi = NULL;
-                                               td->val = &(bp->alfa);
-                                               td->ival = bp->alfa;
+                                               
+                                               if (t->mode==TFM_CURVE_SHRINKFATTEN) {
+                                                       td->val = &(bp->radius);
+                                                       td->ival = bp->radius;
+                                               } else {
+                                                       td->val = &(bp->alfa);
+                                                       td->ival = bp->alfa;
+                                               }
 
                                                Mat3CpyMat3(td->smtx, smtx);
                                                Mat3CpyMat3(td->mtx, mtx);
index 7f9f027953086f90e316d9c6b67062dd7ac92434..52b2c823cc8c9c878f946e482ae72b4724e27219 100755 (executable)
@@ -367,6 +367,7 @@ void initTransModeFlags(TransInfo *t, int mode)
        case TFM_SHEAR:
        case TFM_CREASE:
        case TFM_BONE_ENVELOPE:
+       case TFM_CURVE_SHRINKFATTEN:
                t->flag |= T_NO_CONSTRAINT;
                break;
        }
@@ -499,7 +500,7 @@ static void apply_grid3(TransInfo *t, float *val, int max_index, float fac1, flo
 
        if(t->mode==TFM_ROTATION || t->mode==TFM_WARP || t->mode==TFM_TILT || t->mode==TFM_TRACKBALL)
                invert = U.flag & USER_AUTOROTGRID;
-       else if(t->mode==TFM_RESIZE || t->mode==TFM_SHEAR || t->mode==TFM_BONESIZE || t->mode==TFM_SHRINKFATTEN)
+       else if(t->mode==TFM_RESIZE || t->mode==TFM_SHEAR || t->mode==TFM_BONESIZE || t->mode==TFM_SHRINKFATTEN || t->mode==TFM_CURVE_SHRINKFATTEN)
                invert = U.flag & USER_AUTOSIZEGRID;
        else
                invert = U.flag & USER_AUTOGRABGRID;