== IPO Editor Tools ==

* IPO Curve Smoothing:
This new tool smoothes (i.e. resets the adjusts) the handles on selected
ipo curves in ipo editor. The core code is based upon a python script
that used to do this (author unknown).

- Available from menus
- Hotkey Shift O
- Only available from ipo editor

If the usefulness of this tool is limited (adding bloat), I will consider removing it.
This commit is contained in:
2006-11-13 08:56:02 +00:00
parent 32d49a8dae
commit 6e46d87dd7
4 changed files with 149 additions and 2 deletions

View File

@@ -94,6 +94,7 @@ void add_duplicate_editipo(void);
void remove_doubles_ipo(void);
void clean_ipo(struct Ipo *ipo, short mode);
void clean_ipo_curve(struct IpoCurve *icu);
void smooth_ipo(void);
void join_ipo_menu(void);
void join_ipo(int mode);
void ipo_snap_menu(void);

View File

@@ -3166,6 +3166,141 @@ void clean_ipo_curve(IpoCurve *icu)
calchandles_ipocurve(icu);
}
static void smooth_bezt_handles(BezTriple *prev, BezTriple *me, BezTriple *next)
{
/* Smoothes (i.e. aligns) handles on the beztriple called me!
*
* The code here has been adapted from the "Smooth Ipo"
* python script (author unknown).
*/
float ptA[2], ptB[2], ptC[2];
float tdx, udx;
float tdy, udy;
float tx, ux;
float max_udy, max_tdy;
float slopu, slopt;
float medianSlope, slope;
float simpleudy, simpletdy;
float ty, uy;
/* get center-points of beztriples */
ptA[0]= prev->vec[1][0];
ptA[1]= prev->vec[1][1];
ptB[0]= me->vec[1][0];
ptB[1]= me->vec[1][1];
if (next != NULL) {
ptC[0]= next->vec[1][0];
ptC[1]= next->vec[1][1];
}
else {
ptC[0]= ptB[0] + 1.0f;
ptC[1]= ptB[1];
}
/* varios factors (are all of these needed?) */
tdx= (ptA[0]-ptB[0]) / 3.0f;
udx= (ptC[0]-ptB[0]) / 3.0f;
tx= ptB[0] + tdx;
ux= ptB[0] + udx;
max_udy= ptC[1] - ptB[1];
max_tdy= ptA[1] - ptB[1];
/* compute slopes */
if ((ptC[0]-ptB[0])==0.0)
slopu= 0.0f;
else
slopu= (ptC[1]-ptB[1]) / (ptC[0]-ptB[0]);
if ((ptA[0]-ptB[0])==0.0)
slopt= 0.0f;
else
slopt= (ptA[1]-ptB[1]) / (ptA[0]-ptB[0]);
if ((slopu*slopt) < 0) {
udy= 0;
tdy= 0;
}
else {
/* compute median slope */
medianSlope= (slopu+slopt) / 2.0;
simpleudy= medianSlope * udx;
simpletdy= medianSlope * tdx;
if ((simpleudy < max_udy) && (simpletdy < max_tdy)) {
udy= simpleudy;
tdy= simpletdy;
}
else {
/* use smallest slope */
slope = (slopu < slopt)?slopu:slopt;
slope = slope * ((slopu < 0)?-1:1);
udy= slope*udx;
tdy= slope*tdx;
}
}
/* calculate any remaining values */
ty= ptB[1] + tdy;
uy= ptB[1] + udy;
/* set new values of the handles of of beztriple being acted on */
me->vec[0][0]= tx;
me->vec[0][1]= ty;
me->vec[1][0]= ptB[0];
me->vec[1][1]= ptB[1];
me->vec[2][0]= ux;
me->vec[2][1]= uy;
me->vec[0][2] = me->vec[1][2] = me->vec[2][2] = 0.0f;
}
void smooth_ipo(void)
{
EditIpo *ei;
short ok;
int b;
get_status_editipo();
ei= G.sipo->editipo;
for(b=0; b<G.sipo->totipo; b++, ei++) {
if (ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt)) {
ok= 0;
if(G.sipo->showkey) ok= 1;
else if(totipo_vert && (ei->flag & IPO_EDIT)) ok= 2;
else if(totipo_vert==0 && (ei->flag & IPO_SELECT)) ok= 3;
if(ok) {
IpoCurve *icu= ei->icu;
/* check if enough points */
if (icu->totvert <= 3) {
BezTriple *prev, *me, *next;
int i;
for (i=1; i < icu->totvert; i++) {
/* try to get next point */
prev = (icu->bezt + (i - 1));
me = (icu->bezt + i);
if (i < (icu->totvert - 1))
next = (icu->bezt + (i + 1));
else
next = NULL;
/* smooth handles of current beztriple (me) */
smooth_bezt_handles(prev, me, next);
}
}
/* recalc handles */
calchandles_ipocurve(icu);
}
}
}
editipo_changed(G.sipo, 1);
BIF_undo_push("Smooth IPO");
}
void join_ipo_menu(void)
{
int mode = 0;

View File

@@ -585,6 +585,9 @@ static void do_ipo_editmenu(void *arg, int event)
clean_ipo(sipo->ipo, 1);
}
break;
case 9: /* smooth ipo */
smooth_ipo();
break;
}
}
@@ -641,6 +644,7 @@ static uiBlock *ipo_editmenu(void *arg_unused)
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate|Shift D", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Record Mouse Movement|R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clean IPO Curves|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Smooth IPO Curves|Shift O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, "");
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, "");
@@ -707,7 +711,11 @@ static void do_ipo_viewmenu(void *arg, int event)
G.v2d->flag ^= V2D_VIEWLOCK;
if(G.v2d->flag & V2D_VIEWLOCK)
view2d_do_locks(curarea, 0);
break;
break;
case 10: /* center view to current frame */
center_currframe();
scrarea_queue_winredraw(curarea);
break;
}
}

View File

@@ -2376,7 +2376,10 @@ static void winqreadipospace(ScrArea *sa, void *spacedata, BWinEvent *evt)
doredraw= 1;
break;
case OKEY:
clean_ipo(sipo->ipo, 1);
if(G.qual==LR_SHIFTKEY)
smooth_ipo();
else
clean_ipo(sipo->ipo, 1);
break;
case RKEY:
if((G.qual==0))