diff options
author | Campbell Barton <ideasman42@gmail.com> | 2007-11-08 03:06:48 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2007-11-08 03:06:48 +0300 |
commit | 574744bf42aec3f81a3bac6af88e915715bc1975 (patch) | |
tree | fa1a8f2da8502cd7a7882def39071a6952dd78f6 | |
parent | 32758217590e98e810f6d522d4db24c50284bf08 (diff) |
New Curve function in the curve specials menu - "Smooth Radius" this smooth's the radius of selected curve points to unselected or endpoints. useful when changing the taper of a long curve
with many points (think treetrunk), it would be nice to take into account distance on the path when doing the curve interpolation.
Also moved added undo call's that were missing for 2 of the other curve specials.
-rw-r--r-- | source/blender/include/BDR_editcurve.h | 3 | ||||
-rw-r--r-- | source/blender/src/editcurve.c | 213 | ||||
-rw-r--r-- | source/blender/src/editobject.c | 64 |
3 files changed, 222 insertions, 58 deletions
diff --git a/source/blender/include/BDR_editcurve.h b/source/blender/include/BDR_editcurve.h index a8c36c3485b..70282aeb0c8 100644 --- a/source/blender/include/BDR_editcurve.h +++ b/source/blender/include/BDR_editcurve.h @@ -96,6 +96,9 @@ void add_primitiveNurb(int type); void clear_tilt(void); void clever_numbuts_curve(void); int bezt_compare (const void *e1, const void *e2); +void setweightNurb( void ); +void setradiusNurb( void ); +void smoothradiusNurb( void ); extern void undo_push_curve(char *name); diff --git a/source/blender/src/editcurve.c b/source/blender/src/editcurve.c index a710b53da1c..9d86f88b377 100644 --- a/source/blender/src/editcurve.c +++ b/source/blender/src/editcurve.c @@ -1081,6 +1081,219 @@ void switchdirection_knots(float *base, int tot) MEM_freeN(tempf); } +void setweightNurb(void) +{ + static float weight= 1.0f; + extern ListBase editNurb; + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + int a; + + if(fbutton(&weight, 0.0f, 1.0f, 10, 10, "Set Weight")) { + 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->weight= weight; + } + } + else if(nu->bp) { + for(bp=nu->bp, a=0; a<nu->pntsu*nu->pntsv; a++, bp++) { + if(bp->f1 & SELECT) + bp->weight= weight; + } + } + } + } + BIF_undo_push("Set Curve Weight"); + DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA); + allqueue(REDRAWVIEW3D, 0); +} + +void setradiusNurb( void ) +{ + 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; + } + } + } + } + BIF_undo_push("Set Curve Radius"); + DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSALL, 0); + allqueue(REDRAWINFO, 1); /* 1, because header->win==0! */ +} + + +/* TODO, make smoothing distance based */ +void smoothradiusNurb( void ) +{ + extern ListBase editNurb; + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + int a; + + /* use for smoothing */ + int last_sel; + int start_sel, end_sel; /* selection indicies, inclusive */ + float start_rad, end_rad, fac, range; + + for(nu= editNurb.first; nu; nu= nu->next) { + if(nu->bezt) { + + for (last_sel=0; last_sel < nu->pntsu; last_sel++) { + /* loop over selection segments of a curve, smooth each */ + + /* Start BezTriple code, this is duplicated below for points, make sure these functions stay in sync */ + start_sel = end_sel = -1; + for(bezt=nu->bezt+last_sel, a=last_sel; a<nu->pntsu; a++, bezt++) { + if(bezt->f2 & SELECT) { + start_sel = a; + break; + } + } + /* incase there are no other selected verts */ + end_sel = start_sel; + for(bezt=nu->bezt+(start_sel+1), a=start_sel+1; a<nu->pntsu; a++, bezt++) { + if((bezt->f2 & SELECT)==0) { + break; + } + end_sel = a; + } + + if (start_sel == -1) { + last_sel = nu->pntsu; /* next... */ + } else { + last_sel = end_sel; /* before we modify it */ + + /* now blend between start and end sel */ + start_rad = end_rad = -1.0; + + if (start_sel == end_sel) { + /* simple, only 1 point selected */ + if (start_sel>0) start_rad = (nu->bezt+start_sel-1)->radius; + if (end_sel!=-1 && end_sel < nu->pntsu) end_rad = (nu->bezt+start_sel+1)->radius; + + if (start_rad >= 0.0 && end_rad >= 0.0) (nu->bezt+start_sel)->radius = (start_rad + end_rad)/2; + else if (start_rad >= 0.0) (nu->bezt+start_sel)->radius = start_rad; + else if (end_rad >= 0.0) (nu->bezt+start_sel)->radius = end_rad; + } else { + /* if endpoints selected, then use them */ + if (start_sel==0) { + start_rad = (nu->bezt+start_sel)->radius; + start_sel++; /* we dont want to edit the selected endpoint */ + } else { + start_rad = (nu->bezt+start_sel-1)->radius; + } + if (end_sel==nu->pntsu-1) { + end_rad = (nu->bezt+end_sel)->radius; + end_sel--; /* we dont want to edit the selected endpoint */ + } else { + end_rad = (nu->bezt+end_sel+1)->radius; + } + + /* Now Blend between the 2 points */ + range = (float)(end_sel - start_sel) + 2.0f; + for(bezt=nu->bezt+start_sel, a=start_sel; a<=end_sel; a++, bezt++) { + fac = (float)(1+a-start_sel) / range; + bezt->radius = start_rad*(1.0-fac) + end_rad*fac; + } + } + } + } + } else if (nu->bp) { + /* Same as above, keep these the same! */ + for (last_sel=0; last_sel < nu->pntsu; last_sel++) { + /* loop over selection segments of a curve, smooth each */ + + /* Start BezTriple code, this is duplicated below for points, make sure these functions stay in sync */ + start_sel = end_sel = -1; + for(bp=nu->bp+last_sel, a=last_sel; a<nu->pntsu; a++, bp++) { + if(bp->f1 & SELECT) { + start_sel = a; + break; + } + } + /* incase there are no other selected verts */ + end_sel = start_sel; + for(bp=nu->bp+(start_sel+1), a=start_sel+1; a<nu->pntsu; a++, bp++) { + if((bp->f1 & SELECT)==0) { + break; + } + end_sel = a; + } + + if (start_sel == -1) { + last_sel = nu->pntsu; /* next... */ + } else { + last_sel = end_sel; /* before we modify it */ + + /* now blend between start and end sel */ + start_rad = end_rad = -1.0; + + if (start_sel == end_sel) { + /* simple, only 1 point selected */ + if (start_sel>0) start_rad = (nu->bp+start_sel-1)->radius; + if (end_sel!=-1 && end_sel < nu->pntsu) end_rad = (nu->bp+start_sel+1)->radius; + + if (start_rad >= 0.0 && end_rad >= 0.0) (nu->bp+start_sel)->radius = (start_rad + end_rad)/2; + else if (start_rad >= 0.0) (nu->bp+start_sel)->radius = start_rad; + else if (end_rad >= 0.0) (nu->bp+start_sel)->radius = end_rad; + } else { + /* if endpoints selected, then use them */ + if (start_sel==0) { + start_rad = (nu->bp+start_sel)->radius; + start_sel++; /* we dont want to edit the selected endpoint */ + } else { + start_rad = (nu->bp+start_sel-1)->radius; + } + if (end_sel==nu->pntsu-1) { + end_rad = (nu->bp+end_sel)->radius; + end_sel--; /* we dont want to edit the selected endpoint */ + } else { + end_rad = (nu->bp+end_sel+1)->radius; + } + + /* Now Blend between the 2 points */ + range = (float)(end_sel - start_sel) + 2.0f; + for(bp=nu->bp+start_sel, a=start_sel; a<=end_sel; a++, bp++) { + fac = (float)(1+a-start_sel) / range; + bp->radius = start_rad*(1.0-fac) + end_rad*fac; + } + } + } + } + } + } + BIF_undo_push("Smooth Curve Radius"); + DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSALL, 0); + allqueue(REDRAWINFO, 1); /* 1, because header->win==0! */ +} + + + /* **************** EDIT ************************ */ /* next == 1 -> select next */ diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 997593b30b1..3e316d578ab 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -2476,7 +2476,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|Set Radius %x4"); + nr= pupmenu("Specials%t|Subdivide%x1|Switch Direction%x2|Set Goal Weight %x3|Set Radius %x4|Smooth Radius %x5"); switch(nr) { case 1: @@ -2486,67 +2486,15 @@ void special_editmenu(void) switchdirectionNurb2(); break; case 3: - { - static float weight= 1.0f; - extern ListBase editNurb; - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - int a; - - if(fbutton(&weight, 0.0f, 1.0f, 10, 10, "Set Weight")) { - 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->weight= weight; - } - } - else if(nu->bp) { - for(bp=nu->bp, a=0; a<nu->pntsu*nu->pntsv; a++, bp++) { - if(bp->f1 & SELECT) - bp->weight= weight; - } - } - } - } - } + setweightNurb(); 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! */ - - } + setradiusNurb(); + break; + case 5: + smoothradiusNurb(); break; } - DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); } else if(G.obedit->type==OB_ARMATURE) { |