Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorMatt Ebb <matt@mke3.net>2006-08-13 11:37:51 +0400
committerMatt Ebb <matt@mke3.net>2006-08-13 11:37:51 +0400
commitd3028ec70d49bb7be62aa942cb7b111012ac95e2 (patch)
tree396f41a33b2d713ca8a8658affd4bb3064decb97 /source
parent515fe83f97c37cdf920e1e2fb1ad3479cb8d781c (diff)
* Shrink/Fatten for bevelled curves
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.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/intern/displist.c142
-rwxr-xr-xsource/blender/include/BIF_transform.h1
-rwxr-xr-xsource/blender/include/transform.h3
-rw-r--r--source/blender/makesdna/DNA_curve_types.h13
-rw-r--r--source/blender/src/buttons_editing.c2
-rw-r--r--source/blender/src/drawview.c13
-rw-r--r--source/blender/src/editcurve.c33
-rw-r--r--source/blender/src/editobject.c35
-rw-r--r--source/blender/src/space.c5
-rwxr-xr-xsource/blender/src/transform.c82
-rwxr-xr-xsource/blender/src/transform_conversions.c20
-rwxr-xr-xsource/blender/src/transform_generics.c3
12 files changed, 315 insertions, 37 deletions
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 2930203e0da..5ae7ffa6b36 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -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);
diff --git a/source/blender/include/BIF_transform.h b/source/blender/include/BIF_transform.h
index fc67aaf0f9b..2582920b697 100755
--- a/source/blender/include/BIF_transform.h
+++ b/source/blender/include/BIF_transform.h
@@ -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
diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h
index ab0b16e46a4..c17d920693f 100755
--- a/source/blender/include/transform.h
+++ b/source/blender/include/transform.h
@@ -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]);
diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h
index 4d0cca68ad3..04b7b4804b7 100644
--- a/source/blender/makesdna/DNA_curve_types.h
+++ b/source/blender/makesdna/DNA_curve_types.h
@@ -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;
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index cf2edc8d28b..28d35b979e2 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -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)");
diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c
index dc7b0d0f2d0..8368d69d30e 100644
--- a/source/blender/src/drawview.c
+++ b/source/blender/src/drawview.c
@@ -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");
-
}
}
diff --git a/source/blender/src/editcurve.c b/source/blender/src/editcurve.c
index 351ecc2927a..a899cee70d9 100644
--- a/source/blender/src/editcurve.c
+++ b/source/blender/src/editcurve.c
@@ -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++;
}
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index 27960db8890..4ab9005e875 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -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);
diff --git a/source/blender/src/space.c b/source/blender/src/space.c
index 99ec49961c5..8ce07779d84 100644
--- a/source/blender/src/space.c
+++ b/source/blender/src/space.c
@@ -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) {
diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c
index 76e6c7eaf51..a99482c4261 100755
--- a/source/blender/src/transform.c
+++ b/source/blender/src/transform.c
@@ -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)
diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c
index 577b4966c8f..572bde118d5 100755
--- a/source/blender/src/transform_conversions.c
+++ b/source/blender/src/transform_conversions.c
@@ -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);
diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c
index 7f9f0279530..52b2c823cc8 100755
--- a/source/blender/src/transform_generics.c
+++ b/source/blender/src/transform_generics.c
@@ -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;