Stage two of the giant animation recode project; Ipo/Action/NLA cleanup
authorTon Roosendaal <ton@blender.org>
Mon, 10 Oct 2005 17:42:48 +0000 (17:42 +0000)
committerTon Roosendaal <ton@blender.org>
Mon, 10 Oct 2005 17:42:48 +0000 (17:42 +0000)
-> Note; added 2 new c files (split editipo.c). MSVC needs upgrade.

Impatient people can check the goodies in CMS:
http://www.blender3d.org/cms/Action_and_NLA_editor.706.0.html

Most work was on trying to unwind the spaghetti for editing ipos. Too much
history and bad design got added here. Most evident changes:
- made generic 'context' for detecting which Ipo is being edited, or to
  assign ipos or to retrieve ipo curves.
- made generic insertkey() for all ipo types, including actions
- shuffled a lot of code around to make things more logical. Also made
  sure local functions are not exported

It is far from ready... when action/nla was added in Blender, a lot of
duplicate code was generated. That's for another time.

Now the goodies;
- made Actions to allow any Ipo type
- made NLA to define active actions, for Action window too
- corrected timing for active action, so it shows the 'real time', as
  defined in NLA editor.

I did update python code, but that would require testing. Testing is
needed for this commit in general, too many changes happened on all
levels of the animation system. :)
Will keep track of all reports this evening, hopefully it doesnt break
the pre-release schedule!

26 files changed:
source/blender/src/SConscript
source/blender/src/buttons_object.c
source/blender/src/drawaction.c
source/blender/src/drawipo.c
source/blender/src/drawnla.c
source/blender/src/drawtime.c
source/blender/src/editaction.c
source/blender/src/editarmature.c
source/blender/src/editconstraint.c
source/blender/src/editipo.c
source/blender/src/editipo_lib.c [new file with mode: 0644]
source/blender/src/editipo_mods.c [new file with mode: 0644]
source/blender/src/editkey.c
source/blender/src/editnla.c
source/blender/src/editobject.c
source/blender/src/editview.c
source/blender/src/glutil.c
source/blender/src/header_action.c
source/blender/src/header_ipo.c
source/blender/src/header_nla.c
source/blender/src/headerbuttons.c
source/blender/src/poseobject.c
source/blender/src/resources.c
source/blender/src/space.c
source/blender/src/transform_conversions.c
source/blender/src/usiblender.c

index 7c745b251dabaf2243e12b48aad7f21f30b4d1ca..e2deaa475442a1fffed56a9d56c4f83b5864882d 100644 (file)
@@ -23,7 +23,7 @@ source_files = ['B.blend.c',
                 'cmovie.tga.c',
                 'cursors.c',
                 'drawaction.c',
-                       'drawarmature.c',
+               'drawarmature.c',
                 'drawdeps.c',
                 'drawimage.c',
                 'drawimasel.c',
@@ -50,6 +50,8 @@ source_files = ['B.blend.c',
                 'editgroup.c',
                 'editimasel.c',
                 'editipo.c',
+                'editipo_lib.c',
+                'editipo_mods.c',
                 'editkey.c',
                 'editlattice.c',
                 'editmball.c',
index 54024d0dee994e8f0d1e7d29a1e1436b0f442dbc..cd382f6e89f33c631afee8c1ba657b4bd59f6d61 100644 (file)
@@ -59,7 +59,7 @@
 #include "BSE_headerbuttons.h"
 
 #include "BIF_butspace.h"
-#include "BDR_editcurve.h"
+#include "BIF_editaction.h"
 #include "BIF_gl.h"
 #include "BIF_glutil.h"
 #include "BIF_graphics.h"
@@ -74,6 +74,7 @@
 #include "BIF_toolbox.h"
 
 #include "BDR_drawobject.h"
+#include "BDR_editcurve.h"
 
 #include "mydevice.h"
 #include "blendef.h"
 #include "LBM_fluidsim.h"
 
 #include "BIF_editconstraint.h"
+
 #include "BSE_editipo.h"
+#include "BSE_edit.h"
+
 #include "BDR_editobject.h"
 
 #include "butspace.h" // own module
@@ -162,8 +166,8 @@ static void constraint_active_func(void *ob_v, void *con_v)
        }
 
        /* make sure ipowin and buttons shows it */
-       if(ob->ipowin==IPO_CO) {
-               allqueue(REDRAWIPO, IPO_CO);
+       if(ob->ipowin==ID_CO) {
+               allqueue(REDRAWIPO, ID_CO);
                allspace(REMAKEIPO, 0);
                allqueue(REDRAWNLA, 0);
        }
@@ -185,38 +189,44 @@ static void add_constraint_to_active(Object *ob, bConstraint *con)
        }
 }
 
+/* returns base ID for Ipo, sets actname to channel if appropriate */
+/* should not make action... */
+static void get_constraint_ipo_context(Object *ob, char *actname)
+{
+       
+       /* todo; check object if it has ob-level action ipo */
+       
+       if (ob->flag & OB_POSEMODE) {
+               bPoseChannel *pchan;
+               
+               pchan = get_active_posechannel(ob);
+               if (pchan) {
+                       BLI_strncpy(actname, pchan->name, 32);
+               }
+       }
+       else if(ob->ipoflag & OB_ACTION_OB)
+               strcpy(actname, "Object");
+}      
+
+/* initialize UI to show Ipo window and make sure channels etc exist */
 static void enable_constraint_ipo_func (void *ob_v, void *con_v)
 {
        Object *ob= ob_v;
        bConstraint *con = con_v;
-       bConstraintChannel *chan;
-       ListBase *conbase;
-
+       char actname[32]="";
+       
+       /* verifies if active constraint is set and shown in UI */
        constraint_active_func(ob_v, con_v);
-               
-       conbase = get_active_constraint_channels(ob, 1);        // 1 == create
-
-       if (!conbase)
-               return;
-
-       /* See if this list already has an appropriate channel */
-       chan = find_constraint_channel(conbase, con->name);
-
-       if (!chan){
-               /* Add a new constraint channel */
-               chan = MEM_callocN(sizeof(bConstraintChannel), "constraintChannel");
-               strcpy(chan->name, con->name);
-               BLI_addtail(conbase, chan);
-       }
-
-       /* Ensure there is an ipo to display */
-       if (!chan->ipo){
-               chan->ipo = add_ipo(con->name, IPO_CO);
-       }
-
+       
+       /* the context */
+       get_constraint_ipo_context(ob, actname);
+       
+       /* adds ipo & channels & curve if needed */
+       verify_ipo((ID *)ob, ID_CO, actname, con->name);
+       
        /* make sure ipowin shows it */
-       ob->ipowin= IPO_CO;
-       allqueue(REDRAWIPO, IPO_CO);
+       ob->ipowin= ID_CO;
+       allqueue(REDRAWIPO, ID_CO);
        allspace(REMAKEIPO, 0);
        allqueue(REDRAWNLA, 0);
 }
@@ -226,38 +236,23 @@ static void add_influence_key_to_constraint_func (void *ob_v, void *con_v)
 {
        Object *ob= ob_v;
        bConstraint *con = con_v;
-       bConstraintChannel *chan;
-       ListBase *conbase;
        IpoCurve *icu;
+       char actname[32]="";
        
+       /* verifies if active constraint is set and shown in UI */
        constraint_active_func(ob_v, con_v);
-       conbase = get_active_constraint_channels(ob, 1);        // 1=make
-       
-       if (!conbase)
-               return;
-       
-       /* See if this list already has an appropriate channel */
-       chan = find_constraint_channel(conbase, con->name);
-       
-       if (!chan){
-               /* Add a new constraint channel */
-               chan = MEM_callocN(sizeof(bConstraintChannel), "constraintChannel");
-               strcpy(chan->name, con->name);
-               BLI_addtail(conbase, chan);
-       }
        
-       /* Ensure there is an ipo to display */
-       if (!chan->ipo){
-               chan->ipo = add_ipo(con->name, IPO_CO);
-       }
-       
-       /* now insert an ipo key */
-       icu= get_ipocurve(NULL, IPO_CO, CO_ENFORCE, chan->ipo);
+       /* the context */
+       get_constraint_ipo_context(ob, actname);
+
+       /* adds ipo & channels & curve if needed */
+       icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, CO_ENFORCE);
+
        insert_vert_ipo(icu, CFRA, con->enforce);
        
        /* make sure ipowin shows it */
-       ob->ipowin= IPO_CO;
-       allqueue(REDRAWIPO, IPO_CO);
+       ob->ipowin= ID_CO;
+       allqueue(REDRAWIPO, ID_CO);
        allspace(REMAKEIPO, 0);
        allqueue(REDRAWNLA, 0);
        
@@ -274,7 +269,7 @@ static void del_constraint_func (void *ob_v, void *con_v)
        /* remove ipo channel */
        lb= get_active_constraint_channels(ob_v, 0);
        if(lb) {
-               chan = find_constraint_channel(lb, con->name);
+               chan = get_constraint_channel(lb, con->name);
                if(chan) {
                        if(chan->ipo) chan->ipo->id.us--;
                        BLI_freelinkN(lb, chan);
@@ -1322,23 +1317,21 @@ void do_object_panels(unsigned short event)
                /* write config files (currently no simulation) */
                fluidsimBake(ob);
                break;
-       case B_FLUIDSIM_SELDIR: {
-                       char str[FILE_MAXDIR+FILE_MAXFILE];
-                       ScrArea *sa = closest_bigger_area();
-                       strcpy(str,"//");
-                       ob= OBACT;
-                       /* chosse dir for surface files */
-                       areawinset(sa->win);
-                       activate_fileselect(FILE_SPECIAL, "Select Directory", str, fluidsimFilesel);
-                       // continue with redraw... so no brake here!
-               }
-       case B_FLUIDSIM_FORCEREDRAW: {
-                       // force redraw
-                       allqueue(REDRAWBUTSEDIT, 0);
-                       allqueue(REDRAWVIEW3D, 0);
-                       countall();
-                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
-               }
+       case B_FLUIDSIM_SELDIR:
+               char str[FILE_MAXDIR+FILE_MAXFILE];
+               ScrArea *sa = closest_bigger_area();
+               strcpy(str,"//");
+               ob= OBACT;
+               /* choose dir for surface files */
+               areawinset(sa->win);
+               activate_fileselect(FILE_SPECIAL, "Select Directory", str, fluidsimFilesel);
+               /* continue with redraw... so no brake here! */
+       case B_FLUIDSIM_FORCEREDRAW:
+               /* force redraw */
+               allqueue(REDRAWBUTSEDIT, 0);
+               allqueue(REDRAWVIEW3D, 0);
+               countall();
+               DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
                break;
                
        default:
@@ -1371,35 +1364,35 @@ static void object_panel_anim(Object *ob)
        if(uiNewPanel(curarea, block, "Anim settings", "Object", 0, 0, 318, 204)==0) return;
        
        uiBlockBeginAlign(block);
-       uiDefButC(block, ROW,B_TRACKBUTS,"TrackX",      24,190,59,19, &ob->trackflag, 12.0, 0.0, 0, 0, "Specify the axis that points to another object");
-       uiDefButC(block, ROW,B_TRACKBUTS,"Y",           85,190,19,19, &ob->trackflag, 12.0, 1.0, 0, 0, "Specify the axis that points to another object");
-       uiDefButC(block, ROW,B_TRACKBUTS,"Z",           104,190,19,19, &ob->trackflag, 12.0, 2.0, 0, 0, "Specify the axis that points to another object");
-       uiDefButC(block, ROW,B_TRACKBUTS,"-X",          124,190,24,19, &ob->trackflag, 12.0, 3.0, 0, 0, "Specify the axis that points to another object");
-       uiDefButC(block, ROW,B_TRACKBUTS,"-Y",          150,190,24,19, &ob->trackflag, 12.0, 4.0, 0, 0, "Specify the axis that points to another object");
-       uiDefButC(block, ROW,B_TRACKBUTS,"-Z",          178,190,24,19, &ob->trackflag, 12.0, 5.0, 0, 0, "Specify the axis that points to another object");
+       uiDefButS(block, ROW,B_TRACKBUTS,"TrackX",      24,190,59,19, &ob->trackflag, 12.0, 0.0, 0, 0, "Specify the axis that points to another object");
+       uiDefButS(block, ROW,B_TRACKBUTS,"Y",           85,190,19,19, &ob->trackflag, 12.0, 1.0, 0, 0, "Specify the axis that points to another object");
+       uiDefButS(block, ROW,B_TRACKBUTS,"Z",           104,190,19,19, &ob->trackflag, 12.0, 2.0, 0, 0, "Specify the axis that points to another object");
+       uiDefButS(block, ROW,B_TRACKBUTS,"-X",          124,190,24,19, &ob->trackflag, 12.0, 3.0, 0, 0, "Specify the axis that points to another object");
+       uiDefButS(block, ROW,B_TRACKBUTS,"-Y",          150,190,24,19, &ob->trackflag, 12.0, 4.0, 0, 0, "Specify the axis that points to another object");
+       uiDefButS(block, ROW,B_TRACKBUTS,"-Z",          178,190,24,19, &ob->trackflag, 12.0, 5.0, 0, 0, "Specify the axis that points to another object");
        uiBlockBeginAlign(block);
-       uiDefButC(block, ROW,REDRAWVIEW3D,"UpX",        226,190,45,19, &ob->upflag, 13.0, 0.0, 0, 0, "Specify the axis that points up");
-       uiDefButC(block, ROW,REDRAWVIEW3D,"Y",          274,190,20,19, &ob->upflag, 13.0, 1.0, 0, 0, "Specify the axis that points up");
-       uiDefButC(block, ROW,REDRAWVIEW3D,"Z",          298,190,19,19, &ob->upflag, 13.0, 2.0, 0, 0, "Specify the axis that points up");
+       uiDefButS(block, ROW,REDRAWVIEW3D,"UpX",        226,190,45,19, &ob->upflag, 13.0, 0.0, 0, 0, "Specify the axis that points up");
+       uiDefButS(block, ROW,REDRAWVIEW3D,"Y",          274,190,20,19, &ob->upflag, 13.0, 1.0, 0, 0, "Specify the axis that points up");
+       uiDefButS(block, ROW,REDRAWVIEW3D,"Z",          298,190,19,19, &ob->upflag, 13.0, 2.0, 0, 0, "Specify the axis that points up");
        uiBlockBeginAlign(block);
-       uiDefButBitC(block, TOG, OB_DRAWKEY, REDRAWVIEW3D, "Draw Key",          24,160,71,19, &ob->ipoflag, 0, 0, 0, 0, "Draw object as key position");
-       uiDefButBitC(block, TOG, OB_DRAWKEYSEL, REDRAWVIEW3D, "Draw Key Sel",   97,160,81,19, &ob->ipoflag, 0, 0, 0, 0, "Limit the drawing of object keys");
-       uiDefButBitC(block, TOG, OB_POWERTRACK, REDRAWVIEW3D, "Powertrack",             180,160,78,19, &ob->transflag, 0, 0, 0, 0, "Switch objects rotation off");
+       uiDefButBitS(block, TOG, OB_DRAWKEY, REDRAWVIEW3D, "Draw Key",          24,160,71,19, &ob->ipoflag, 0, 0, 0, 0, "Draw object as key position");
+       uiDefButBitS(block, TOG, OB_DRAWKEYSEL, REDRAWVIEW3D, "Draw Key Sel",   97,160,81,19, &ob->ipoflag, 0, 0, 0, 0, "Limit the drawing of object keys");
+       uiDefButBitS(block, TOG, OB_POWERTRACK, REDRAWVIEW3D, "Powertrack",             180,160,78,19, &ob->transflag, 0, 0, 0, 0, "Switch objects rotation off");
        uiDefButBitS(block, TOG, PARSLOW, 0, "SlowPar",                                 260,160,56,19, &ob->partype, 0, 0, 0, 0, "Create a delay in the parent relationship");
        uiBlockBeginAlign(block);
-       uiDefButBitC(block, TOG, OB_DUPLIFRAMES, REDRAWVIEW3D, "DupliFrames",   24,128,89,19, &ob->transflag, 0, 0, 0, 0, "Make copy of object for every frame");
-       uiDefButBitC(block, TOG, OB_DUPLIVERTS, REDRAWVIEW3D, "DupliVerts",             114,128,82,19, &ob->transflag, 0, 0, 0, 0, "Duplicate child objects on all vertices");
-       uiDefButBitC(block, TOG, OB_DUPLIROT, REDRAWVIEW3D, "Rot",              200,128,31,19, &ob->transflag, 0, 0, 0, 0, "Rotate dupli according to facenormal");
-       uiDefButBitC(block, TOG, OB_DUPLINOSPEED, REDRAWVIEW3D, "No Speed",     234,128,82,19, &ob->transflag, 0, 0, 0, 0, "Set dupliframes to still, regardless of frame");
+       uiDefButBitS(block, TOG, OB_DUPLIFRAMES, REDRAWVIEW3D, "DupliFrames",   24,128,89,19, &ob->transflag, 0, 0, 0, 0, "Make copy of object for every frame");
+       uiDefButBitS(block, TOG, OB_DUPLIVERTS, REDRAWVIEW3D, "DupliVerts",             114,128,82,19, &ob->transflag, 0, 0, 0, 0, "Duplicate child objects on all vertices");
+       uiDefButBitS(block, TOG, OB_DUPLIROT, REDRAWVIEW3D, "Rot",              200,128,31,19, &ob->transflag, 0, 0, 0, 0, "Rotate dupli according to facenormal");
+       uiDefButBitS(block, TOG, OB_DUPLINOSPEED, REDRAWVIEW3D, "No Speed",     234,128,82,19, &ob->transflag, 0, 0, 0, 0, "Set dupliframes to still, regardless of frame");
        uiBlockBeginAlign(block);
        uiDefButS(block, NUM, REDRAWVIEW3D, "DupSta:",          24,105,141,19, &ob->dupsta, 1.0, (MAXFRAMEF - 1.0f), 0, 0, "Specify startframe for Dupliframes");
        uiDefButS(block, NUM, REDRAWVIEW3D, "DupOn:",           170,105,146,19, &ob->dupon, 1.0, 1500.0, 0, 0, "");
        uiDefButS(block, NUM, REDRAWVIEW3D, "DupEnd",           24,82,140,19, &ob->dupend, 1.0, MAXFRAMEF, 0, 0, "Specify endframe for Dupliframes");
        uiDefButS(block, NUM, REDRAWVIEW3D, "DupOff",           171,82,145,19, &ob->dupoff, 0.0, 1500.0, 0, 0, "");
        uiBlockBeginAlign(block);
-       uiDefButBitC(block, TOG, OB_OFFS_OB, REDRAWALL, "Offs Ob",                      24,51,56,20, &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on its own objectipo");
-       uiDefButBitC(block, TOG, OB_OFFS_PARENT, REDRAWALL, "Offs Par",                 82,51,56,20 , &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on the parent");
-       uiDefButBitC(block, TOG, OB_OFFS_PARTICLE, REDRAWALL, "Offs Particle",          140,51,103,20, &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on the particle effect");
+       uiDefButBitS(block, TOG, OB_OFFS_OB, REDRAWALL, "Offs Ob",                      24,51,56,20, &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on its own objectipo");
+       uiDefButBitS(block, TOG, OB_OFFS_PARENT, REDRAWALL, "Offs Par",                 82,51,56,20 , &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on the parent");
+       uiDefButBitS(block, TOG, OB_OFFS_PARTICLE, REDRAWALL, "Offs Particle",          140,51,103,20, &ob->ipoflag, 0, 0, 0, 0, "Let the timeoffset work on the particle effect");
        
        uiBlockBeginAlign(block);
        uiDefButF(block, NUM, REDRAWALL, "TimeOffset:",                 24,17,115,30, &ob->sf, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify an offset in frames");
index 44a78de6729ef43d86261a2cbee97ec619975a83..8e6b1934f4d6f29d97810a4bc972e22c2e670f2e 100644 (file)
@@ -78,6 +78,7 @@
 #include "BDR_editcurve.h"
 
 #include "BSE_view.h"
+#include "BSE_drawnla.h"
 #include "BSE_drawipo.h"
 
 /* 'old' stuff": defines and types, and own include -------------------- */
@@ -360,41 +361,6 @@ int count_action_levels(bAction *act)
 
        return y;
 }
-       /** Draw a nicely beveled button (in screen space) */
-void draw_bevel_but(int x, int y, int w, int h, int sel)
-{
-       int xmin= x, ymin= y;
-       int xmax= x+w-1, ymax= y+h-1;
-       int i;
-
-       glColor3ub(0,0,0);
-       glBegin(GL_LINE_LOOP);
-       glVertex2i(xmin, ymin);
-       glVertex2i(xmax, ymin);
-       glVertex2i(xmax, ymax);
-       glVertex2i(xmin, ymax);
-       glEnd();
-
-       glBegin(GL_LINE_LOOP);
-       if (sel) glColor3ub(0xD0, 0x7E, 0x06);
-       else glColor3ub(0x8C, 0x8C, 0x8C);
-       glVertex2i(xmax-1, ymin+1);
-       glVertex2i(xmax-1, ymax-1);
-       if (sel) glColor3ub(0xF4, 0xEE, 0x8E);
-       else glColor3ub(0xDF, 0xDF, 0xDF);
-       glVertex2i(xmin+1, ymax-1);
-       glVertex2i(xmin+1, ymin+1);
-       glEnd();
-
-       if (sel) glColor3ub(0xF1, 0xCA, 0x13);
-       else glColor3ub(0xAC, 0xAC, 0xAC);
-       glBegin(GL_LINES);
-       for (i=xmin+2; i<=xmax-2; i++) {
-               glVertex2f(i, ymin+2);
-               glVertex2f(i, ymax-1);
-       }
-       glEnd();
-}
 
 static void draw_channel_strips(SpaceAction *saction)
 {
@@ -404,6 +370,7 @@ static void draw_channel_strips(SpaceAction *saction)
        bActionChannel *chan;
        bConstraintChannel *conchan;
        float   y;
+       int act_end, dummy;
        char col1[3], col2[3];
        
        BIF_GetThemeColor3ubv(TH_SHADE2, col2);
@@ -413,14 +380,21 @@ static void draw_channel_strips(SpaceAction *saction)
        if (!act)
                return;
 
-       scr_rct.xmin= saction->area->winrct.xmin + ACTWIDTH;
+       scr_rct.xmin= saction->area->winrct.xmin + saction->v2d.mask.xmin;
        scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin;
        scr_rct.xmax= saction->area->winrct.xmin + saction->v2d.hor.xmax;
        scr_rct.ymax= saction->area->winrct.ymin + saction->v2d.mask.ymax; 
        di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
 
+       /* if in NLA there's a strip active, map the view */
+       if (G.saction->pin==0 && OBACT)
+               map_active_strip(di, OBACT, 0);
+       
        y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP);
 
+       /* end of action itself */
+       gla2DDrawTranslatePt(di, calc_action_end(act), 0, &act_end, &dummy);
+       
        for (chan=act->chanbase.first; chan; chan=chan->next){
                int frame1_x, channel_y;
 
@@ -429,11 +403,11 @@ static void draw_channel_strips(SpaceAction *saction)
                glEnable(GL_BLEND);
                if (chan->flag & ACHAN_SELECTED) glColor4ub(col1[0], col1[1], col1[2], 0x22);
                else glColor4ub(col2[0], col2[1], col2[2], 0x22);
-               glRectf(0,  channel_y-CHANNELHEIGHT/2,  frame1_x,  channel_y+CHANNELHEIGHT/2);
+               glRectf(0,  channel_y-CHANNELHEIGHT/2,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
 
                if (chan->flag & ACHAN_SELECTED) glColor4ub(col1[0], col1[1], col1[2], 0x44);
                else glColor4ub(col2[0], col2[1], col2[2], 0x44);
-               glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
+               glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2,  act_end,  channel_y+CHANNELHEIGHT/2);
                glDisable(GL_BLEND);
        
                draw_ipo_channel(di, chan->ipo, 0, y);
@@ -445,14 +419,15 @@ static void draw_channel_strips(SpaceAction *saction)
                /* Draw constraint channels */
                for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
                        gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
+                       
                        glEnable(GL_BLEND);
                        if (conchan->flag & ACHAN_SELECTED) glColor4ub(col1[0], col1[1], col1[2], 0x22);
                        else glColor4ub(col2[0], col2[1], col2[2], 0x22);
-                       glRectf(0,  channel_y-CHANNELHEIGHT/2+4,  frame1_x,  channel_y+CHANNELHEIGHT/2-4);
+                       glRectf(0,  channel_y-CHANNELHEIGHT/2+4,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2-4);
                        
                        if (conchan->flag & ACHAN_SELECTED) glColor4ub(col1[0], col1[1], col1[2], 0x44);
                        else glColor4ub(col2[0], col2[1], col2[2], 0x44);
-                       glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2+4,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2-4);
+                       glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2+4,  act_end,  channel_y+CHANNELHEIGHT/2-4);
                        glDisable(GL_BLEND);
                        
                        draw_ipo_channel(di, conchan->ipo, 0, y);
@@ -651,10 +626,8 @@ void drawactionspace(ScrArea *sa, void *spacedata)
                 * then draw the key frames in the action window
                 */
                draw_mesh_strips(G.saction, key);
-               /*meshactionbuts(G.saction, key);*/
        }
 
-
        /* Draw current frame */
        glViewport(ofsx+G.v2d->mask.xmin,  
              ofsy+G.v2d->mask.ymin, 
@@ -674,16 +647,20 @@ void drawactionspace(ScrArea *sa, void *spacedata)
       if(G.v2d->scroll) drawscroll(0);
        }
 
-       /* Draw channel names */
-       draw_channel_names();
+       if(G.v2d->mask.xmin!=0) {
+               /* Draw channel names */
+               draw_channel_names();
 
-       if ( key ) {
-               /* if there is a mesh with rvk's selected,
-                * then draw the key frames in the action window
-                */
-               meshactionbuts(G.saction, key);
+               if(sa->winx > 50 + NAMEWIDTH + SLIDERWIDTH) {
+                       if ( key ) {
+                               /* if there is a mesh with rvk's selected,
+                                * then draw the key frames in the action window
+                                */
+                               meshactionbuts(G.saction, key);
+                       }
+               }
        }
-
+       
        mywinset(curarea->win); // reset scissor too
        myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
        draw_area_emboss(sa);
@@ -695,11 +672,41 @@ void drawactionspace(ScrArea *sa, void *spacedata)
        curarea->win_swap= WIN_BACK_OK;
 }
 
-/* unused and blank
-void draw_channel_name(const char* name, short type, float ypos, int selected)
+
+/** Draw a nicely beveled button (in screen space) */
+static void draw_bevel_but(int x, int y, int w, int h, int sel)
 {
+       int xmin= x, ymin= y;
+       int xmax= x+w-1, ymax= y+h-1;
+       
+       /* outline */
+       glColor3ub(0,0,0);
+       glBegin(GL_LINE_LOOP);
+       glVertex2i(xmin, ymin);
+       glVertex2i(xmax, ymin);
+       glVertex2i(xmax, ymax);
+       glVertex2i(xmin, ymax);
+       glEnd();
+       
+       /* interior */
+       if (sel) glColor3ub(0xF1, 0xCA, 0x13);
+       else glColor3ub(0xAC, 0xAC, 0xAC);
+       glRectf(xmin+1, ymin+1, xmax-1, ymax-1);
+       
+       /* bevel */
+       glBegin(GL_LINE_LOOP);
+       
+       if (sel) glColor3ub(0xD0, 0x7E, 0x06);
+       else glColor3ub(0x8C, 0x8C, 0x8C);
+       glVertex2i(xmax-1, ymin+1);
+       glVertex2i(xmax-1, ymax-1);
+       
+       if (sel) glColor3ub(0xF4, 0xEE, 0x8E);
+       else glColor3ub(0xDF, 0xDF, 0xDF);
+       glVertex2i(xmin+1, ymax-1);
+       glVertex2i(xmin+1, ymin+1);
+       glEnd();
 }
-*/
 
 static void draw_keylist(gla2DDrawInfo *di, int totvert, BezTriple **blist, float ypos)
 {
@@ -712,7 +719,7 @@ static void draw_keylist(gla2DDrawInfo *di, int totvert, BezTriple **blist, floa
                if (v==0 || (blist[v]->vec[1][0] != blist[v-1]->vec[1][0])){
                        int sc_x, sc_y;
                        gla2DDrawTranslatePt(di, blist[v]->vec[1][0], ypos, &sc_x, &sc_y);
-                       draw_bevel_but(sc_x-2, sc_y-5, 7, 13, (blist[v]->f2 & 1));
+                       draw_bevel_but(sc_x-2, sc_y-7, 7, 13, (blist[v]->f2 & 1));
                }
        }                       
 }
@@ -770,6 +777,7 @@ void draw_action_channel(gla2DDrawInfo *di, bAction *act, int flags, float ypos)
 static BezTriple **ob_to_keylist(Object *ob, int flags, int *totvert)
 {
        IpoCurve *icu;
+       bConstraintChannel *conchan;
        int v, count=0;
 
        BezTriple **list = NULL;
@@ -784,6 +792,12 @@ static BezTriple **ob_to_keylist(Object *ob, int flags, int *totvert)
                }
                
                /* Count Constraint Keys */
+               for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next){
+                       if(conchan->ipo)
+                               for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
+                                       count+=icu->totvert;
+               }
+               
                /* Count object data keys */
 
                /* Build the list */
@@ -792,13 +806,21 @@ static BezTriple **ob_to_keylist(Object *ob, int flags, int *totvert)
                        count=0;
                        
                        /* Add object keyframes */
-                       for (icu=ob->ipo->curve.first; icu; icu=icu->next){
-                               for (v=0; v<icu->totvert; v++){
-                                       list[count++]=&icu->bezt[v];
+                       if(ob->ipo) {
+                               for (icu=ob->ipo->curve.first; icu; icu=icu->next){
+                                       for (v=0; v<icu->totvert; v++){
+                                               list[count++]=&icu->bezt[v];
+                                       }
                                }
+                       }                       
+                       /* Add constraint keyframes */
+                       for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next){
+                               if(conchan->ipo)
+                                       for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
+                                               for (v=0; v<icu->totvert; v++)
+                                                       list[count++]=&icu->bezt[v];
                        }
                        
-                       /* Add constraint keyframes */
                        /* Add object data keyframes */
 
                        /* Sort */
@@ -880,13 +902,13 @@ static BezTriple **action_to_keylist(bAction *act, int flags, int *totvert)
                        if(achan->ipo) {
                                for (icu=achan->ipo->curve.first; icu; icu=icu->next)
                                        count+=icu->totvert;
-                               
-                               /* Count constraint keys */
-                               for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
+                       }
+                       /* Count constraint keys */
+                       for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
+                               if(conchan->ipo) 
                                        for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
                                                count+=icu->totvert;
                                
-                       }
                }
                
                /* Build the list */
@@ -895,17 +917,19 @@ static BezTriple **action_to_keylist(bAction *act, int flags, int *totvert)
                        count=0;
                        
                        for (achan=act->chanbase.first; achan; achan=achan->next){
-                               /* Add transformation keys */
-                               for (icu=achan->ipo->curve.first; icu; icu=icu->next){
-                                       for (v=0; v<icu->totvert; v++)
-                                               list[count++]=&icu->bezt[v];
-                               }
-                                       
-                                       /* Add constraint keys */
-                               for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next){
-                                       for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
+                               if(achan->ipo) {
+                                       /* Add transformation keys */
+                                       for (icu=achan->ipo->curve.first; icu; icu=icu->next){
                                                for (v=0; v<icu->totvert; v++)
                                                        list[count++]=&icu->bezt[v];
+                                       }
+                               }                                       
+                                       /* Add constraint keys */
+                               for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next){
+                                       if(conchan->ipo)
+                                               for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
+                                                       for (v=0; v<icu->totvert; v++)
+                                                               list[count++]=&icu->bezt[v];
                                }
                                                        
                        }               
index f4e416e4fb55581b43655cab853eebccc4dfbfeb..f7870fda239fc5229c1341590d0b8b4f9aff523b 100644 (file)
 #define ISPOIN4(a, b, c, d, e)        ( (a->b) && (a->c) && (a->d) && (a->e) )   
 
 #define IPOBUTX        65
-#define IPOSTEP 35                     /* minimum pixels per gridstep */
+               /* minimum pixels per gridstep */
+#define IPOSTEP 35
 
 static float ipogrid_dx, ipogrid_dy, ipogrid_startx, ipogrid_starty;
 static int ipomachtx, ipomachty;
 
-static int vertymin, vertymax, horxmin, horxmax;       /* globals om LEFTMOUSE op scrollbar te testen */
+static int vertymin, vertymax, horxmin, horxmax;       /* globals to test LEFTMOUSE for scrollbar */
 
-extern short ACTWIDTH;
+extern short ACTWIDTH;         /* this is ugly! */
 
 static void scroll_prstr(float x, float y, float val, char dir, int disptype)
 {
@@ -313,7 +314,7 @@ void draw_ipogrid(void)
                        glRectf(0.0,  0.0,  100.0,  1.0); 
                        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
                }
-               else if(ELEM(G.sipo->blocktype, ID_CU, IPO_CO)) {
+               else if(ELEM(G.sipo->blocktype, ID_CU, ID_CO)) {
                        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
                        glRectf(0.0,  1.0,  G.v2d->cur.xmax,  1.0); 
                        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
@@ -594,12 +595,16 @@ void calc_scrollrcts(ScrArea *sa, View2D *v2d, int winx, int winy)
        v2d->mask.ymax= winy;
        
        if(sa->spacetype==SPACE_ACTION) {
-               v2d->mask.xmin+= ACTWIDTH;
-               v2d->hor.xmin+=ACTWIDTH;
+               if(sa->winx > ACTWIDTH+50) { 
+                       v2d->mask.xmin+= ACTWIDTH;
+                       v2d->hor.xmin+=ACTWIDTH;
+               }
        }
        else if(sa->spacetype==SPACE_NLA){
-               v2d->mask.xmin+= NLAWIDTH;
-               v2d->hor.xmin+=NLAWIDTH;
+               if(sa->winx > NLAWIDTH+50) { 
+                       v2d->mask.xmin+= NLAWIDTH;
+                       v2d->hor.xmin+=NLAWIDTH;
+               }
        }
        else if(sa->spacetype==SPACE_IPO) {
                v2d->mask.xmax-= IPOBUTX;
@@ -1688,7 +1693,7 @@ void do_ipobuts(unsigned short event)
                ei= get_active_editipo();
                if(ei) {
                        if(ei->icu==NULL) {
-                               ei->icu= get_ipocurve(G.sipo->from, G.sipo->blocktype, ei->adrcode, NULL);
+                               ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, ei->adrcode);
                                ei->flag |= IPO_SELECT;
                                ei->icu->flag= ei->flag;
                        }
@@ -2040,6 +2045,8 @@ int view2dzoom(unsigned short event)
        areawinset(curarea->win);       /* from buttons */
        curarea->head_swap= 0;
        getmouseco_areawin(mvalo);
+       mval[0]= mvalo[0];
+       mval[1]= mvalo[1];
        
        while( (get_mbut()&(L_MOUSE|M_MOUSE)) || (event==WHEELUPMOUSE) || (event==WHEELDOWNMOUSE) ) {
        
@@ -2130,11 +2137,23 @@ int view2dzoom(unsigned short event)
                                mvalo[1]= mval[1];
                        }
                        
-                       G.v2d->cur.xmin+= dx;
-                       G.v2d->cur.xmax-= dx;
-                       
-                       if ELEM5(curarea->spacetype, SPACE_SEQ, SPACE_SOUND, SPACE_ACTION, SPACE_NLA, SPACE_TIME);
+                       if( ELEM(curarea->spacetype, SPACE_NLA, SPACE_ACTION) ) {
+                               if(mvalo[0] < G.v2d->mask.xmin) {
+                                       G.v2d->cur.ymin+= dy;
+                                       G.v2d->cur.ymax-= dy;
+                               }
+                               else {
+                                       G.v2d->cur.xmin+= dx;
+                                       G.v2d->cur.xmax-= dx;
+                               }
+                       }
+                       else if (ELEM3(curarea->spacetype, SPACE_SEQ, SPACE_SOUND, SPACE_TIME)) {
+                               G.v2d->cur.xmin+= dx;
+                               G.v2d->cur.xmax-= dx;
+                       }
                        else {
+                               G.v2d->cur.xmin+= dx;
+                               G.v2d->cur.xmax-= dx;
                                G.v2d->cur.ymin+= dy;
                                G.v2d->cur.ymax-= dy;
                        }
@@ -2214,10 +2233,20 @@ int view2dmove(unsigned short event)
        
        if ELEM7(curarea->spacetype, SPACE_IPO, SPACE_SEQ, SPACE_OOPS, SPACE_SOUND, SPACE_ACTION, SPACE_NLA, SPACE_TIME) 
                {
+
                        if( BLI_in_rcti(&G.v2d->mask, (int)mvalo[0], (int)mvalo[1]) ) {
                                facx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/(float)(G.v2d->mask.xmax-G.v2d->mask.xmin);
                                facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
                        }
+                       /* stoopid exception to allow scroll in lefthand side */
+                       else if(curarea->spacetype==SPACE_ACTION && BLI_in_rcti(&G.v2d->mask, ACTWIDTH+(int)mvalo[0], (int)mvalo[1]) ) {
+                               facx= 0.0f;
+                               facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
+                       }
+                       else if(curarea->spacetype==SPACE_NLA && BLI_in_rcti(&G.v2d->mask, NLAWIDTH+(int)mvalo[0], (int)mvalo[1]) ) {
+                               facx= 0.0f;
+                               facy= (G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
+                       }
                        else if(IN_2D_VERT_SCROLL((int)mvalo)) {
                                facy= -(G.v2d->tot.ymax-G.v2d->tot.ymin)/(float)(G.v2d->mask.ymax-G.v2d->mask.ymin);
                                if(get_mbut() & mousebut) {
index 98969f795bf9cd9fa17d28a0c927b862c8b837f6..120ce5c3d8d90d540f0dd0a1b77647b4c5945f03 100644 (file)
@@ -56,6 +56,8 @@
 
 #include "BLI_blenlib.h"
 #include "MEM_guardedalloc.h"
+
+#include "BKE_action.h"
 #include "BKE_global.h"
 
 #include "BSE_drawnla.h"
 #include "blendef.h"
 #include "mydevice.h"
 
-/* Local function prototypes */
-static void draw_nlastrips(SpaceNla *snla);
-static void draw_nlatree(void);
-
-int count_nla_levels(void);
-int nla_filter (Base* base, int flags);
-
 #define TESTBASE_SAFE(base)    ((base)->flag & SELECT)
 
-/* Implementation */
-static void draw_nlatree(void)
+/* the left hand side with channels only */
+static void draw_nla_channels(void)
 {
-
-       short ofsx, ofsy = 0; 
+       bActionStrip *strip;
        Base *base;
+       Object *ob;
        float   x, y;
-       bActionStrip *strip;
-       bConstraintChannel *conchan;
+       short ofsx, ofsy = 0; 
 
        myortho2(0,     NLAWIDTH, G.v2d->cur.ymin, G.v2d->cur.ymax);    //      Scaling
 
@@ -111,14 +105,13 @@ static void draw_nlatree(void)
        glColor3ub(0x00, 0x00, 0x00);
        
        x = 0.0;
-
        y = count_nla_levels();
-
        y*= (NLACHANNELHEIGHT+NLACHANNELSKIP);
-
        
        for (base=G.scene->base.first; base; base=base->next){
-               if (nla_filter(base, 0)){               
+               if (nla_filter(base)) {
+                       ob= base->object;
+                       
                        BIF_ThemeColorShade(TH_HEADER, 20);
                        glRectf(x,  y-NLACHANNELHEIGHT/2,  (float)NLAWIDTH,  y+NLACHANNELHEIGHT/2);
 
@@ -127,63 +120,56 @@ static void draw_nlatree(void)
                                BIF_ThemeColor(TH_TEXT_HI);
                        else
                                BIF_ThemeColor(TH_TEXT);
-                       glRasterPos2f(x+16,  y-4);
+                       glRasterPos2f(x+21,  y-4);
 
-                       BMF_DrawString(G.font, base->object->id.name+2);
+                       BMF_DrawString(G.font, ob->id.name+2);
                        
-                       /* Draw the constraint ipos */
-                       for (conchan = base->object->constraintChannels.first; conchan; conchan=conchan->next){
-                               y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
-                               BIF_ThemeColorShade(TH_HEADER, -30);
+                       /* icon to indicate nla or action */
+                       if(ob->nlastrips.first && ob->action) {
+                               if(ob->nlaflag & OB_NLA_OVERRIDE)
+                                       BIF_draw_icon(x+5, y-8, ICON_NLA);
+                               else
+                                       BIF_draw_icon(x+5, y-8, ICON_ACTION);
+                       }                       
+                       y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
+                       
+                       /* Draw the action timeline */
+                       if (ob->action){
+                               BIF_ThemeColorShade(TH_HEADER, -20);
                                glRectf(x+16,  y-NLACHANNELHEIGHT/2,  (float)NLAWIDTH,  y+NLACHANNELHEIGHT/2);
-                               
-                               if (conchan->flag & CONSTRAINT_CHANNEL_SELECT)
+
+                               if (TESTBASE_SAFE(base))
                                        BIF_ThemeColor(TH_TEXT_HI);
                                else
                                        BIF_ThemeColor(TH_TEXT);
-
                                glRasterPos2f(x+32,  y-4);
-                               BMF_DrawString(G.font, conchan->name);
-                       }
-       
-                       /* Draw the action timeline */
-                       if (ACTIVE_ARMATURE(base)){
-                               BIF_draw_icon(x, y-8, ICON_DOWNARROW_HLT);
-                               y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
+                               BMF_DrawString(G.font, ob->action->id.name+2);
                                
-                               if (base->object->action){
-                                       BIF_ThemeColorShade(TH_HEADER, -30);
-                                       glRectf(x+16,  y-NLACHANNELHEIGHT/2,  (float)NLAWIDTH,  y+NLACHANNELHEIGHT/2);
-
-                                       if (TESTBASE_SAFE(base))
-                                               BIF_ThemeColor(TH_TEXT_HI);
-                                       else
-                                               BIF_ThemeColor(TH_TEXT);
-                                       glRasterPos2f(x+32,  y-4);
-                                       BMF_DrawString(G.font, base->object->action->id.name+2);
-                               }
+                               y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
                        }
-                       y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
 
                        /* Draw the nla strips */
-                       if (base->object->type==OB_ARMATURE){
-                               for (strip = base->object->nlastrips.first; strip; strip=strip->next){
-                                       BIF_ThemeColorShade(TH_HEADER, -50);
-                                       glRectf(x+32,  y-NLACHANNELHEIGHT/2,  (float)NLAWIDTH,  y+NLACHANNELHEIGHT/2);
-
-                                       if (TESTBASE_SAFE(base))
-                                               BIF_ThemeColor(TH_TEXT_HI);
-                                       else
-                                               BIF_ThemeColor(TH_TEXT);
-
-       // why this test? check freeing mem when deleting strips? (ton)
-                                       if(strip->act) {
-                                               glRasterPos2f(x+48,  y-4);
-                                               BMF_DrawString(G.font, strip->act->id.name+2);
-
-                                               y-=(NLACHANNELHEIGHT+NLACHANNELSKIP);
+                       for (strip = ob->nlastrips.first; strip; strip=strip->next){
+                               BIF_ThemeColorShade(TH_HEADER, -40);
+                               glRectf(x+32,  y-NLACHANNELHEIGHT/2,  (float)NLAWIDTH,  y+NLACHANNELHEIGHT/2);
+
+                               if (TESTBASE_SAFE(base))
+                                       BIF_ThemeColor(TH_TEXT_HI);
+                               else
+                                       BIF_ThemeColor(TH_TEXT);
+
+                               // why this test? check freeing mem when deleting strips? (ton)
+                               if(strip->act) {
+                                       glRasterPos2f(x+48,  y-4);
+                                       BMF_DrawString(G.font, strip->act->id.name+2);
+                                       
+                                       if(strip->flag & ACTSTRIP_ACTIVE) {
+                                               glEnable(GL_BLEND);
+                                               BIF_draw_icon_blended(x+16, y-8, ICON_DOT, TH_BACK, 0);
+                                               glDisable(GL_BLEND);
                                        }
                                }
+                               y-=(NLACHANNELHEIGHT+NLACHANNELSKIP);
                        }
                }
        }
@@ -191,12 +177,29 @@ static void draw_nlatree(void)
        myortho2(0,     NLAWIDTH, 0, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin));        //      Scaling
 }
 
-static void draw_nlastrips(SpaceNla *snla)
+void map_active_strip(gla2DDrawInfo *di, Object *ob, int restore)
 {
+       static rctf stored;
+       
+       if(restore)
+               gla2DSetMap(di, &stored);
+       else {
+               rctf map;
+               
+               gla2DGetMap(di, &stored);
+               map= stored;
+               map.xmin= get_action_frame(ob, map.xmin);
+               map.xmax= get_action_frame(ob, map.xmax);
+               gla2DSetMap(di, &map);
+       }
+}
+
+/* the right hand side, with strips and keys */
+static void draw_nla_strips_keys(SpaceNla *snla)
+{
+       Base *base;
        rcti scr_rct;
        gla2DDrawInfo *di;
-       Base *base;
-       bConstraintChannel *conchan;
        float   y;
        char col1[3], col2[3];
        
@@ -205,7 +208,7 @@ static void draw_nlastrips(SpaceNla *snla)
        
        /* Draw strips */
 
-       scr_rct.xmin= snla->area->winrct.xmin + NLAWIDTH;
+       scr_rct.xmin= snla->area->winrct.xmin + snla->v2d.mask.xmin;
        scr_rct.ymin= snla->area->winrct.ymin + snla->v2d.mask.ymin;
        scr_rct.xmax= snla->area->winrct.xmin + snla->v2d.hor.xmax;
        scr_rct.ymax= snla->area->winrct.ymin + snla->v2d.mask.ymax; 
@@ -215,13 +218,12 @@ static void draw_nlastrips(SpaceNla *snla)
        y*= (NLACHANNELHEIGHT+NLACHANNELSKIP);
        
        for (base=G.scene->base.first; base; base=base->next){
-               Object *ob;
+               Object *ob= base->object;
                bActionStrip *strip;
                int frame1_x, channel_y;
                
-               ob=base->object;
-               
-               if (nla_filter(base, 0)){
+               if (nla_filter(base)) {
+                       
                        /* Draw the field */
                        glEnable (GL_BLEND);
                        if (TESTBASE_SAFE(base))
@@ -241,42 +243,14 @@ static void draw_nlastrips(SpaceNla *snla)
                        
                        glDisable (GL_BLEND);
                        
-                       /* Draw the ipo */
+                       /* Draw the ipo keys */
                        draw_object_channel(di, ob, 0, y);
-                       y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
                        
-                       /* Draw the constraints */
-                       for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next){
-                               glEnable (GL_BLEND);
-                               if (conchan->flag & CONSTRAINT_CHANNEL_SELECT)
-                                       glColor4ub (col1[0], col1[1], col1[2], 0x22);
-                               else
-                                       glColor4ub (col2[0], col2[1], col2[2], 0x22);
-                               
-                               gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
-                               glRectf(0,  channel_y-NLACHANNELHEIGHT/2+4,  frame1_x,  channel_y+NLACHANNELHEIGHT/2-4);
-                               
-                               
-                               if (conchan->flag & CONSTRAINT_CHANNEL_SELECT)
-                                       glColor4ub (col1[0], col1[1], col1[2], 0x44);
-                               else
-                                       glColor4ub (col2[0], col2[1], col2[2], 0x44);
-                               glRectf(frame1_x,  channel_y-NLACHANNELHEIGHT/2+4,   G.v2d->hor.xmax,  channel_y+NLACHANNELHEIGHT/2-4);
-                               
-                               glDisable (GL_BLEND);
-                               
-                               /* Draw the ipo */
-                               draw_ipo_channel(di, conchan->ipo, 0, y);
-                               y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
-
-                       }
+                       y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
                }
-               
-               
-               
-               
+                               
                /* Draw the action strip */
-               if (ACTIVE_ARMATURE(base)){
+               if (ob->action){
                        
                        /* Draw the field */
                        glEnable (GL_BLEND);
@@ -284,10 +258,10 @@ static void draw_nlastrips(SpaceNla *snla)
                                glColor4ub (col1[0], col1[1], col1[2], 0x22);
                        else
                                glColor4ub (col2[0], col2[1], col2[2], 0x22);
+                       
                        gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
                        glRectf(0,  channel_y-NLACHANNELHEIGHT/2+4,  frame1_x,  channel_y+NLACHANNELHEIGHT/2-4);
                        
-                       
                        if (TESTBASE_SAFE(base))
                                glColor4ub (col1[0], col1[1], col1[2], 0x44);
                        else
@@ -296,107 +270,108 @@ static void draw_nlastrips(SpaceNla *snla)
                        
                        glDisable (GL_BLEND);
                        
-                       /* Draw the action keys */
+                       /* Draw the action keys, optionally corrected for active strip */
+                       map_active_strip(di, ob, 0);
                        draw_action_channel(di, ob->action, 0, y);
-
+                       map_active_strip(di, ob, 1);
+                       
                        y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
                        
                }
 
                /* Draw the nla strips */
-               if (ob->type==OB_ARMATURE){
-                       for (strip=ob->nlastrips.first; strip; strip=strip->next){
-                               int stripstart, stripend;
-                               int blendstart, blendend;
-                               unsigned char r, g, b;
-                               
-                               /* Draw rect */
-                               if (strip->flag & ACTSTRIP_SELECT){
-                                       r= 0xff; g= 0xff; b= 0xaa;
-                               }
-                               else{
-                                       r= 0xe4; g= 0x9c; b= 0xc6;
-                               }
-                               
-                               glColor4ub (r, g, b, 0xFF);
+               for (strip=ob->nlastrips.first; strip; strip=strip->next){
+                       int stripstart, stripend;
+                       int blendstart, blendend;
+                       
+                       /* Draw rect */
+                       if (strip->flag & ACTSTRIP_SELECT)
+                               BIF_ThemeColor(TH_STRIP_SELECT);
+                       else
+                               BIF_ThemeColor(TH_STRIP);
+                       
+                       gla2DDrawTranslatePt(di, strip->start+strip->blendin, y, &stripstart, &channel_y);
+                       gla2DDrawTranslatePt(di, strip->end-strip->blendout, y, &stripend, &channel_y);
+                       glRectf(stripstart,  channel_y-NLACHANNELHEIGHT/2+3,  stripend,  channel_y+NLACHANNELHEIGHT/2-3);
+                       
+                       if (strip->flag & ACTSTRIP_SELECT)
+                               BIF_ThemeColorShade(TH_STRIP_SELECT, -60);
+                       else
+                               BIF_ThemeColorShade(TH_STRIP, -60);
+                       
+                       /* Draw blendin */
+                       if (strip->blendin>0){
+                               glBegin(GL_TRIANGLES);
                                
-                               gla2DDrawTranslatePt(di, strip->start+strip->blendin, y, &stripstart, &channel_y);
-                               gla2DDrawTranslatePt(di, strip->end-strip->blendout, y, &stripend, &channel_y);
-                               glRectf(stripstart,  channel_y-NLACHANNELHEIGHT/2+3,  stripend,  channel_y+NLACHANNELHEIGHT/2-3);
+                               gla2DDrawTranslatePt(di, strip->start, y, &blendstart, &channel_y);
                                
+                               glVertex2f(blendstart, channel_y-NLACHANNELHEIGHT/2+3);
+                               glVertex2f(stripstart, channel_y+NLACHANNELHEIGHT/2-3);
+                               glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
                                
-                               /* Draw blendin */
-                               if (strip->blendin>0){
-                                       glBegin(GL_TRIANGLES);
-                                       
-                                       gla2DDrawTranslatePt(di, strip->start, y, &blendstart, &channel_y);
-                                       
-                                       glColor4ub (r*0.75, g*0.75, b*0.75, 0xFF);
-                                       glVertex2f(blendstart, channel_y-NLACHANNELHEIGHT/2+3);
-                                       glVertex2f(stripstart, channel_y+NLACHANNELHEIGHT/2-3);
-                                       glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
-                                       
-                                       
-                                       glEnd();
-                               }
-                               if (strip->blendout>0){
-                                       glBegin(GL_TRIANGLES);
-                                       gla2DDrawTranslatePt(di, strip->end, y, &blendend, &channel_y);
-                                       glColor4ub (r*0.75, g*0.75, b*0.75, 0xFF);
-                                       glVertex2f(blendend, channel_y-NLACHANNELHEIGHT/2+3);
-                                       glVertex2f(stripend, channel_y+NLACHANNELHEIGHT/2-3);
-                                       glVertex2f(stripend, channel_y-NLACHANNELHEIGHT/2+3);
-                                       glEnd();
-                               }
                                
-                               /* Draw border */
-                               glBegin(GL_LINE_STRIP);
-                               glColor4f(1, 1, 1, 0.5); 
-                               gla2DDrawTranslatePt(di, strip->start, y, &stripstart, &channel_y);
-                               gla2DDrawTranslatePt(di, strip->end, y, &stripend, &channel_y);
+                               glEnd();
+                       }
+                       if (strip->blendout>0){
+                               glBegin(GL_TRIANGLES);
                                
-                               glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
-                               glVertex2f(stripstart, channel_y+NLACHANNELHEIGHT/2-3);
+                               gla2DDrawTranslatePt(di, strip->end, y, &blendend, &channel_y);
+
+                               glVertex2f(blendend, channel_y-NLACHANNELHEIGHT/2+3);
                                glVertex2f(stripend, channel_y+NLACHANNELHEIGHT/2-3);
-                               glColor4f(0, 0, 0, 0.5); 
                                glVertex2f(stripend, channel_y-NLACHANNELHEIGHT/2+3);
-                               glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
                                glEnd();
-                               
-                               glEnable (GL_BLEND);
+                       }
+                       
+                       /* Draw border */
+                       glBegin(GL_LINE_STRIP);
+                       glColor4f(1, 1, 1, 0.5); 
+                       gla2DDrawTranslatePt(di, strip->start, y, &stripstart, &channel_y);
+                       gla2DDrawTranslatePt(di, strip->end, y, &stripend, &channel_y);
+                       
+                       glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
+                       glVertex2f(stripstart, channel_y+NLACHANNELHEIGHT/2-3);
+                       glVertex2f(stripend, channel_y+NLACHANNELHEIGHT/2-3);
+                       glColor4f(0, 0, 0, 0.5); 
+                       glVertex2f(stripend, channel_y-NLACHANNELHEIGHT/2+3);
+                       glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
+                       glEnd();
+                       
+                       glEnable (GL_BLEND);
 
-                               /* Show strip extension */
-                               if (strip->flag & ACTSTRIP_HOLDLASTFRAME){
-                                       glColor4ub (r, g, b, 0x55);
-                                       
-                                       glRectf(stripend,  channel_y-NLACHANNELHEIGHT/2+4,  G.v2d->hor.xmax,  channel_y+NLACHANNELHEIGHT/2-2);
-                               }
+                       /* Show strip extension */
+                       if (strip->flag & ACTSTRIP_HOLDLASTFRAME){
+                               if (strip->flag & ACTSTRIP_SELECT)
+                                       BIF_ThemeColorShadeAlpha(TH_STRIP_SELECT, 0, -180);
+                               else
+                                       BIF_ThemeColorShadeAlpha(TH_STRIP, 0, -180);
                                
-                               /* Show repeat */
-                               if (strip->repeat > 1.0 && !(strip->flag & ACTSTRIP_USESTRIDE)){
-                                       float rep = 1;
-                                       glBegin(GL_LINES);
-                                       while (rep<strip->repeat){
-                                               /* Draw line */ 
-                                               glColor4f(0, 0, 0, 0.5); 
-                                               gla2DDrawTranslatePt(di, strip->start+(rep*((strip->end-strip->start)/strip->repeat)), y, &frame1_x, &channel_y);
-                                               glVertex2f(frame1_x, channel_y-NLACHANNELHEIGHT/2+4);
-                                               glVertex2f(frame1_x, channel_y+NLACHANNELHEIGHT/2-2);
-                                               
-                                               glColor4f(1.0, 1.0, 1.0, 0.5); 
-                                               gla2DDrawTranslatePt(di, strip->start+(rep*((strip->end-strip->start)/strip->repeat)), y, &frame1_x, &channel_y);
-                                               glVertex2f(frame1_x+1, channel_y-NLACHANNELHEIGHT/2+4);
-                                               glVertex2f(frame1_x+1, channel_y+NLACHANNELHEIGHT/2-2);
-                                               rep+=1.0;
-                                       }
-                                       glEnd();
+                               glRectf(stripend,  channel_y-NLACHANNELHEIGHT/2+4,  G.v2d->hor.xmax,  channel_y+NLACHANNELHEIGHT/2-2);
+                       }
+                       
+                       /* Show repeat */
+                       if (strip->repeat > 1.0 && !(strip->flag & ACTSTRIP_USESTRIDE)){
+                               float rep = 1;
+                               glBegin(GL_LINES);
+                               while (rep<strip->repeat){
+                                       /* Draw line */ 
+                                       glColor4f(0, 0, 0, 0.5); 
+                                       gla2DDrawTranslatePt(di, strip->start+(rep*((strip->end-strip->start)/strip->repeat)), y, &frame1_x, &channel_y);
+                                       glVertex2f(frame1_x, channel_y-NLACHANNELHEIGHT/2+4);
+                                       glVertex2f(frame1_x, channel_y+NLACHANNELHEIGHT/2-2);
                                        
+                                       glColor4f(1.0, 1.0, 1.0, 0.5); 
+                                       gla2DDrawTranslatePt(di, strip->start+(rep*((strip->end-strip->start)/strip->repeat)), y, &frame1_x, &channel_y);
+                                       glVertex2f(frame1_x+1, channel_y-NLACHANNELHEIGHT/2+4);
+                                       glVertex2f(frame1_x+1, channel_y+NLACHANNELHEIGHT/2-2);
+                                       rep+=1.0;
                                }
-                               glDisable (GL_BLEND);
+                               glEnd();
                                
-                               y-=(NLACHANNELHEIGHT+NLACHANNELSKIP);
                        }
+                       glDisable (GL_BLEND);
                        
+                       y-=(NLACHANNELHEIGHT+NLACHANNELSKIP);
                }
        }
        glaEnd2DDraw(di);
@@ -407,18 +382,16 @@ static void draw_nlastrips(SpaceNla *snla)
 
 #define B_NLA_PANEL            121
 
-static bActionStrip *get_active_nlastrip(void)
 /* For now just returns the first selected strip */
+bActionStrip *get_active_nlastrip(void)
 {
        Base *base;
        bActionStrip *strip;
        
        for (base=G.scene->base.first; base; base=base->next){
-               if (nla_filter(base, 0) && base->object->type==OB_ARMATURE){
-                       for (strip=base->object->nlastrips.first; strip; strip=strip->next){
-                               if (strip->flag & ACTSTRIP_SELECT)
-                                       return strip;
-                       }
+               for (strip=base->object->nlastrips.first; strip; strip=strip->next){
+                       if (strip->flag & ACTSTRIP_SELECT)
+                               return strip;
                }
        }
        
@@ -478,30 +451,30 @@ static void nla_panel_properties(short cntrl)     // NLA_HANDLER_PROPERTIES
        strip = get_active_nlastrip();
        if (!strip) return;
        
-       // first labels, for simpler align code :)
+       /* first labels, for simpler align code :) */
        uiDefBut(block, LABEL, 0, "Timeline Range:",    10,180,300,19, 0, 0, 0, 0, 0, "");
        uiDefBut(block, LABEL, 0, "Action Range:",              10,140,300,19, 0, 0, 0, 0, 0, "");
        uiDefBut(block, LABEL, 0, "Blending:",                  10,100,300,19, 0, 0, 0, 0, 0, "");
        uiDefBut(block, LABEL, 0, "Options:",                   10,60,300,19, 0, 0, 0, 0, 0, "");
 
        uiBlockBeginAlign(block);
-       uiDefButF(block, NUM, B_REDR, "Strip Start:", 10,160,150,19, &strip->start, 1.0, MAXFRAMEF, 100, 0, "First frame in the timeline");
-       uiDefButF(block, NUM, B_REDR, "Strip End:",     160,160,150,19, &strip->end, 1.0, MAXFRAMEF, 100, 0, "Last frame in the timeline");
+       uiDefButF(block, NUM, B_REDR, "Strip Start:", 10,160,150,19, &strip->start, -1000.0, MAXFRAMEF, 100, 0, "First frame in the timeline");
+       uiDefButF(block, NUM, B_REDR, "Strip End:",     160,160,150,19, &strip->end, -1000.0, MAXFRAMEF, 100, 0, "Last frame in the timeline");
 
        uiBlockBeginAlign(block);
        uiDefButF(block, NUM, B_REDR, "Action Start:", 10,120,150,19, &strip->actstart, 1.0, MAXFRAMEF, 100, 0, "First frame of the action to map to the playrange");
        uiDefButF(block, NUM, B_REDR, "Action End:", 160,120,150,19, &strip->actend, 1.0, MAXFRAMEF, 100, 0, "Last frame of the action to map to the playrange");
 
        uiBlockBeginAlign(block);
-       uiDefButF(block, NUM, B_REDR, "Blendin:",       10,80,150,19, &strip->blendin, 0.0, MAXFRAMEF, 100, 0, "Number of frames of ease-in");
-       uiDefButF(block, NUM, B_REDR, "Blendout:",      160,80,150,19, &strip->blendout, 0.0, MAXFRAMEF, 100, 0, "Number of frames of ease-out");
+       uiDefButF(block, NUM, B_REDR, "Blendin:",       10,80,150,19, &strip->blendin, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-in");
+       uiDefButF(block, NUM, B_REDR, "Blendout:",      160,80,150,19, &strip->blendout, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-out");
 
        uiBlockBeginAlign(block);
-       uiDefButF(block, NUM, B_REDR, "Repeat:",        10,40,150,19, &strip->repeat, 0.0001, MAXFRAMEF, 100, 0, "Number of times the action should repeat");
-       uiDefButF(block, NUM, B_REDR, "Stride:",        160,40,150,19, &strip->stridelen, 0.0001, MAXFRAMEF, 100, 0, "Distance covered by one complete cycle of the action specified in the Action Range");
+       uiDefButF(block, NUM, B_REDR, "Repeat:",        10,40,150,19, &strip->repeat, 0.0001, 1000.0f, 100, 0, "Number of times the action should repeat");
+       uiDefButF(block, NUM, B_REDR, "Stride:",        160,40,150,19, &strip->stridelen, 0.0001, 1000.0, 100, 0, "Distance covered by one complete cycle of the action specified in the Action Range");
 
        uiBlockBeginAlign(block);
-       uiDefButBitS(block, TOG, ACTSTRIP_USESTRIDE, B_REDR, "Use Path",        10,0,100,19, &strip->flag, 0, 0, 0, 0, "Plays action based on path position & stride. Only armatures parented to a path");
+       uiDefButBitS(block, TOG, ACTSTRIP_USESTRIDE, B_REDR, "Use Path",        10,0,100,19, &strip->flag, 0, 0, 0, 0, "Plays action based on path position & stride");
        uiDefButBitS(block, TOG, ACTSTRIP_HOLDLASTFRAME, B_REDR, "Hold",        110,0,100,19, &strip->flag, 0, 0, 0, 0, "Toggles whether to continue displaying the last frame past the end of the strip");
        uiDefButS(block, TOG, B_REDR, "Add",    210,0,100,19, &strip->mode, 0, 0, 0, 0, "Toggles additive blending mode");
 }
@@ -563,8 +536,8 @@ void drawnlaspace(ScrArea *sa, void *spacedata)
        calc_ipogrid(); 
        draw_ipogrid();
 
-       /* Draw channel strips */
-       draw_nlastrips(G.snla);
+       /* the right hand side, with strips and keys */
+       draw_nla_strips_keys(G.snla);
 
        /* Draw current frame */
        glViewport(ofsx+G.v2d->mask.xmin,  ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1); 
@@ -578,10 +551,10 @@ void drawnlaspace(ScrArea *sa, void *spacedata)
                myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
                if(G.v2d->scroll) drawscroll(0);
        }
-
-       /* Draw channel names */
-       draw_nlatree();
-
+       if(G.v2d->mask.xmin!=0) {
+               /* Draw channel names */
+               draw_nla_channels();
+       }
        mywinset(curarea->win); // reset scissor too
        myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
        draw_area_emboss(sa);
@@ -598,48 +571,36 @@ int count_nla_levels(void)
        Base *base;
        int y=0;
 
-       for (y=0, base=G.scene->base.first; base; base=base->next)
-       {
-               if (nla_filter(base,0 )){
-                       /*      Ipo     */
+       for (y=0, base=G.scene->base.first; base; base=base->next) {
+               if (nla_filter(base)) {
+                       /* object level */
                        y++;
-                       /*      Constraint channels */
-                       y+=BLI_countlist(&base->object->constraintChannels);
-
-                       if (base->object->type==OB_ARMATURE){
-                               /* Action */
-                               if(base->object->action){
-                               //      bActionChannel *achan;
-                                       y++;
-
-                               //      for (achan=base->object->action->chanbase.first; achan; achan=achan->next){
-                               //              y+=BLI_countlist(&achan->constraintChannels);
-                               //      }
-                               }
-                               /* Nla strips */
-                               y+= BLI_countlist(&base->object->nlastrips);
-                       }
+
+                       if(base->object->action)
+                               y++;
+                       
+                       /* Nla strips */
+                       y+= BLI_countlist(&base->object->nlastrips);
                }
        }
 
        return y;
 }
 
-int nla_filter (Base* base, int flags)
+int nla_filter (Base *base)
 {
        Object *ob = base->object;
+       
+       if(ob->action || ob->nlastrips.first) 
+               return 1;
 
-       /* Only objects with ipos */
+       /* should become option */
        if (ob->ipo)
                return 1;
 
        if (ob->constraintChannels.first)
                return 1;
 
-       /* Only armatures */
-       if (ob->type==OB_ARMATURE)
-               return 1;
-
-       else return 0;
+       return 0;
 }
 
index 00c2e43833900eadbf57ca4834c19d96202aa28c..2eb19db36fb8c9a65e5c8d4983d7cdbf0a62d1d8 100644 (file)
@@ -255,14 +255,15 @@ static void draw_ob_keys()
                                        /* go through each channel in the action */
                                        for (achan=act->chanbase.first; achan; achan=achan->next){
                                                /* convert the ipo to a list of 'current frame elements' */
-                                               
-                                               elems.first= elems.last= NULL;
-                                               make_cfra_list(achan->ipo, &elems);
-
-                                               col[0] = 0x00; col[1] = 0x82; col[2] = 0x8B;
-                                               draw_key_list(elems, col);
-                                               
-                                               BLI_freelistN(&elems);
+                                               if(achan->ipo) {
+                                                       elems.first= elems.last= NULL;
+                                                       make_cfra_list(achan->ipo, &elems);
+
+                                                       col[0] = 0x00; col[1] = 0x82; col[2] = 0x8B;
+                                                       draw_key_list(elems, col);
+                                                       
+                                                       BLI_freelistN(&elems);
+                                               }
                                        }
                                }
                                
index 6dad0f8eb88ec423b6e16df2d19971b3539b5afb..44f16abe886e8eb17452b9efb14b962804581511 100644 (file)
@@ -55,6 +55,7 @@
 #include "DNA_constraint_types.h"
 #include "DNA_key_types.h"
 #include "DNA_mesh_types.h"
+#include "DNA_nla_types.h"
 #include "DNA_lattice_types.h"
 
 #include "BKE_action.h"
@@ -98,9 +99,7 @@ extern int count_action_levels (bAction *act);
 #define BEZSELECTED(bezt)   (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
 
 /* Local Function prototypes, are forward needed */
-static void insertactionkey(bAction *act, bActionChannel *achan, bPoseChannel *chan, int adrcode, short makecurve, float time);
 static void hilight_channel (bAction *act, bActionChannel *chan, short hilight);
-static void set_action_key_time (bAction *act, bPoseChannel *chan, int adrcode, short makecurve, float time);
 
 static void up_sel_action(void);
 static void down_sel_action(void);
@@ -137,6 +136,7 @@ bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance)
        bActionChannel *achan;
        bAction                 *temp;
        bPoseChannel    *pchan;
+       ID                              *id;
        float                   actlen;
        int                             oldframe;
        int                             curframe;
@@ -144,7 +144,7 @@ bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance)
 
        if (!act)
                return NULL;
-
+       
        arm = get_armature(armob);
 
        if (G.obedit){
@@ -158,7 +158,8 @@ bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance)
        }
        
        /* Get a new action */
-       result = add_empty_action();
+       result = add_empty_action(ID_PO);
+       id= (ID *)armob;
 
        /* Assign the new action a unique name */
        sprintf (newname, "%s.BAKED", act->id.name+2);
@@ -169,7 +170,7 @@ bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance)
        oldframe = G.scene->r.cfra;
 
        temp = armob->action;
-       armob->action = act;
+       armob->action = result;
        
        for (curframe=1; curframe<ceil(actlen+1); curframe++){
 
@@ -186,16 +187,16 @@ bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance)
                for (pchan=armob->pose->chanbase.first; pchan; pchan=pchan->next){
 
                        /* Apply to keys */
-                       set_action_key_time (result, pchan, AC_QUAT_X, 1, curframe);
-                       set_action_key_time (result, pchan, AC_QUAT_Y, 1, curframe);
-                       set_action_key_time (result, pchan, AC_QUAT_Z, 1, curframe);
-                       set_action_key_time (result, pchan, AC_QUAT_W, 1, curframe);
-                       set_action_key_time (result, pchan, AC_LOC_X, 1, curframe);
-                       set_action_key_time (result, pchan, AC_LOC_Y, 1, curframe);
-                       set_action_key_time (result, pchan, AC_LOC_Z, 1, curframe);
-                       set_action_key_time (result, pchan, AC_SIZE_X, 1, curframe);
-                       set_action_key_time (result, pchan, AC_SIZE_Y, 1, curframe);
-                       set_action_key_time (result, pchan, AC_SIZE_Z, 1, curframe);
+                       insertkey(id, ID_AC, pchan->name, NULL, AC_LOC_X);
+                       insertkey(id, ID_AC, pchan->name, NULL, AC_LOC_Y);
+                       insertkey(id, ID_AC, pchan->name, NULL, AC_LOC_Z);
+                       insertkey(id, ID_AC, pchan->name, NULL, AC_QUAT_X);
+                       insertkey(id, ID_AC, pchan->name, NULL, AC_QUAT_Y);
+                       insertkey(id, ID_AC, pchan->name, NULL, AC_QUAT_Z);
+                       insertkey(id, ID_AC, pchan->name, NULL, AC_QUAT_W);
+                       insertkey(id, ID_AC, pchan->name, NULL, AC_SIZE_X);
+                       insertkey(id, ID_AC, pchan->name, NULL, AC_SIZE_Y);
+                       insertkey(id, ID_AC, pchan->name, NULL, AC_SIZE_Z);
                }
        }
 
@@ -203,8 +204,10 @@ bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance)
        /* Make another pass to ensure all keyframes are set to linear interpolation mode */
        for (achan = result->chanbase.first; achan; achan=achan->next){
                IpoCurve* icu;
-               for (icu = achan->ipo->curve.first; icu; icu=icu->next){
-                       icu->ipo= IPO_LIN;
+               if(achan->ipo) {
+                       for (icu = achan->ipo->curve.first; icu; icu=icu->next){
+                               icu->ipo= IPO_LIN;
+                       }
                }
        }
 
@@ -231,7 +234,6 @@ void select_actionchannel_by_name (bAction *act, char *name, int select)
 
        for (chan = act->chanbase.first; chan; chan=chan->next){
                if (!strcmp (chan->name, name)){
-                       act->achan = chan;
                        if (select){
                                chan->flag |= ACHAN_SELECTED;
                                hilight_channel (act, chan, 1);
@@ -322,25 +324,27 @@ void duplicate_actionchannel_keys(void)
                        duplicate_ipo_keys(conchan->ipo);
        }
 
-       transform_actionchannel_keys ('g');
+       transform_actionchannel_keys ('g', 0);
 }
 
-static bActionChannel *get_nearest_actionchannel_key (float *index, short *sel, bConstraintChannel **rchan){
+static bActionChannel *get_nearest_actionchannel_key (float *index, short *sel, bConstraintChannel **rchan)
+{
        bAction *act;
        bActionChannel *chan;
        IpoCurve *icu;
        bActionChannel *firstchan=NULL;
        bConstraintChannel *conchan, *firstconchan=NULL;
-       int     foundsel=0;
+       rctf    rectf;
        float firstvert=-1, foundx=-1;
-               int i;
+       float ymin, ymax, xmin, xmax;
+       int i;
+       int     foundsel=0;
        short mval[2];
-       float ymin, ymax;
-       rctf    rectf;
+       
        *index=0;
 
        *rchan=NULL;
-       act=G.saction->action; /* We presume that we are only called during a valid action */
+       act= G.saction->action; /* We presume that we are only called during a valid action */
        
        getmouseco_areawin (mval);
 
@@ -352,16 +356,26 @@ static bActionChannel *get_nearest_actionchannel_key (float *index, short *sel,
        ymax = count_action_levels(act) * (CHANNELHEIGHT + CHANNELSKIP);
        ymax += CHANNELHEIGHT/2;
        
+       /* if action is mapped in NLA, it returns a correction */
+       if(G.saction->pin==0 && OBACT) {
+               xmin= get_action_frame(OBACT, rectf.xmin);
+               xmax= get_action_frame(OBACT, rectf.xmax);
+       }
+       else {
+               xmin= rectf.xmin;
+               xmax= rectf.xmax;
+       }
+       
        *sel=0;
 
        for (chan=act->chanbase.first; chan; chan=chan->next){
 
                /* Check action channel */
                ymin= ymax-(CHANNELHEIGHT+CHANNELSKIP);
-               if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){
+               if (!((ymax < rectf.ymin) || (ymin > rectf.ymax)) && chan->ipo){
                        for (icu=chan->ipo->curve.first; icu; icu=icu->next){
                                for (i=0; i<icu->totvert; i++){
-                                       if (icu->bezt[i].vec[1][0] > rectf.xmin && icu->bezt[i].vec[1][0] <= rectf.xmax ){
+                                       if (icu->bezt[i].vec[1][0] > xmin && icu->bezt[i].vec[1][0] <= xmax ){
                                                if (!firstchan){
                                                        firstchan=chan;
                                                        firstvert=icu->bezt[i].vec[1][0];
@@ -388,10 +402,10 @@ static bActionChannel *get_nearest_actionchannel_key (float *index, short *sel,
                /* Check constraint channels */
                for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
                        ymin=ymax-(CHANNELHEIGHT+CHANNELSKIP);
-                       if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){
+                       if (!((ymax < rectf.ymin) || (ymin > rectf.ymax)) && conchan->ipo) {
                                for (icu=conchan->ipo->curve.first; icu; icu=icu->next){
                                        for (i=0; i<icu->totvert; i++){
-                                               if (icu->bezt[i].vec[1][0] > rectf.xmin && icu->bezt[i].vec[1][0] <= rectf.xmax ){
+                                               if (icu->bezt[i].vec[1][0] > xmin && icu->bezt[i].vec[1][0] <= xmax ){
                                                        if (!firstchan){
                                                                firstchan=chan;
                                                                firstconchan=conchan;
@@ -550,13 +564,11 @@ static void mouse_action(int selectmode)
 
        if (chan){
                if (selectmode == SELECT_REPLACE) {
-                       if (sel == 0)
-                               selectmode = SELECT_ADD;
-                       else
-                               selectmode = SELECT_SUBTRACT;
+                       selectmode = SELECT_ADD;
+                       
                        deselect_actionchannel_keys(act, 0);
                        deselect_actionchannels(act, 0);
-                       act->achan = chan;
+                       
                        chan->flag |= ACHAN_SELECTED;
                        hilight_channel (act, chan, 1);
                        select_poseelement_by_name(chan->name, 1);
@@ -567,7 +579,9 @@ static void mouse_action(int selectmode)
                else
                        select_ipo_key(chan->ipo, selx, selectmode);
 
-               BIF_undo_push("Select Action");
+               
+               std_rmouse_transform(transform_actionchannel_keys);
+               
                allqueue(REDRAWIPO, 0);
                allqueue(REDRAWVIEW3D, 0);
                allqueue(REDRAWACTION, 0);
@@ -731,16 +745,17 @@ void borderselect_mesh(Key *key)
                /* Lets loop throug the IpoCurves and do borderselect
                 * on the curves with adrcodes in our selected range.
                 */
-               for (icu = key->ipo->curve.first; icu ; icu = icu->next) {
-                       /* lets not deal with the "speed" Ipo
-                        */
-                       if (!icu->adrcode) continue;
-                       if ( (icu->adrcode >= adrcodemin) && 
-                                (icu->adrcode <= adrcodemax) ) {
-                               borderselect_icu_key(icu, xmin, xmax, select_function);
+               if(key->ipo) {
+                       for (icu = key->ipo->curve.first; icu ; icu = icu->next) {
+                               /* lets not deal with the "speed" Ipo
+                                */
+                               if (!icu->adrcode) continue;
+                               if ( (icu->adrcode >= adrcodemin) && 
+                                        (icu->adrcode <= adrcodemax) ) {
+                                       borderselect_icu_key(icu, xmin, xmax, select_function);
+                               }
                        }
                }
-
                /* redraw stuff */
                BIF_undo_push("Border select Action Key");
                allqueue(REDRAWNLA, 0);
@@ -749,6 +764,23 @@ void borderselect_mesh(Key *key)
        }
 }
 
+/* ******************** action API ***************** */
+
+/* generic get current action call, for action window context */
+bAction *ob_get_action(Object *ob)
+{
+       bActionStrip *strip;
+       
+       if(ob->action)
+               return ob->action;
+       
+       for (strip=ob->nlastrips.first; strip; strip=strip->next){
+               if (strip->flag & ACTSTRIP_SELECT)
+                       return strip->act;
+       }
+       return NULL;
+}
+
 /* used by ipo, outliner, buttons to find the active channel */
 bActionChannel* get_hilighted_action_channel(bAction* action)
 {
@@ -766,41 +798,6 @@ bActionChannel* get_hilighted_action_channel(bAction* action)
 
 }
 
-/* sets action->achan to active channel, also adds if needed */
-void verify_active_action_channel(Object *ob)
-{
-       if(ob) {
-               bPoseChannel *pchan;
-               bActionChannel *achan;
-               
-               if(ob->action==NULL) return;
-               
-               pchan= get_active_posechannel(ob);
-               if(pchan) {
-                       /* See if this action channel exists already */ 
-                       for (achan=ob->action->chanbase.first; achan; achan=achan->next){
-                               if (!strcmp (pchan->name, achan->name))
-                                       break;
-                       }
-                       
-                       if (!achan){
-                               achan = MEM_callocN (sizeof(bActionChannel), "actionChannel");
-                               strcpy (achan->name, pchan->name);
-                               BLI_addtail (&ob->action->chanbase, achan);
-                       }
-                       
-                       ob->action->achan= achan;
-                       ob->action->pchan= pchan;
-                       
-                       for (achan=ob->action->chanbase.first; achan; achan=achan->next)
-                               achan->flag &= ~(ACHAN_SELECTED|ACHAN_HILIGHTED);
-                       
-                       ob->action->achan->flag |= ACHAN_SELECTED|ACHAN_HILIGHTED;
-
-               }
-       }               
-}
-
 void set_exprap_action(int mode)
 {
        if(G.saction->action && G.saction->action->id.lib) return;
@@ -808,109 +805,23 @@ void set_exprap_action(int mode)
        error ("Not yet implemented!");
 }
 
-void set_action_key (struct bAction *act, struct bPoseChannel *chan, int adrcode, short makecurve)
-{
-       set_action_key_time (act, chan, adrcode, makecurve, frame_to_float(CFRA));
-}
-
-static void set_action_key_time (bAction *act, bPoseChannel *chan, int adrcode, short makecurve, float time)
-{
-       bActionChannel  *achan;
-       char    ipstr[256];
-
-       if (!act)
-               return;
-
-       if (!chan)
-               return;
-       
-       /* See if this action channel exists already */ 
-       for (achan=act->chanbase.first; achan; achan=achan->next){
-               if (!strcmp (chan->name, achan->name))
-                       break;
-       }
-
-       if (!achan){
-               if (!makecurve)
-                       return;
-               achan = MEM_callocN (sizeof(bActionChannel), "actionChannel");
-               strcpy (achan->name, chan->name);
-               BLI_addtail (&act->chanbase, achan);
-       }
-
-       /* Ensure the channel appears selected in the action window */
-       /* ton: added flag hilighted, for display in ipowin. dunno what the difference is between select/hilite */
-       achan->flag |= ACHAN_SELECTED|ACHAN_HILIGHTED;
-
-       /* Ensure this action channel has a valid Ipo */
-       if (!achan->ipo){
-               sprintf (ipstr, "%s.%s", act->id.name+2, chan->name);
-               ipstr[23]=0;
-               achan->ipo=     add_ipo(ipstr, ID_AC);  
-       }
-
-       insertactionkey(act, achan, chan, adrcode, makecurve, time);
-
-}
-
-static void insertactionkey(bAction *act, bActionChannel *achan, bPoseChannel *chan, int adrcode, short makecurve, float cfra)
+bAction *add_empty_action(int blocktype)
 {
-       IpoCurve *icu;
-       void *poin;
-       float curval;
-       int type;
-       ID *id;
-       
-       if (!act){
-               return;
-       }
-       if (act->id.lib){
-               error ("Can't pose library actions");
-               return;
-       }
-       act->achan=achan;
-       act->pchan=chan;
-
-       id=(ID*) act;
-
-       /* First see if this curve exists */
-       if (!makecurve){
-               if (!achan->ipo)
-                       return;
-
-               for (icu = achan->ipo->curve.first; icu; icu=icu->next){
-                       if (icu->adrcode == adrcode)
-                               break;
-               }
-               if (!icu)
-                       return;
-       }
-
+       bAction *act;
+       char *str= "Action";
        
-       icu = get_ipocurve (id, GS(id->name), adrcode, achan->ipo);
-
-       if(icu) {
-               poin= get_ipo_poin(id, icu, &type);
-               if(poin) {
-                       curval= read_ipo_poin(poin, type);
-       //              cfra= frame_to_float(CFRA);
-                       insert_vert_ipo(icu, cfra, curval);
-               }
-       }
+       if(blocktype==ID_OB)
+               str= "ObAction";
+       else if(blocktype==ID_KE)
+               str= "ShapeAction";
        
-}
-
-bAction *add_empty_action(void)
-{
-       bAction *act;
-
-       act= alloc_libblock(&G.main->action, ID_AC, "Action");
+       act= alloc_libblock(&G.main->action, ID_AC, str);
        act->id.flag |= LIB_FAKEUSER;
        act->id.us++;
        return act;
 }
 
-void transform_actionchannel_keys(char mode)
+void transform_actionchannel_keys(int mode, int dummy)
 {
        bAction *act;
        TransVert *tv;
@@ -1054,9 +965,13 @@ void transform_actionchannel_keys(char mode)
                                headerprint(str);
                        }
        
-                       if (G.saction->lock){
-                               if(ob && ob->pose) {
-                                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+                       if (G.saction->lock) {
+                               if(ob) {
+                                       ob->ctime= -1234567.0f;
+                                       if(ob->pose || ob_get_key(ob))
+                                               DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+                                       else
+                                               DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
                                }
                                force_draw_plus(SPACE_VIEW3D, 0);
                        }
@@ -1073,8 +988,13 @@ void transform_actionchannel_keys(char mode)
        /*              Update the curve */
        /*              Depending on the lock status, draw necessary views */
 
-       if(ob && ob->pose) {
-               DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
+       if(ob) {
+               ob->ctime= -1234567.0f;
+
+               if(ob->pose || ob_get_key(ob))
+                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+               else
+                       DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
        }
        remake_action_ipos(act);
 
@@ -1272,7 +1192,6 @@ void transform_meshchannel_keys(char mode, Key *key)
         */
 }
 
-
 void deselect_actionchannel_keys (bAction *act, int test)
 {
        bActionChannel  *chan;
@@ -1535,9 +1454,7 @@ static void mouse_actionchannels(bAction *act, short *mval,
                         * active channel for the action
                         */
                        sel = (chan->flag & ACHAN_SELECTED);
-                       if ( select_channel(act, chan, selectmode) && !sel ) {
-                               act->achan = chan;
-                       }
+                       select_channel(act, chan, selectmode);
                }
                --clickmin;
                --clickmax;
@@ -2175,7 +2092,7 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                        transform_meshchannel_keys('g', key);
                                }
                                else if (act) {
-                                       transform_actionchannel_keys ('g');
+                                       transform_actionchannel_keys ('g', 0);
                                }
                        }
                        break;
@@ -2215,7 +2132,7 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                        transform_meshchannel_keys('s', key);
                                }
                                else if (act) {
-                                       transform_actionchannel_keys ('s');
+                                       transform_actionchannel_keys ('s', 0);
                                }
                        }
                        break;
@@ -2284,7 +2201,8 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                 * based on user preference USER_LMOUSESELECT
                 */
                case LEFTMOUSE:
-                       if(view2dmove(LEFTMOUSE)); // only checks for sliders
+                       if(view2dmove(LEFTMOUSE)) // only checks for sliders
+                               break;
                        else if (mval[0]>ACTWIDTH){
                                do {
                                        getmouseco_areawin(mval);
@@ -2301,8 +2219,9 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                        else PIL_sleep_ms(30);
                                        
                                } while(get_mbut() & mousebut);
+                               break;
                        }
-                       break;
+                       /* passed on as selection */
                case RIGHTMOUSE:
                        /* Clicking in the channel area selects the
                         * channel or constraint channel
index 301658f5339a69f08fe20952379266951efbc6c2..59394973d4ea7b39f915c64194351c709a32ef0e 100644 (file)
@@ -2433,7 +2433,7 @@ void armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
                                act = ob->action;
                                if (act && !act->id.lib){
                                        /*      Find the appropriate channel */
-                                       chan= get_named_actionchannel(act, oldname);
+                                       chan= get_action_channel(act, oldname);
                                        if(chan) BLI_strncpy(chan->name, newname, MAXBONENAME);
                                }
                
index 5b48986c8fb2fa5abd82bb20d70ced75ff2260c5..bac3099a71857475b97ee37dabb5a1470cecb0c0 100644 (file)
@@ -85,11 +85,11 @@ ListBase *get_active_constraint_channels (Object *ob, int forcevalid)
                                if (!forcevalid)
                                        return NULL;
                                
-                               ob->action=add_empty_action();
+                               ob->action=add_empty_action(ID_PO);
                        }
                        
                        /* Make sure we have an actionchannel */
-                       achan = get_named_actionchannel(ob->action, pchan->name);
+                       achan = get_action_channel(ob->action, pchan->name);
                        if (!achan){
                                if (!forcevalid)
                                        return NULL;
@@ -109,7 +109,17 @@ ListBase *get_active_constraint_channels (Object *ob, int forcevalid)
                else return NULL;
        }
        /* else we return object constraints */
-       return &ob->constraintChannels;
+       else {
+               if(ob->ipoflag & OB_ACTION_OB) {
+                       bActionChannel *achan = get_action_channel(ob->action, "Object");
+                       if(achan)
+                               return &achan->constraintChannels;
+                       else 
+                               return NULL;
+               }
+               
+               return &ob->constraintChannels;
+       }
 }
 
 
@@ -162,7 +172,7 @@ bConstraintChannel *get_active_constraint_channel(Object *ob)
                                        if(con->flag & CONSTRAINT_ACTIVE)
                                                break;
                                if(con) {
-                                       bActionChannel *achan = get_named_actionchannel(ob->action, pchan->name);
+                                       bActionChannel *achan = get_action_channel(ob->action, pchan->name);
                                        if(achan) {
                                                for(chan= achan->constraintChannels.first; chan; chan= chan->next)
                                                        if(!strcmp(chan->name, con->name))
@@ -178,10 +188,14 @@ bConstraintChannel *get_active_constraint_channel(Object *ob)
                        if(con->flag & CONSTRAINT_ACTIVE)
                                break;
                if(con) {
-                       for(chan= ob->constraintChannels.first; chan; chan= chan->next)
-                               if(!strcmp(chan->name, con->name))
-                                       break;
-                       return chan;
+                       ListBase *lb= get_active_constraint_channels(ob, 0);
+
+                       if(lb) {
+                               for(chan= lb->first; chan; chan= chan->next)
+                                       if(!strcmp(chan->name, con->name))
+                                               break;
+                               return chan;
+                       }
                }
        }
        
@@ -189,7 +203,6 @@ bConstraintChannel *get_active_constraint_channel(Object *ob)
 }
 
 
-
 bConstraint *add_new_constraint(short type)
 {
        bConstraint *con;
index cb5988ee16ea467b12402cf53fdccdab9ea1c86b..d5eb4268367ac1339e8a6f53244788725c91876c 100644 (file)
@@ -1,15 +1,12 @@
 /**
  * $Id$
  *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  *
- * The Original Code is: all of this file.
+ * Contributor(s): Blender Foundation, 2005. Full recode
  *
- * Contributor(s): none yet.
- *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  */
 
 
 #include <string.h>
 #include <math.h>
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #ifndef WIN32
 #include <unistd.h>
 #else
@@ -81,6 +72,7 @@
 
 #include "BKE_action.h"
 #include "BKE_anim.h"
+#include "BKE_constraint.h"
 #include "BKE_depsgraph.h"
 #include "BKE_global.h"
 #include "BKE_group.h"
 #include "blendef.h"
 #include "mydevice.h"
 
-/* forwards */
-#define BEZSELECTED(bezt)   (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
-
-#define IPOTHRESH      0.9
-#define ISPOIN(a, b, c)                       ( (a->b) && (a->c) )
-#define ISPOIN3(a, b, c, d)           ( (a->b) && (a->c) && (a->d) )
-#define ISPOIN4(a, b, c, d, e)        ( (a->b) && (a->c) && (a->d) && (a->e) )   
-
 extern int ob_ar[];
 extern int ma_ar[];
 extern int seq_ar[];
@@ -138,155 +122,12 @@ extern int ac_ar[];
 extern int co_ar[];
 extern int te_ar[];
 
-char *ob_ic_names[OB_TOTNAM] = { "LocX", "LocY", "LocZ", "dLocX", "dLocY", "dLocZ",
-                                                "RotX", "RotY", "RotZ", "dRotX", "dRotY", "dRotZ",
-                                                "SizeX", "SizeY", "SizeZ", "dSizeX", "dSizeY", "dSizeZ",
-                                                "Layer", "Time", "ColR", "ColG", "ColB", "ColA",
-                                                "FStreng", "FFall", "RDamp", "Damping", "Perm" };
-
-char *co_ic_names[CO_TOTNAM] = { "Inf" };
-char *mtex_ic_names[TEX_TOTNAM] = { "OfsX", "OfsY", "OfsZ", "SizeX", "SizeY", "SizeZ",
-                                                 "texR", "texG", "texB", "DefVar", "Col", "Nor", "Var",
-                                                 "Disp" };
-char *tex_ic_names[TE_TOTNAM] = { "NSize", "NDepth", "NType", "Turb", "Vnw1", "Vnw2",
-                                                                  "Vnw3", "Vnw4", "MinkMExp", "DistM", "ColT", "iScale",
-                                                                  "DistA", "MgType", "MgH", "Lacu", "Oct", "MgOff",
-                                                                  "MgGain", "NBase1", "NBase2" };
-char *ma_ic_names[MA_TOTNAM] = { "R", "G", "B", "SpecR", "SpecG", "SpecB", "MirR",
-                                                "MirG", "MirB", "Ref", "Alpha", "Emit", "Amb", "Spec",
-                                                "Hard", "SpTra", "Ior", "Mode", "HaSize", "Translu",
-                                                "RayMir", "FresMir", "FresMirI", "FresTra", "FresTraI",
-                                                "TraGlow" };
-char *seq_ic_names[SEQ_TOTNAM] = { "Fac" };
-char *cu_ic_names[CU_TOTNAM] = { "Speed" };
-char *key_ic_names[KEY_TOTNAM] = { "Speed", "Key 1", "Key 2", "Key 3", "Key 4", "Key 5",
-                                                                       "Key 6", "Key 7", "Key 8", "Key 9", "Key 10",
-                                                                       "Key 11", "Key 12", "Key 13", "Key 14", "Key 15",
-                                                                       "Key 16", "Key 17", "Key 18", "Key 19", "Key 20",
-                                                                       "Key 21", "Key 22", "Key 23", "Key 24", "Key 25",
-                                                                       "Key 26", "Key 27", "Key 28", "Key 29", "Key 30",
-                                                                       "Key 31", "Key 32", "Key 33", "Key 34", "Key 35",
-                                                                       "Key 36", "Key 37", "Key 38", "Key 39", "Key 40",
-                                                                       "Key 41", "Key 42", "Key 43", "Key 44", "Key 45",
-                                                                       "Key 46", "Key 47", "Key 48", "Key 49", "Key 50",
-                                                                       "Key 51", "Key 52", "Key 53", "Key 54", "Key 55",
-                                                                       "Key 56", "Key 57", "Key 58", "Key 59", "Key 60",
-                                                                       "Key 61", "Key 62", "Key 63"};
-char *wo_ic_names[WO_TOTNAM] = { "HorR", "HorG", "HorB", "ZenR", "ZenG", "ZenB", "Expos",
-                                                "Misi", "MisDi", "MisSta", "MisHi", "StarR", "StarB",
-                                                "StarG", "StarDi", "StarSi" };
-char *la_ic_names[LA_TOTNAM] = { "Energ", "R", "G", "B", "Dist", "SpoSi", "SpoBl",
-                                                                 "Quad1", "Quad2", "HaInt" };
-/* yafray: two curve names added, 'Apert' for aperture, and 'FDist' for focal distance */
-char *cam_ic_names[CAM_TOTNAM] = { "Lens", "ClSta", "ClEnd", "Apert", "FDist" };
-char *snd_ic_names[SND_TOTNAM] = { "Vol", "Pitch", "Pan", "Atten" };
-char *ac_ic_names[AC_TOTNAM] = {"LocX", "LocY", "LocZ", "SizeX", "SizeY",
-                                                 "SizeZ", "QuatW", "QuatX", "QuatY", "QuatZ"};
-char *ic_name_empty[1] ={ "" };
-
-char *getname_ac_ei(int nr) 
-{
-       switch(nr) {
-       case AC_LOC_X:
-       case AC_LOC_Y:
-       case AC_LOC_Z:
-               return ac_ic_names[nr-1];
-       case AC_SIZE_X:
-       case AC_SIZE_Y:
-       case AC_SIZE_Z:
-               return ac_ic_names[nr-10];
-       case AC_QUAT_X:
-       case AC_QUAT_Y:
-       case AC_QUAT_Z:
-       case AC_QUAT_W:
-               return ac_ic_names[nr-19];
-       default:
-               return ic_name_empty[0]; /* empty */
-       }
-}
-
-char *getname_co_ei(int nr)
-{
-       switch(nr){
-       case CO_ENFORCE:
-               return co_ic_names[nr-1];
-       }
-       return ic_name_empty[0];
-}
-
-char *getname_ob_ei(int nr, int colipo)
-{
-       if(nr>=OB_LOC_X && nr <= OB_PD_PERM) return ob_ic_names[nr-1];
-
-       return ic_name_empty[0];
-}
-
-char *getname_tex_ei(int nr)
-{
-       if(nr>=TE_NSIZE && nr<=TE_N_BAS2) return tex_ic_names[nr-1];
-
-       return ic_name_empty[0];
-}
-
-char *getname_mtex_ei(int nr)
-{
-       if(nr>=MAP_OFS_X && nr<=MAP_DISP) return mtex_ic_names[nr-1];
-       
-       return ic_name_empty[0];
-}
-
-char *getname_mat_ei(int nr)
-{
-       if(nr>=MA_MAP1) return getname_mtex_ei((nr & (MA_MAP1-1)));
-       else {
-               if(nr>=MA_COL_R && nr<=MA_ADD) return ma_ic_names[nr-1];
-       }
-       return ic_name_empty[0];
-}
-
-char *getname_world_ei(int nr)
-{
-       if(nr>=MA_MAP1) return getname_mtex_ei((nr & (MA_MAP1-1)));
-       else {
-               if(nr>=WO_HOR_R && nr<=WO_STARSIZE) return wo_ic_names[nr-1];
-       }
-       return ic_name_empty[0];
-}
-
-char *getname_seq_ei(int nr)
-{
-       if(nr == SEQ_FAC1) return seq_ic_names[nr-1];
-       return ic_name_empty[0];
-}
-
-char *getname_cu_ei(int nr)
-{
-       if(nr==CU_SPEED) return cu_ic_names[nr-1];
-       return ic_name_empty[0];
-}
-
-char *getname_la_ei(int nr)
-{
-       if(nr>=MA_MAP1) return getname_mtex_ei((nr & (MA_MAP1-1)));
-       else {
-               if(nr>=LA_ENERGY && nr<=LA_HALOINT) return la_ic_names[nr-1];
-       }
-       return ic_name_empty[0];
-}
-
-char *getname_cam_ei(int nr)
-{
-       /* yafray: curves extended to CAM_YF_FDIST */
-       //if(nr>=CAM_LENS && nr<=CAM_END) return cam_ic_names[nr-1];
-       if(nr>=CAM_LENS && nr<=CAM_YF_FDIST) return cam_ic_names[nr-1];
-       return ic_name_empty[0];
-}
+/* forwards */
+#define BEZSELECTED(bezt)   (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
 
-char *getname_snd_ei(int nr)
-{
-       if(nr>=SND_VOLUME && nr<=SND_ATTEN) return snd_ic_names[nr-1];
-       return ic_name_empty[0];
-}
+#define IPOTHRESH      0.9
+#define ISPOIN(a, b, c)                       ( (a->b) && (a->c) )
+#define ISPOIN3(a, b, c, d)           ( (a->b) && (a->c) && (a->d) )
 
 /* tests if only one editipo is active */
 static void check_active_editipo(void)
@@ -371,78 +212,6 @@ static void set_active_key(int index)
        }                       
 }
 
-void boundbox_ipocurve(IpoCurve *icu)
-{
-       BezTriple *bezt;
-       float vec[3]={0.0,0.0,0.0};
-       float min[3], max[3];
-       int a;
-       
-       if(icu->totvert) {
-               INIT_MINMAX(min, max);
-               
-               if(icu->bezt ) {
-                       a= icu->totvert;
-                       bezt= icu->bezt;
-                       while(a--) {
-                               if(icu->vartype & IPO_BITS) {
-                                       vec[0]= bezt->vec[1][0];
-                                       vec[1]= 0.0;
-                                       DO_MINMAX(vec, min, max);
-                                       
-                                       vec[1]= 16.0;
-                                       DO_MINMAX(vec, min, max);
-                               }
-                               else {
-                                       if(icu->ipo==IPO_BEZ && a!=icu->totvert-1) {
-                                               DO_MINMAX(bezt->vec[0], min, max);
-                                       }
-                                       DO_MINMAX(bezt->vec[1], min, max);
-                                       if(icu->ipo==IPO_BEZ && a!=0) {
-                                               DO_MINMAX(bezt->vec[2], min, max);
-                                       }
-                               }
-                               
-                               bezt++;
-                       }
-               }
-               if(min[0]==max[0]) max[0]= (float)(min[0]+1.0);
-               if(min[1]==max[1]) max[1]= (float)(min[1]+0.1);
-               
-               icu->totrct.xmin= min[0];
-               icu->totrct.ymin= min[1];
-               icu->totrct.xmax= max[0];
-               icu->totrct.ymax= max[1];
-       }
-       else {
-               icu->totrct.xmin= icu->totrct.ymin= 0.0;
-               icu->totrct.xmax= EFRA;
-               icu->totrct.ymax= 1.0;
-       }
-}
-
-void boundbox_ipo(Ipo *ipo, rctf *bb)
-{
-       IpoCurve *icu;
-       int first= 1;
-       
-       icu= ipo->curve.first;
-       while(icu) {
-                       
-               boundbox_ipocurve(icu);
-                               
-               if(first) {
-                       *bb= icu->totrct;
-                       first= 0;
-               }
-               else BLI_union_rctf(bb, &(icu->totrct));
-               
-               icu= icu->next;
-       }
-}
-
-
-
 void editipo_changed(SpaceIpo *si, int doredraw)
 {
        EditIpo *ei;
@@ -544,7 +313,7 @@ void editipo_changed(SpaceIpo *si, int doredraw)
                        allqueue(REDRAWVIEW3D, 0);
                }
                else if(si->blocktype==ID_SEQ) clear_last_seq();
-               else if(si->blocktype==ID_AC) {
+               else if(si->blocktype==ID_PO) {
                        Object *ob= OBACT;
                        if(ob && ob->pose) {
                                DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
@@ -581,7 +350,7 @@ void scale_editipo(void)
        ei= G.sipo->editipo;
        if(ei==0) return;
        for(a=0; a<G.sipo->totipo; a++, ei++) {
-               if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
+               if (ISPOIN(ei, flag & IPO_VISIBLE, icu)) {
                        bezt= ei->icu->bezt;
                        b= ei->icu->totvert;
                        while(b--) {
@@ -607,130 +376,7 @@ void scale_editipo(void)
        allqueue(REDRAWIPO, 0);
 }
 
-
-Ipo *get_ipo_to_edit(ID **from)
-{
-       Object *ob= OBACT;
-       
-       *from= 0;
-       
-       
-       if (G.sipo->pin) {
-               *from = G.sipo->from;
-               return G.sipo->ipo;
-       }
-
-       if(G.sipo->blocktype==ID_SEQ) {
-               extern Sequence *last_seq;
-               
-               *from= (ID *)last_seq;
-               if(last_seq) return last_seq->ipo;
-       }
-       else if(G.sipo->blocktype==IPO_CO){
-               if (ob) {
-                       bConstraintChannel *chan= get_active_constraint_channel(ob);
-                       if(chan) {
-                               *from= (ID*) ob;
-                               return chan->ipo;
-                       }
-               }
-       }
-       else if(G.sipo->blocktype==ID_AC) {
-               bActionChannel *chan;
-               if (ob && ob->action) {
-                       *from= (ID *) ob->action;
-                       chan= get_hilighted_action_channel(ob->action);
-                       if (chan)
-                               return chan->ipo;
-                       else
-                               return NULL;
-               } 
-
-       }
-       else if(G.sipo->blocktype==ID_WO) {
-               World *wo= G.scene->world;
-               *from= (ID *)wo;
-               if(wo) return wo->ipo;
-       }
-       else if(G.sipo->blocktype==ID_OB) {
-               if(ob) {
-                       *from= (ID *)ob;
-                       return ob->ipo;
-               }
-       }
-       else if(G.sipo->blocktype==ID_TE) {
-               if(ob) {
-                       Tex *tex= give_current_texture(ob, ob->actcol);
-                       *from= (ID *)tex;
-                       if(tex) return tex->ipo;
-               }
-       }
-       else if(G.sipo->blocktype==ID_MA) {
-               if(ob) {
-                       Material *ma= give_current_material(ob, ob->actcol);
-                       *from= (ID *)ma;
-                       if(ma) return ma->ipo;
-               }
-       }
-       else if(G.sipo->blocktype==ID_KE) {
-               if(ob) {
-                       Key *key= ob_get_key(ob);
-                       *from= (ID *)key;
-                       if(key) return key->ipo;
-               }
-       }
-       else if(G.sipo->blocktype==ID_CU) {
-               if(ob && ob->type==OB_CURVE) {
-                       Curve *cu= ob->data;
-                       *from= (ID *)cu;
-                       return cu->ipo;
-               }
-       }
-       else if(G.sipo->blocktype==ID_LA) {
-               if(ob && ob->type==OB_LAMP) {
-                       Lamp *la= ob->data;
-                       *from= (ID *)la;
-                       return la->ipo;
-               }
-       }
-       else if(G.sipo->blocktype==ID_CA) {
-               if(ob && ob->type==OB_CAMERA) {
-                       Camera *ca= ob->data;
-                       *from= (ID *)ca;
-                       if(ca) return ca->ipo;
-               }
-       }
-       else if(G.sipo->blocktype==ID_SO) {
-
-//             if (G.buts && G.buts->mainb == BUTS_SOUND) {
-//                     bSound *sound = G.buts->lockpoin;
-//                     *from= (ID *)sound;
-//                     if(sound) return sound->ipo;
-//             }
-       }
-
-       return NULL;
-}
-
-unsigned int ipo_rainbow(int cur, int tot)
-{
-       float dfac, fac, sat;
-
-       dfac= (float)(1.0/( (float)tot+1.0));
-
-       /* this calculation makes 2 or 4 different cycles of rainbow colors */
-       if(cur< tot/2) fac= (float)(cur*2.0f*dfac);
-       else fac= (float)((cur-tot/2)*2.0f*dfac +dfac);
-       if(tot > 32) fac= fac*1.95f;
-       if(fac>1.0f) fac-= 1.0f;
-       
-       if(fac>0.5f && fac<0.8f) sat= 0.4f;
-       else sat= 0.5f;
-       
-       return hsv_to_cpack(fac, sat, 1.0f);
-}              
-
-void make_ob_editipo(Object *ob, SpaceIpo *si)
+static void make_ob_editipo(Object *ob, SpaceIpo *si)
 {
        EditIpo *ei;
        int a, len, colipo=0;
@@ -772,8 +418,7 @@ void make_ob_editipo(Object *ob, SpaceIpo *si)
        }
 }
 
-
-void make_seq_editipo(SpaceIpo *si)
+static void make_seq_editipo(SpaceIpo *si)
 {
        EditIpo *ei;
        int a;
@@ -801,7 +446,7 @@ void make_seq_editipo(SpaceIpo *si)
        }
 }
 
-void make_cu_editipo(SpaceIpo *si)
+static void make_cu_editipo(SpaceIpo *si)
 {
        EditIpo *ei;
        int a;
@@ -829,7 +474,7 @@ void make_cu_editipo(SpaceIpo *si)
        }
 }
 
-void make_key_editipo(SpaceIpo *si)
+static void make_key_editipo(SpaceIpo *si)
 {
        Key *key;
        KeyBlock *kb=NULL;
@@ -884,24 +529,7 @@ void make_key_editipo(SpaceIpo *si)
        }
 }
 
-int texchannel_to_adrcode(int channel)
-{
-       switch(channel) {
-               case 0: return MA_MAP1;
-               case 1: return MA_MAP2; 
-               case 2: return MA_MAP3; 
-               case 3: return MA_MAP4; 
-               case 4: return MA_MAP5; 
-               case 5: return MA_MAP6; 
-               case 6: return MA_MAP7; 
-               case 7: return MA_MAP8; 
-               case 8: return MA_MAP9; 
-               case 9: return MA_MAP10; 
-               default: return 0;
-       }
-}
-
-void make_mat_editipo(SpaceIpo *si)
+static void make_mat_editipo(SpaceIpo *si)
 {
        EditIpo *ei;
        int a, len;
@@ -944,7 +572,7 @@ void make_mat_editipo(SpaceIpo *si)
        }
 }
 
-void make_texture_editipo(SpaceIpo *si)
+static void make_texture_editipo(SpaceIpo *si)
 {
        EditIpo *ei;
        int a;
@@ -972,7 +600,7 @@ void make_texture_editipo(SpaceIpo *si)
        }
 }
 
-void make_world_editipo(SpaceIpo *si)
+static void make_world_editipo(SpaceIpo *si)
 {
        EditIpo *ei;
        int a, len;
@@ -1016,7 +644,7 @@ void make_world_editipo(SpaceIpo *si)
        }
 }
 
-void make_lamp_editipo(SpaceIpo *si)
+static void make_lamp_editipo(SpaceIpo *si)
 {
        EditIpo *ei;
        int a;
@@ -1026,7 +654,6 @@ void make_lamp_editipo(SpaceIpo *si)
        
        si->totipo= LA_TOTIPO;
        
-       
        for(a=0; a<LA_TOTIPO; a++) {
                name = getname_la_ei(la_ar[a]);
                strcpy(ei->name, name);
@@ -1048,7 +675,7 @@ void make_lamp_editipo(SpaceIpo *si)
        }
 }
 
-void make_camera_editipo(SpaceIpo *si)
+static void make_camera_editipo(SpaceIpo *si)
 {
        EditIpo *ei;
        int a;
@@ -1075,7 +702,7 @@ void make_camera_editipo(SpaceIpo *si)
        }
 }
 
-int make_constraint_editipo(Ipo *ipo, EditIpo **si)
+static int make_constraint_editipo(Ipo *ipo, EditIpo **si)
 {
        EditIpo *ei;
        int a;
@@ -1100,7 +727,8 @@ int make_constraint_editipo(Ipo *ipo, EditIpo **si)
 
        return CO_TOTIPO;
 }
-int make_action_editipo(Ipo *ipo, EditIpo **si)
+
+static int make_bone_editipo(Ipo *ipo, EditIpo **si)
 {
        EditIpo *ei;
        int a;
@@ -1126,7 +754,7 @@ int make_action_editipo(Ipo *ipo, EditIpo **si)
        return AC_TOTIPO;
 }
 
-void make_sound_editipo(SpaceIpo *si)
+static void make_sound_editipo(SpaceIpo *si)
 {
        EditIpo *ei;
        int a;
@@ -1153,23 +781,24 @@ void make_sound_editipo(SpaceIpo *si)
        }
 }
 
-void make_editipo(void)
+/* only called in test_editipo() below */
+static void make_editipo(void)
 {
        EditIpo *ei;
        Object *ob;
-       ID *from;
        rctf *rf;
        int a;
 
        if(G.sipo->editipo)
                MEM_freeN(G.sipo->editipo);
+       
        G.sipo->editipo= NULL;
        G.sipo->totipo= 0;
+       
+       if(G.sipo->from==NULL) return;
+       
        ob= OBACT;
 
-       G.sipo->ipo= get_ipo_to_edit(&from);
-       G.sipo->from= from;
-
        if(G.sipo->ipo) G.sipo->showkey= G.sipo->ipo->showkey;
 
        if(G.sipo->blocktype==ID_SEQ) {
@@ -1226,17 +855,17 @@ void make_editipo(void)
                        make_sound_editipo(G.sipo);
                }
        }
-       else if(G.sipo->blocktype==IPO_CO){
+       else if(G.sipo->blocktype==ID_CO){
                G.sipo->totipo = make_constraint_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo);
                if (ob) {
-                       ob->ipowin= IPO_CO;
+                       ob->ipowin= ID_CO;
                }
        }
-       else if(G.sipo->blocktype==ID_AC) {
+       else if(G.sipo->blocktype==ID_PO) {
 
-               G.sipo->totipo = make_action_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo);
+               G.sipo->totipo = make_bone_editipo(G.sipo->ipo, (EditIpo**)&G.sipo->editipo);
                if (ob) {
-                       ob->ipowin= ID_AC;
+                       ob->ipowin= ID_PO;
                }
        }
 
@@ -1259,128 +888,242 @@ void make_editipo(void)
                
        }
        else {
-               if(G.sipo->blocktype==ID_OB) {
-                       G.v2d->cur.xmin= 0.0;
-                       G.v2d->cur.xmax= EFRA;
-                       G.v2d->cur.ymin= -5.0;
-                       G.v2d->cur.ymax= +5.0;
-               }
-               else if(G.sipo->blocktype==ID_CA) {
-                       G.v2d->cur.xmin= 0.0;
-                       G.v2d->cur.xmax= EFRA;
-                       G.v2d->cur.ymin= 0.0;
-                       G.v2d->cur.ymax= 100.0;
-               }
-               else if ELEM5(G.sipo->blocktype, ID_MA, ID_CU, ID_WO, ID_LA, IPO_CO) {
-                       G.v2d->cur.xmin= (float)-0.1;
-                       G.v2d->cur.xmax= EFRA;
-                       G.v2d->cur.ymin= (float)-0.1;
-                       G.v2d->cur.ymax= (float)+1.1;
-               }
-               else if(G.sipo->blocktype==ID_TE) {
-                       G.v2d->cur.xmin= (float)-0.1;
-                       G.v2d->cur.xmax= EFRA;
-                       G.v2d->cur.ymin= (float)-0.1;
-                       G.v2d->cur.ymax= (float)+1.1;
-               }
-               else if(G.sipo->blocktype==ID_SEQ) {
-                       G.v2d->cur.xmin= -5.0;
-                       G.v2d->cur.xmax= 105.0;
-                       G.v2d->cur.ymin= (float)-0.1;
-                       G.v2d->cur.ymax= (float)+1.1;
-               }
-               else if(G.sipo->blocktype==ID_KE) {
-                       G.v2d->cur.xmin= (float)-0.1;
-                       G.v2d->cur.xmax= EFRA;
-                       G.v2d->cur.ymin= (float)-0.1;
-                       G.v2d->cur.ymax= (float)+2.1;
-               }
-
-       }
-}
-
-
-void test_editipo(void)
-{
-       Ipo *ipo;
-       ID *from;
-       
-       if(G.sipo->editipo==NULL){
-               make_editipo();
-       }
-       else {
-               ipo= get_ipo_to_edit(&from);
-
-               if(G.sipo->ipo != ipo || G.sipo->from!=from)
-                       make_editipo();
-               
+               ipo_default_v2d_cur(G.sipo->blocktype, &G.v2d->cur);
        }
-
-       if (G.sipo->pin)
-               return;
-
-
-       if(G.sipo->ipo)
-               G.sipo->ipo->cur = G.v2d->cur;
-
 }
 
-/* ****************************************** */
-
-int totipo_edit, totipo_sel, totipo_curve, totipo_vis, totipo_vert, totipo_vertsel, totipo_key, totipo_keysel;
-
-void get_status_editipo(void)
+/* evaluates context in the current UI */
+/* blocktype is type of ipo */
+/* from is the base pointer to find data to change (ob in case of action or pose) */
+static void get_ipo_context(short blocktype, ID **from, Ipo **ipo, char *actname, char *constname)
 {
-       EditIpo *ei;
-       IpoKey *ik;
-       BezTriple *bezt;
-       int a, b;
-       
-       totipo_vis= 0;
-       totipo_curve= 0;
-       totipo_sel= 0;
-       totipo_edit= 0;
-       totipo_vert= 0;
-       totipo_vertsel= 0;
-       totipo_key= 0;
-       totipo_keysel= 0;
+       Object *ob= OBACT;
        
-       if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+       *from= NULL;
+       *ipo= NULL;
        
-       ei= G.sipo->editipo;
-       if(ei==0) return;
-       for(a=0; a<G.sipo->totipo; a++) {
-               if( ei->flag & IPO_VISIBLE ) {
-                       totipo_vis++;
-                       if(ei->flag & IPO_SELECT) totipo_sel++;
-                       if(ei->icu && ei->icu->totvert) totipo_curve++;
-                       if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
+       if(blocktype==ID_CO) {
+               if (ob) {
+                       bConstraintChannel *chan;
+                       bConstraint *con= get_active_constraint(ob);
+                       
+                       if(con) {
+                               BLI_strncpy(constname, con->name, 32);
                                
-                               /* if showkey: do count the vertices (for grab) */
-                               if(G.sipo->showkey==0) totipo_edit++;
+                               chan= get_active_constraint_channel(ob);
+                               if(chan) {
+                                       *ipo= chan->ipo;
+                                       BLI_strncpy(constname, con->name, 32);
+                               }
                                
-                               if(ei->icu) {
-                                       if(ei->icu->bezt) {
-                                               bezt= ei->icu->bezt;
-                                               b= ei->icu->totvert;
-                                               while(b--) {
-                                                       if(ei->icu->ipo==IPO_BEZ) {
-                                                               if(bezt->f1 & 1) totipo_vertsel++;
-                                                               if(bezt->f3 & 1) totipo_vertsel++;
-                                                               totipo_vert+= 2;
-                                                       }
-                                                       if(bezt->f2 & 1) totipo_vertsel++;
-                                                       
-                                                       totipo_vert++;
-                                                       bezt++;
-                                               }
+                               *from= &ob->id;
+                               
+                               /* set actname if in posemode */
+                               if(ob->action) {
+                                       if(ob->flag & OB_POSEMODE) {
+                                               bPoseChannel *pchan= get_active_posechannel(ob);
+                                               if(pchan)
+                                                       BLI_strncpy(actname, pchan->name, 32);
                                        }
+                                       else if(ob->ipoflag & OB_ACTION_OB)
+                                               strcpy(actname, "Object");
                                }
                        }
                }
-               ei++;
        }
-       
+       else if(blocktype==ID_PO) {
+               if (ob && ob->action) {
+                       bPoseChannel *pchan= get_active_posechannel(ob);
+                       
+                       *from= (ID *)ob;
+                       if (pchan) {
+                               bActionChannel *achan;
+                               
+                               BLI_strncpy(actname, pchan->name, 32);  /* also set when no channel yet */
+                               
+                               achan= get_action_channel(ob->action, pchan->name);
+                               if(achan)
+                                       *ipo= achan->ipo;
+                       }
+               } 
+               
+       }
+       else if(blocktype==ID_OB) {
+               if(ob) {
+                       *from= (ID *)ob;
+                       if(ob->ipoflag & OB_ACTION_OB) {
+                               if (ob->action) {
+                                       bActionChannel *achan= get_action_channel(ob->action, "Object");
+                                       if(achan) {
+                                               *ipo= achan->ipo;
+                                               BLI_strncpy(actname, achan->name, 32);
+                                       }
+                               }
+                       }
+                       else {
+                               *ipo= ob->ipo;
+                       }
+               }
+       }
+       else if(blocktype==ID_SEQ) {
+               extern Sequence *last_seq;
+               
+               *from= (ID *)last_seq;
+               if(last_seq) *ipo= last_seq->ipo;
+       }
+       else if(blocktype==ID_WO) {
+               World *wo= G.scene->world;
+               *from= (ID *)wo;
+               if(wo) *ipo= wo->ipo;
+       }
+       else if(blocktype==ID_TE) {
+               if(ob) {
+                       Tex *tex= give_current_texture(ob, ob->actcol);
+                       *from= (ID *)tex;
+                       if(tex) *ipo= tex->ipo;
+               }
+       }
+       else if(blocktype==ID_MA) {
+               if(ob) {
+                       Material *ma= give_current_material(ob, ob->actcol);
+                       *from= (ID *)ma;
+                       if(ma) *ipo= ma->ipo;
+               }
+       }
+       else if(blocktype==ID_KE) {
+               if(ob) {
+                       Key *key= ob_get_key(ob);
+                       *from= (ID *)key;
+                       if(key) *ipo= key->ipo;
+               }
+       }
+       else if(blocktype==ID_CU) {
+               if(ob && ob->type==OB_CURVE) {
+                       Curve *cu= ob->data;
+                       *from= (ID *)cu;
+                       *ipo= cu->ipo;
+               }
+       }
+       else if(blocktype==ID_LA) {
+               if(ob && ob->type==OB_LAMP) {
+                       Lamp *la= ob->data;
+                       *from= (ID *)la;
+                       *ipo= la->ipo;
+               }
+       }
+       else if(blocktype==ID_CA) {
+               if(ob && ob->type==OB_CAMERA) {
+                       Camera *ca= ob->data;
+                       *from= (ID *)ca;
+                       if(ca) *ipo= ca->ipo;
+               }
+       }
+       else if(blocktype==ID_SO) {
+               
+               //              if (G.buts && G.buts->mainb == BUTS_SOUND) {
+               //                      bSound *sound = G.buts->lockpoin;
+               //                      *from= (ID *)sound;
+               //                      if(sound) *ipo= sound->ipo;
+               //              }
+       }
+}
+
+/* called on each redraw, check if editipo data has to be remade */
+void test_editipo(void)
+{
+       int doit= 0;
+       
+       if(G.sipo->pin==0) {
+               Ipo *ipo;
+               ID *from;
+               char actname[32]="", constname[32]="";
+               
+               get_ipo_context(G.sipo->blocktype, &from, &ipo, actname, constname);
+               
+               if(G.sipo->ipo != ipo) {
+                       G.sipo->ipo= ipo;
+                       if(ipo) G.v2d->cur= ipo->cur;
+                       doit= 1;
+               }
+               if(G.sipo->from != from) {
+                       G.sipo->from= from;
+                       doit= 1;
+               }
+               if( strcmp(G.sipo->actname, actname)) {
+                       BLI_strncpy(G.sipo->actname, actname, 32);
+                       doit= 1;
+               }
+               if( strcmp(G.sipo->constname, constname)) {
+                       BLI_strncpy(G.sipo->constname, constname, 32);
+                       doit= 1;
+               }
+               
+               if(G.sipo->ipo)
+                       G.sipo->ipo->cur = G.v2d->cur;
+               
+       }
+               
+       if(G.sipo->editipo==NULL || doit) {
+               make_editipo();
+       }
+}
+
+/* ****************** EditIpo ************************ */
+
+int totipo_edit, totipo_sel, totipo_curve, totipo_vis, totipo_vert, totipo_vertsel, totipo_key, totipo_keysel;
+
+void get_status_editipo(void)
+{
+       EditIpo *ei;
+       IpoKey *ik;
+       BezTriple *bezt;
+       int a, b;
+       
+       totipo_vis= 0;
+       totipo_curve= 0;
+       totipo_sel= 0;
+       totipo_edit= 0;
+       totipo_vert= 0;
+       totipo_vertsel= 0;
+       totipo_key= 0;
+       totipo_keysel= 0;
+       
+       if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+       
+       ei= G.sipo->editipo;
+       if(ei==0) return;
+       for(a=0; a<G.sipo->totipo; a++) {
+               if( ei->flag & IPO_VISIBLE ) {
+                       totipo_vis++;
+                       if(ei->flag & IPO_SELECT) totipo_sel++;
+                       if(ei->icu && ei->icu->totvert) totipo_curve++;
+                       if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
+                               
+                               /* if showkey: do count the vertices (for grab) */
+                               if(G.sipo->showkey==0) totipo_edit++;
+                               
+                               if(ei->icu) {
+                                       if(ei->icu->bezt) {
+                                               bezt= ei->icu->bezt;
+                                               b= ei->icu->totvert;
+                                               while(b--) {
+                                                       if(ei->icu->ipo==IPO_BEZ) {
+                                                               if(bezt->f1 & 1) totipo_vertsel++;
+                                                               if(bezt->f3 & 1) totipo_vertsel++;
+                                                               totipo_vert+= 2;
+                                                       }
+                                                       if(bezt->f2 & 1) totipo_vertsel++;
+                                                       
+                                                       totipo_vert++;
+                                                       bezt++;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               ei++;
+       }
+       
        if(G.sipo->showkey) {
                ik= G.sipo->ipokey.first;
                while(ik) {
@@ -1426,6 +1169,7 @@ void update_editipo_flags(void)
        }
 }
 
+/* sort of enter/leave editmode for curves */
 void set_editflag_editipo(void)
 {
        EditIpo *ei;
@@ -1470,171 +1214,7 @@ void set_editflag_editipo(void)
        scrarea_queue_winredraw(curarea);
 }
 
-void ipo_toggle_showkey(void) 
-{
-       if(G.sipo->showkey) {
-               G.sipo->showkey= 0;
-               swap_selectall_editipo();       /* sel all */
-       }
-       else G.sipo->showkey= 1;
-       free_ipokey(&G.sipo->ipokey);
-       if(G.sipo->ipo) G.sipo->ipo->showkey= G.sipo->showkey;
-
-       BIF_undo_push("Toggle show key Ipo");
-}
-
-void swap_selectall_editipo(void)
-{
-       Object *ob;
-       EditIpo *ei;
-       IpoKey *ik;
-       BezTriple *bezt;
-       int a, b; /*  , sel=0; */
-       
-       get_status_editipo();
-
-       if(G.sipo->showkey) {
-               ik= G.sipo->ipokey.first;
-               while(ik) {
-                       if(totipo_vertsel) ik->flag &= ~1;
-                       else ik->flag |= 1;
-                       ik= ik->next;
-               }
-               update_editipo_flags();
-
-               if(G.sipo->showkey && G.sipo->blocktype==ID_OB ) {
-                       ob= OBACT;
-                       if(ob && (ob->ipoflag & OB_DRAWKEY)) draw_object_ext(BASACT);
-               }
-       }
-       else if(totipo_edit==0) {
-               ei= G.sipo->editipo;
-               if (ei){
-                       for(a=0; a<G.sipo->totipo; a++) {
-                               if( ei->flag & IPO_VISIBLE ) {
-                                       if(totipo_sel) ei->flag &= ~IPO_SELECT;
-                                       else ei->flag |= IPO_SELECT;
-                               }
-                               ei++;
-                       }
-                       update_editipo_flags();
-               }
-               get_status_editipo();
-       }
-       else {
-               ei= G.sipo->editipo;
-               for(a=0; a<G.sipo->totipo; a++) {
-                       if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu ) {
-                               bezt= ei->icu->bezt;
-                               if(bezt) {
-                                       b= ei->icu->totvert;
-                                       while(b--) {
-                                               if(totipo_vertsel) {
-                                                       bezt->f1= bezt->f2= bezt->f3= 0;
-                                               }
-                                               else {
-                                                       bezt->f1= bezt->f2= bezt->f3= 1;
-                                               }
-                                               bezt++;
-                                       }
-                               }
-                       }
-                       ei++;
-               }
-               
-       }
-       
-       BIF_undo_push("Swap select all Ipo");
-       scrarea_queue_winredraw(curarea);
-       
-}
-
-void swap_visible_editipo(void)
-{
-       EditIpo *ei;
-       Object *ob;
-       int a; /*  , sel=0; */
-       
-       get_status_editipo();
-       
-       
-       ei= G.sipo->editipo;
-       for(a=0; a<G.sipo->totipo; a++) {
-               if(totipo_vis==0) {
-                       if(ei->icu) {
-                               ei->flag |= IPO_VISIBLE;
-                               ei->flag |= IPO_SELECT;
-                       }
-               }
-               else ei->flag &= ~IPO_VISIBLE;
-               ei++;
-       }
-       
-       update_editipo_flags();
-       
-       if(G.sipo->showkey) {
-               
-               make_ipokey();
-               
-               ob= OBACT;
-               if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
-       }
-
-       scrarea_queue_winredraw(curarea);
-       BIF_undo_push("Swap Visible Ipo");      
-}
-
-void deselectall_editipo(void)
-{
-       EditIpo *ei;
-       IpoKey *ik;
-       BezTriple *bezt;
-       int a, b; /*  , sel=0; */
-       
-       get_status_editipo();
-       
-       if(G.sipo->showkey) {
-               ik= G.sipo->ipokey.first;
-               while(ik) {
-                       ik->flag &= ~1;
-                       ik= ik->next;
-               }
-               update_editipo_flags();
-
-       }
-       else if(totipo_edit==0) {
-               
-               ei= G.sipo->editipo;
-               for(a=0; a<G.sipo->totipo; a++) {
-                       if( ei->flag & IPO_VISIBLE ) {
-                               ei->flag &= ~IPO_SELECT;
-                       }
-                       ei++;
-               }
-               update_editipo_flags();
-       }
-       else {
-               ei= G.sipo->editipo;
-               for(a=0; a<G.sipo->totipo; a++) {
-                       if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu ) {
-                               if(ei->icu->bezt) {
-                                       bezt= ei->icu->bezt;
-                                       b= ei->icu->totvert;
-                                       while(b--) {
-                                               bezt->f1= bezt->f2= bezt->f3= 0;
-                                               bezt++;
-                                       }
-                               }
-                       }
-                       ei++;
-               }
-       }
-       
-       BIF_undo_push("(De)select all Ipo");
-       scrarea_queue_winredraw(curarea);
-}
-
-short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt)
+static short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt)
 {
        /* selected verts get a disadvantage */
        /* in icu and (bezt or bp) the nearest is written */
@@ -1651,7 +1231,7 @@ short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt)
 
        ei= G.sipo->editipo;
        for(a=0; a<G.sipo->totipo; a++, ei++) {
-               if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu) {
+               if (ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu)) {
                        
                        if(ei->icu->bezt) {
                                bezt1= ei->icu->bezt;
@@ -1704,55 +1284,192 @@ short findnearest_ipovert(IpoCurve **icu, BezTriple **bezt)
        return hpoint;
 }
 
-
-void move_to_frame(void)
+void mouse_select_ipo(void)
 {
-       EditIpo *ei;
+       Object *ob;
+       Key *key;
+       KeyBlock *kb, *actkb=NULL, *curkb;
+       EditIpo *ei, *actei= 0;
+       IpoCurve *icu;
+       IpoKey *ik, *actik;
        BezTriple *bezt;
-       ID *id;
-       float cfra;
-       int a, b;
+       float x, y, dist, mindist;
+       int a, oldflag = 0, hand, ok;
+       short mval[2], xo, yo;
        
        if(G.sipo->editipo==0) return;
-
-       ei= G.sipo->editipo;
-
-       for(a=0; a<G.sipo->totipo; a++, ei++) {
-               if ISPOIN(ei, flag & IPO_VISIBLE, icu) {
-                       if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
+       
+       get_status_editipo();
+       
+       if(G.sipo->showkey) {
+               getmouseco_areawin(mval);
+               
+               areamouseco_to_ipoco(G.v2d, mval, &x, &y);
+               actik= 0;
+               mindist= 1000.0;
+               ik= G.sipo->ipokey.first;
+               while(ik) {
+                       dist= (float)(fabs(ik->val-x));
+                       if(ik->flag & 1) dist+= 1.0;
+                       if(dist < mindist) {
+                               actik= ik;
+                               mindist= dist;
+                       }
+                       ik= ik->next;
+               }
+               if(actik) {
+                       oldflag= actik->flag;
                        
-                               if(ei->icu->bezt) {
-                                       
-                                       b= ei->icu->totvert;
-                                       bezt= ei->icu->bezt;
-                                       while(b--) {
-                                               if(BEZSELECTED(bezt)) {
-                                               
-                                                       cfra=  bezt->vec[1][0]/G.scene->r.framelen;
-
-                                                       id= G.sipo->from;
-                                                       if(id && GS(id->name)==ID_OB ) {
-                                                               Object *ob= (Object *)id;
-                                                               if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
-                                                                       cfra+= ob->sf/G.scene->r.framelen;
-                                                               }
-                                                       }
-                                                       CFRA= (short)floor(cfra+0.5);
-                                               
-                                                       if(CFRA < 1) CFRA= 1;
-                                                       update_for_newframe();
-                                                       
-                                                       break;
-                                               }
-                                               bezt++;
+                       if(G.qual & LR_SHIFTKEY);
+                       else deselectall_editipo();
+                       
+                       if(G.qual & LR_SHIFTKEY) {
+                               if(oldflag & 1) actik->flag &= ~1;
+                               else actik->flag |= 1;
+                       }
+                       else {
+                               actik->flag |= 1;
+                       }
+               }
+       }
+       else if(totipo_edit) {
+               
+               hand= findnearest_ipovert(&icu, &bezt);
+               
+               if(G.qual & LR_SHIFTKEY) {
+                       if(bezt) {
+                               if(hand==1) {
+                                       if(BEZSELECTED(bezt)) {
+                                               bezt->f1= bezt->f2= bezt->f3= 0;
+                                       }
+                                       else {
+                                               bezt->f1= bezt->f2= bezt->f3= 1;
                                        }
                                }
+                               else if(hand==0) {
+                                       if(bezt->f1 & 1) bezt->f1= 0;
+                                       else bezt->f1= 1;
+                               }
+                               else {
+                                       if(bezt->f3 & 1) bezt->f3= 0;
+                                       else bezt->f3= 1;
+                               }
+                       }                               
+               }
+               else {
+                       deselectall_editipo();
+                       
+                       if(bezt) {
+                               if(hand==1) {
+                                       bezt->f1|= 1; bezt->f2|= 1; bezt->f3|= 1;
+                               }
+                               else if(hand==0) bezt->f1|= 1;
+                               else bezt->f3|= 1;
                        }
                }
        }
-       BIF_undo_push("Set frame to selected Ipo vertex");
+       else {
+               
+               /* vertex keys ? */
+               if(G.sipo->blocktype==ID_KE && G.sipo->from) {
+                       int i, index= 1;
+                       
+                       key= (Key *)G.sipo->from;
+                       ob= OBACT;
+                       curkb= BLI_findlink(&key->block, ob->shapenr-1);
+                       
+                       ei= G.sipo->editipo;
+                       if(key->type==KEY_NORMAL || (ei->flag & IPO_VISIBLE)) {
+                               getmouseco_areawin(mval);
+                               
+                               areamouseco_to_ipoco(G.v2d, mval, &x, &y);
+                               /* how much is 20 pixels? */
+                               mindist= (float)(20.0*(G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)curarea->winy);
+                               
+                               for(i=1, kb= key->block.first; kb; kb= kb->next, i++) {
+                                       dist= (float)(fabs(kb->pos-y));
+                                       if(kb==curkb) dist+= (float)0.01;
+                                       if(dist < mindist) {
+                                               actkb= kb;
+                                               mindist= dist;
+                                               index= i;
+                                       }
+                               }
+                               if(actkb) {
+                                       ok= TRUE;
+                                       if(G.obedit && actkb!=curkb) {
+                                               ok= okee("Copy key after leaving Edit Mode");
+                                       }
+                                       if(ok) {
+                                               /* also does all keypos */
+                                               deselectall_editipo();
+                                               set_active_key(index);
+                                               set_active_editipo(ei+index-1);
+                                       }
+                               }
+                       }
+               }
+               
+               /* select curve */
+               if(actkb==NULL) {
+                       if(totipo_vis==1) {
+                               ei= G.sipo->editipo;
+                               for(a=0; a<G.sipo->totipo; a++, ei++) {
+                                       if(ei->icu) {
+                                               if(ei->flag & IPO_VISIBLE) actei= ei;
+                                       }
+                               }
+                       }
+                       else if(totipo_vis>1) {
+                               actei= select_proj_ipo(0, 0);
+                       }
+                       
+                       if(actei) oldflag= actei->flag;
+                       
+                       if(G.qual & LR_SHIFTKEY);
+                       else deselectall_editipo();
+                       
+                       if(actei) {
+                               if(G.qual & LR_SHIFTKEY) {
+                                       if(oldflag & IPO_SELECT) actei->flag &= ~IPO_SELECT;
+                                       else actei->flag |= IPO_SELECT;
+                               }
+                               else {
+                                       actei->flag |= IPO_SELECT;
+                               }
+                               set_active_editipo(actei);
+                       }
+               }
+       }
+       
+       update_editipo_flags();
+       
+       force_draw(0);
+       BIF_undo_push("Select Ipo");
+       
+       if(G.sipo->showkey && G.sipo->blocktype==ID_OB) {
+               ob= OBACT;
+               if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
+       }
+       
+       getmouseco_areawin(mval);
+       xo= mval[0]; 
+       yo= mval[1];
+       
+       while(get_mbut()&R_MOUSE) {             
+               getmouseco_areawin(mval);
+               if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) {
+                       
+                       if(actkb) move_keys(OBACT);
+                       else transform_ipo('g');
+                       
+                       return;
+               }
+               BIF_wait_for_statechange();
+       }
 }
 
+
 /* *********************************** */
 
 /* handling of right-hand channel/curve buttons in ipo window */
@@ -1843,203 +1560,189 @@ void do_ipo_selectbuttons(void)
        BIF_undo_push("Select Ipo curve");
 }
 
-/* ******************************************* */
-
-EditIpo *get_editipo(void)
-{
-       EditIpo *ei;
-       int a; /*  , sel=0; */
-       
-       get_status_editipo();
-       
-       if(totipo_edit>1) {
-               return 0;
-       }
-       if(G.sipo->editipo==0) return 0;
-       
-       ei= G.sipo->editipo;
-       for(a=0; a<G.sipo->totipo; a++) {
-               if(ei->flag & IPO_VISIBLE) {
-                       if( ei->flag & IPO_EDIT ) return ei;
-                       else if(totipo_vis==1) return ei;
-                       
-                       if(ei->flag & IPO_SELECT) {
-                               if(totipo_sel==1) return ei;
-                       }
-               }
-               ei++;
-       }
-       return 0;
-}
+/* ********************************* Inserting keys ********************************************* */
 
+/* depending type, it returns ipo, if neded it creates one */
+/* returns either action ipo or "real" ipo */
+/* arguments define full context;
+   - *from has to be set always, to Object in case of Actions
+   - blocktype defines available channels of Ipo struct (blocktype ID_OB can be in action too)
+   - if actname, use this to locate action, and optional constname to find the channel 
+*/
 
-Ipo *get_ipo(ID *from, short type, int make)
+/* note; check header_ipo.c, spaceipo_assign_ipo() too */
+Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname)
 {
-       Object *ob;
-       Material *ma;
-       Tex *tex;
-       Curve *cu;
-       Sequence *seq;
-       Key *key;
-       World *wo;
-       Lamp *la;
-       Camera *ca;
-       Ipo *ipo= NULL;
-       bAction *act;
 
-       if(from==NULL) return NULL;
+       if(from==NULL || from->lib) return NULL;
        
-       if( type==ID_OB) {
-               ob= (Object *)from;
-               if(ob->id.lib) return NULL;
+       /* first check action ipos */
+       if(actname && actname[0]) {
+               Object *ob= (Object *)from;
+               bActionChannel *achan;
                
-               ipo= ob->ipo;
-               if(make && ipo==NULL) ipo= ob->ipo= add_ipo("ObIpo", ID_OB);    
-       }
-       else if( type==IPO_CO){
-               bConstraintChannel *chan;
+               if(ob->action==NULL)
+                       ob->action= add_empty_action(blocktype);
                
-               ob= (Object *)from;
-               if(ob->id.lib) return NULL;
+               achan= verify_action_channel(ob->action, actname);
                
-               chan= get_active_constraint_channel(ob);
-
-               if (chan){
-                       ipo= chan->ipo;
-                       if(make && ipo==NULL) ipo= chan->ipo= add_ipo("CoIpo", IPO_CO); 
+               if(achan) {
+                       /* constraint exception */
+                       if(blocktype==ID_CO) {
+                               bConstraintChannel *conchan= verify_constraint_channel(&achan->constraintChannels, constname);
+                               if(conchan->ipo==NULL) {
+                                       conchan->ipo= add_ipo("CoIpo", ID_CO);  
+                               }
+                               return conchan->ipo;
+                       }
+                       else {
+                               if(achan->ipo==NULL) {
+                                       achan->ipo= add_ipo("ActIpo", blocktype);
+                               }
+                               
+                               return achan->ipo;
+                       }
                }
        }
-       else if( type==ID_AC) {
-               act= (bAction *)from;
-               if (act->id.lib) return NULL;
-               
-               /* weak... the *from pointer has action, ipo doesnt give more context info yet */
-               verify_active_action_channel(OBACT);
-               
-               if (act->achan==NULL)
-                       return NULL;
+       else {
                
-               ipo= act->achan->ipo;
+               switch(GS(from->name)) {
+               case ID_OB:
+                       {
+                               Object *ob= (Object *)from;
+                               /* constraint exception */
+                               if(blocktype==ID_CO) {
+                                       bConstraintChannel *conchan= verify_constraint_channel(&ob->constraintChannels, constname);
+                                       if(conchan->ipo==NULL) {
+                                               conchan->ipo= add_ipo("CoIpo", ID_CO);  
+                                       }
+                                       return conchan->ipo;
+                               }
+                               else if(blocktype==ID_OB) {
+                                       if(ob->ipo==NULL) {
+                                               ob->ipo= add_ipo("ObIpo", ID_OB);
+                                       }
+                                       return ob->ipo;
+                               }
+                       }
+                       break;
+               case ID_MA:
+                       {
+                               Material *ma= (Material *)from;
 
-               if(make && ipo==NULL) {
-                       ipo= act->achan->ipo= add_ipo(act->achan->name, ID_AC);
-                       allspace(REMAKEIPO, 0);
-                       allqueue(REDRAWIPO, 0);
-                       allqueue(REDRAWACTION, 0);
-               }
-       }
-       else if( type==ID_MA) {
-               ma= (Material *)from;
-               if(ma->id.lib) return NULL;
-               ipo= ma->ipo;
-               
-               if(make && ipo==NULL) ipo= ma->ipo= add_ipo("MatIpo", ID_MA);
-       }
-       else if( type==ID_TE) {
-               tex= (Tex *)from;
-               if(tex->id.lib) return NULL;
-               ipo= tex->ipo;
-               
-               if(make && ipo==NULL) ipo= tex->ipo= add_ipo("TexIpo", ID_TE);
-       }
-       else if( type==ID_SEQ) {
-               seq= (Sequence *)from;
+                               if(ma->ipo==NULL) {
+                                       ma->ipo= add_ipo("MatIpo", ID_MA);
+                               }
+                               return ma->ipo;
+                       }
+                       break;
+               case ID_TE:
+                       {
+                               Tex *tex= (Tex *)from;
+
+                               if(tex->ipo==NULL) {
+                                       tex->ipo= add_ipo("TexIpo", ID_TE);
+                               }
+                               return tex->ipo;
+                       }
+                       break;
+               case ID_SEQ:
+                       {
+                               Sequence *seq= (Sequence *)from;        /* note, sequence is mimicing Id */
+
+                               if((seq->type & SEQ_EFFECT)||(seq->type == SEQ_SOUND)) {
+                                       if(seq->ipo==NULL) {
+                                               seq->ipo= add_ipo("SeqIpo", ID_SEQ);
+                                       }
+                                       return seq->ipo;
+                               }
+                       }
+                       break;
+               case ID_CU:
+                       {
+                               Curve *cu= (Curve *)from;
+                               
+                               if(cu->ipo==NULL) {
+                                       cu->ipo= add_ipo("CuIpo", ID_CU);
+                               }
+                               return cu->ipo;
+                       }
+                       break;
+               case ID_KE:
+                       {
+                               Key *key= (Key *)from;
+
+                               if(key->ipo==NULL) {
+                                       key->ipo= add_ipo("KeyIpo", ID_KE);
+                               }
+                               return key->ipo;
+                       }
+                       break;
+               case ID_WO:
+                       {
+                               World *wo= (World *)from;
+
+                               if(wo->ipo==NULL) {
+                                       wo->ipo= add_ipo("WoIpo", ID_WO);
+                               }
+                               return wo->ipo;
+                       }
+                       break;
+               case ID_LA:
+                       {
+                               Lamp *la= (Lamp *)from;
+                               
+                               if(la->ipo==NULL) {
+                                       la->ipo= add_ipo("LaIpo", ID_LA);
+                               }
+                               return la->ipo;
+                       }
+                       break;
+               case ID_CA:
+                       {
+                               Camera *ca= (Camera *)from;
 
-               if((seq->type & SEQ_EFFECT)||(seq->type == SEQ_SOUND)) {
-                       ipo= seq->ipo;
-                       if(make && ipo==NULL) ipo= seq->ipo= add_ipo("SeqIpo", ID_SEQ);
+                               if(ca->ipo==NULL) {
+                                       ca->ipo= add_ipo("CaIpo", ID_CA);
+                               }
+                               return ca->ipo;
+                       }
+                       break;
+               case ID_SO:
+                       {
+                               bSound *snd= (bSound *)from;
+
+                               if(snd->ipo==NULL) {
+                                       snd->ipo= add_ipo("SndIpo", ID_SO);
+                               }
+                               return snd->ipo;
+                       }
                }
-               else return NULL;
-       }               
-       else if( type==ID_CU) {
-               cu= (Curve *)from;
-               if(cu->id.lib) return NULL;
-               ipo= cu->ipo;
-               
-               if(make && ipo==NULL) ipo= cu->ipo= add_ipo("CuIpo", ID_CU);
-       }
-       else if( type==ID_KE) {
-               key= (Key *)from;
-               if(key->id.lib) return NULL;
-               ipo= key->ipo;
-               
-               if(make && ipo==NULL) ipo= key->ipo= add_ipo("KeyIpo", ID_KE);
-       }
-       else if( type==ID_WO) {
-               wo= (World *)from;
-               if(wo->id.lib) return NULL;
-               ipo= wo->ipo;
-               
-               if(make && ipo==NULL) ipo= wo->ipo= add_ipo("WoIpo", ID_WO);
-       }
-       else if( type==ID_LA) {
-               la= (Lamp *)from;
-               if(la->id.lib) return NULL;
-               ipo= la->ipo;
-               
-               if(make && ipo==NULL) ipo= la->ipo= add_ipo("LaIpo", ID_LA);
        }
-       else if( type==ID_CA) {
-               ca= (Camera *)from;
-               if(ca->id.lib) return NULL;
-               ipo= ca->ipo;
-               
-               if(make && ipo==NULL) ipo= ca->ipo= add_ipo("CaIpo", ID_CA);
-       }
-       else if( type==ID_SO) {
-               bSound *snd= (bSound *)from;
-               if(snd->id.lib) return NULL;
-               ipo= snd->ipo;
-               
-               if(make && ipo==NULL) ipo= snd->ipo= add_ipo("SndIpo", ID_SO);
-       }
-       else return NULL;
        
-       return ipo;     
+       return NULL;    
 }
 
-
-// this function should not have the G.sipo in it...
-
-IpoCurve *get_ipocurve(ID *from, short type, int adrcode, Ipo *useipo)
+/* returns and creates */
+IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constname, int adrcode)
 {
-       Ipo *ipo= NULL;
-       IpoCurve *icu=NULL;
+       Ipo *ipo;
+       IpoCurve *icu= NULL;
        
        /* return 0 if lib */
-       /* also test if ipo and ipocurve exist */
-
-       if (useipo==NULL) {
-               if (G.sipo==NULL || G.sipo->pin==0){
-                       ipo= get_ipo(from, type, 1);    /* 1= make */
-               }
-               else
-                       ipo = G.sipo->ipo;
-               
-               if(G.sipo) {
-                       if (G.sipo->pin==0) G.sipo->ipo= ipo;
-               }
-       }
-       else
-               ipo= useipo;
-
-               
-       if(ipo && ipo->id.lib==0) {
+       /* creates ipo too */
+       ipo= verify_ipo(from, blocktype, actname, constname);
        
-               icu= ipo->curve.first;
-               while(icu) {
+       if(ipo && ipo->id.lib==NULL) {
+               
+               for(icu= ipo->curve.first; icu; icu= icu->next) {
                        if(icu->adrcode==adrcode) break;
-                       icu= icu->next;
                }
-               if(icu==0) {
+               if(icu==NULL) {
                        icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
-                       
-                       icu->flag |= IPO_VISIBLE|IPO_AUTO_HORIZ;
 
-                       if (!useipo && G.sipo && G.sipo->pin)
-                               icu->blocktype = G.sipo->blocktype;
-                       else
-                               icu->blocktype= type;
+                       icu->flag |= IPO_VISIBLE|IPO_AUTO_HORIZ;
+                       icu->blocktype= blocktype;
                        icu->adrcode= adrcode;
                        
                        set_icu_vars(icu);
@@ -2047,6 +1750,7 @@ IpoCurve *get_ipocurve(ID *from, short type, int adrcode, Ipo *useipo)
                        BLI_addtail( &(ipo->curve), icu);
                }
        }
+
        return icu;
 }
 
@@ -2138,17 +1842,19 @@ void add_vert_ipo(void)
        
        if(mval[0]>G.v2d->mask.xmax) return;
        
-       ei= get_editipo();
+       ei= get_active_editipo();
        if(ei==0) {
-               error("Too many (or no) EditIpos");
+               error("No active Ipo curve");
                return;
        }
        
        areamouseco_to_ipoco(G.v2d, mval, &x, &y);
        
        if(ei->icu==NULL) {
-               if(G.sipo->from)
-                       ei->icu= get_ipocurve(G.sipo->from, G.sipo->blocktype, ei->adrcode, 0);
+               if(G.sipo->from) {
+                       ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, ei->adrcode);
+                       ei->flag |= ei->icu->flag & IPO_AUTO_HORIZ;     /* new curve could have been added, weak... */
+               }
        }
        if(ei->icu==NULL) return;
 
@@ -2169,1094 +1875,970 @@ void add_vert_ipo(void)
        BIF_undo_push("Add Ipo vertex");
 }
 
-void add_duplicate_editipo(void)
+static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, IpoCurve *icu, int *vartype)
 {
-       Object *ob;
-       EditIpo *ei;
-       IpoCurve *icu;
-       BezTriple *bezt, *beztn, *newb;
-       int tot, a, b;
-       
-       get_status_editipo();
-       if(totipo_vertsel==0) return;
-       
-       ei= G.sipo->editipo;
-       for(a=0; a<G.sipo->totipo; a++, ei++) {
-               if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
-                       if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
-                               icu= ei->icu;
-                               
-                               /* how many points */
-                               tot= 0;
-                               b= icu->totvert;
-                               bezt= icu->bezt;
-                               while(b--) {
-                                       if(bezt->f2 & 1) tot++;
-                                       bezt++;
-                               }
-                               
-                               if(tot) {
-                                       icu->totvert+= tot;
-                                       newb= beztn= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt");
-                                       bezt= icu->bezt;
-                                       b= icu->totvert-tot;
-                                       while(b--) {
-                                               *beztn= *bezt;
-                                               if(bezt->f2 & 1) {
-                                                       beztn->f1= beztn->f2= beztn->f3= 0;
-                                                       beztn++;
-                                                       *beztn= *bezt;
-                                               }
-                                               beztn++;
-                                               bezt++;
-                                       }
-                                       MEM_freeN(icu->bezt);
-                                       icu->bezt= newb;
-                                       
-                                       calchandles_ipocurve(icu);
-                               }
-                       }
-               }
-       }
-       
-       if(G.sipo->showkey) {
-               make_ipokey();
-               if(G.sipo->blocktype==ID_OB) {
-                       ob= OBACT;
-                       if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
+       if(blocktype==ID_PO) {
+               if(GS(id->name)==ID_OB) {
+                       Object *ob= (Object *)id;
+                       bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
+                       
+                       *vartype= IPO_FLOAT;
+                       return get_pchan_ipo_poin(pchan, icu->adrcode);
                }
+               return NULL;
        }
-       BIF_undo_push("Duplicate Ipo");
-       transform_ipo('g');
+       else
+               return get_ipo_poin(id, icu, vartype);
+
 }
 
-void remove_doubles_ipo(void)
+void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcode)
 {
-       EditIpo *ei;
-       IpoKey *ik, *ikn;
-       BezTriple *bezt, *newb, *new1;
-       float val;
-       int mode, a, b;
+       IpoCurve *icu;
+       Object *ob;
+       void *poin= NULL;
+       float curval, cfra;
+       int vartype;
        
-       ei= G.sipo->editipo;
-       for(a=0; a<G.sipo->totipo; a++, ei++) {
-               if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
-                       
-                       /* OR the curve is selected OR in editmode OR in keymode */
-                       mode= 0;
-                       if(G.sipo->showkey || (ei->flag & IPO_EDIT)) mode= 1;
-                       else if(ei->flag & IPO_SELECT) mode= 2;
-                       
-                       if(mode) {
-                               bezt= ei->icu->bezt;
-                               newb= new1= MEM_mallocN(ei->icu->totvert*sizeof(BezTriple), "newbezt");
-                               *newb= *bezt;
-                               b= ei->icu->totvert-1;
-                               bezt++;
-                               while(b--) {
-                                       
-                                       /* can we remove? */
-                                       if(mode==2 || (bezt->f2 & 1)) {
-                                       
-                                               /* are the points different? */
-                                               if( fabs( bezt->vec[1][0]-newb->vec[1][0] ) > 0.9 ) {
-                                                       newb++;
-                                                       *newb= *bezt;
-                                               }
-                                               else {
-                                                       /* median */
-                                                       VecMidf(newb->vec[0], newb->vec[0], bezt->vec[0]);
-                                                       VecMidf(newb->vec[1], newb->vec[1], bezt->vec[1]);
-                                                       VecMidf(newb->vec[2], newb->vec[2], bezt->vec[2]);
-                                                       
-                                                       newb->h1= newb->h2= HD_FREE;
-                                                       
-                                                       ei->icu->totvert--;
-                                               }
-                                               
-                                       }
-                                       else {
-                                               newb++;
-                                               *newb= *bezt;
-                                       }
-                                       bezt++;
-                               }
-                               
-                               MEM_freeN(ei->icu->bezt);
-                               ei->icu->bezt= new1;
-                               
-                               calchandles_ipocurve(ei->icu);                          
-                       }
-               }
-       }
+       icu= verify_ipocurve(id, blocktype, actname, constname, adrcode);
        
-       editipo_changed(G.sipo, 1);     /* makes ipokeys again! */
-
-       /* remove double keys */
-       if(G.sipo->showkey) {
-               ik= G.sipo->ipokey.first;
-               ikn= ik->next;
+       if(icu) {
                
-               while(ik && ikn) {
-                       if( (ik->flag & 1) && (ikn->flag & 1) ) {
-                               if( fabs(ik->val-ikn->val) < 0.9 ) {
-                                       val= (float)((ik->val + ikn->val)/2.0);
-                                       
-                                       for(a=0; a<G.sipo->totipo; a++) {
-                                               if(ik->data[a]) ik->data[a]->vec[1][0]= val;
-                                               if(ikn->data[a]) ikn->data[a]->vec[1][0]= val;                                          
-                                       }
+               poin= get_context_ipo_poin(id, blocktype, actname, icu, &vartype);
+               
+               if(poin) {
+                       curval= read_ipo_poin(poin, vartype);
+                       
+                       cfra= frame_to_float(CFRA);
+                       
+                       /* if action is mapped in NLA, it returns a correction */
+                       if(actname && actname[0] && GS(id->name)==ID_OB)
+                               cfra= get_action_frame((Object *)id, cfra);
+                       
+                       if( GS(id->name)==ID_OB ) {
+                               ob= (Object *)id;
+                               if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
+                                       /* actually frametofloat calc again! */
+                                       cfra-= ob->sf*G.scene->r.framelen;
                                }
                        }
-                       ik= ikn;
-                       ikn= ikn->next;
-
+                       
+                       insert_vert_ipo(icu, cfra, curval);
                }
-               
-               editipo_changed(G.sipo, 1);     /* makes ipokeys agian! */
-
        }
-       deselectall_editipo();
-}
-
-void join_ipo_menu(void)
-{
-       int mode = 0;
-       mode= pupmenu("Join %t|All Selected %x1|Selected Doubles %x2");
-       
-       if (mode == -1) return;
-       
-       join_ipo(mode);
 }
 
-void join_ipo(int mode)
+void insertkey_editipo(void)
 {
        EditIpo *ei;
        IpoKey *ik;
-       IpoCurve *icu;
-       BezTriple *bezt, *beztn, *newb;
-       float val;
-       int tot, a, b;
-       
-       get_status_editipo();
+       ID *id;
+       float *fp, cfra, *insertvals;
+       int a, nr, ok, tot;
+       short event;
        
-       /* Mode events:
-        * All Selected: 1
-        * Selected Doubles: 2
-        */
+       ei= get_active_editipo();
+       if(ei && ei->icu && ei->icu->driver) 
+               event= pupmenu("Insert Curve %t|Default one-to-one mapping %x3");
+       else if(G.sipo->showkey)
+               event= pupmenu("Insert Key Vertices %t|Current Frame %x1|Selected Keys %x2");
+       else 
+               event= pupmenu("Insert Key Vertices %t|Current Frame %x1");
        
-       if( mode==2 ) {
-               remove_doubles_ipo();
-               return;
-       }
+       if(event<1) return;
        
-       /* first: multiple selected verts in 1 curve */
-       ei= G.sipo->editipo;
-       for(a=0; a<G.sipo->totipo; a++, ei++) {
-               if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
-                       if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
-                               icu= ei->icu;
-                               
-                               /* how many points */
-                               tot= 0;
-                               b= icu->totvert;
-                               bezt= icu->bezt;
-                               while(b--) {
-                                       if(bezt->f2 & 1) tot++;
-                                       bezt++;
-                               }
-                               
-                               if(tot>1) {
-                                       tot--;
-                                       icu->totvert-= tot;
-                                       
-                                       newb= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt");
-                                       /* the first point is the new one */
-                                       beztn= newb+1;
-                                       tot= 0;
-                                       
-                                       bezt= icu->bezt;
-                                       b= icu->totvert+tot+1;
-                                       while(b--) {
-                                               
-                                               if(bezt->f2 & 1) {
-                                                       if(tot==0) *newb= *bezt;
-                                                       else {
-                                                               VecAddf(newb->vec[0], newb->vec[0], bezt->vec[0]);
-                                                               VecAddf(newb->vec[1], newb->vec[1], bezt->vec[1]);
-                                                               VecAddf(newb->vec[2], newb->vec[2], bezt->vec[2]);
-                                                       }
-                                                       tot++;
-                                               }
-                                               else {
-                                                       *beztn= *bezt;
-                                                       beztn++;
-                                               }
-                                               bezt++;
-                                       }
-                                       
-                                       VecMulf(newb->vec[0], (float)(1.0/((float)tot)));
-                                       VecMulf(newb->vec[1], (float)(1.0/((float)tot)));
-                                       VecMulf(newb->vec[2], (float)(1.0/((float)tot)));
-                                       
-                                       MEM_freeN(icu->bezt);
-                                       icu->bezt= newb;
-                                       
-                                       sort_time_ipocurve(icu);
-                                       calchandles_ipocurve(icu);
-                               }
-                       }
+       if(event==3) {
+               IpoDriver *driver= ei->icu->driver;
+               
+               if(ei->icu->bezt) MEM_freeN(ei->icu->bezt);
+               ei->icu->totvert= 0;
+               ei->icu->bezt= NULL;
+               
+               insert_vert_ipo(ei->icu, 0.0f, 0.0f);
+               
+               if(ELEM3(driver->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) {
+                       if(ei->disptype==IPO_DISPDEGR)
+                               insert_vert_ipo(ei->icu, 18.0f, 18.0f);
+                       else
+                               insert_vert_ipo(ei->icu, 18.0f, 1.0f);
                }
+               else
+                       insert_vert_ipo(ei->icu, 1.0f, 1.0f);
+               
+               ei->flag |= IPO_SELECT|IPO_VISIBLE;
+               ei->icu->flag= ei->flag;
+               ei->icu->extrap= IPO_DIR;
+
+               do_ipo_buttons(B_IPOHOME);
        }
-       
-       /* next: in keymode: join multiple selected keys */
-       
-       editipo_changed(G.sipo, 1);     /* makes ipokeys again! */
-       
-       if(G.sipo->showkey) {
-               ik= G.sipo->ipokey.first;
-               val= 0.0;
-               tot= 0;
-               while(ik) {
-                       if(ik->flag & 1) {
-                               for(a=0; a<G.sipo->totipo; a++) {
-                                       if(ik->data[a]) {
-                                               val+= ik->data[a]->vec[1][0];
-                                               break;
-                                       }
-                               }
-                               tot++;
-                       }
-                       ik= ik->next;
-               }
-               if(tot>1) {
-                       val/= (float)tot;
+       else {
+               ei= G.sipo->editipo;
+               for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
+                       if (ISPOIN(ei, flag & IPO_VISIBLE, icu)) {
                        
-                       ik= G.sipo->ipokey.first;
-                       while(ik) {
-                               if(ik->flag & 1) {
-                                       for(a=0; a<G.sipo->totipo; a++) {
-                                               if(ik->data[a]) {
-                                                       ik->data[a]->vec[1][0]= val;
-                                               }
-                                       }
-                               }
-                               ik= ik->next;
-                       }
-                       editipo_changed(G.sipo, 0);
-               }
-       }
-       deselectall_editipo();
-       BIF_undo_push("Join Ipo");
-}
-
-void ipo_snap_menu(void)
-{
-       short event;
-       
-       event= pupmenu("Snap %t|Horizontal %x1|To Next %x2|To Frame %x3|To Current Frame%x4");
-       if(event < 1) return;
-
-       ipo_snap(event);
-}
-
-void ipo_snap(short event)
-{
-       EditIpo *ei;
-       BezTriple *bezt;
-       float dx = 0.0;
-       int a, b;
-       short ok, ok2;
-       
-       /* events:
-        * Horizontal : 1
-        * To Next: 2
-        * To Frame: 3
-        * To Current Frame: 4
-        */
-        
-       get_status_editipo();
+                               ok= 0;
+                               if(G.sipo->showkey) ok= 1;
+                               else if(ei->flag & IPO_SELECT) ok= 1;
 
-       ei= G.sipo->editipo;
-       for(b=0; b<G.sipo->totipo; b++, ei++) {
-               if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
-               
-                       ok2= 0;
-                       if(G.sipo->showkey) ok2= 1;
-                       else if(totipo_vert && (ei->flag & IPO_EDIT)) ok2= 2;
-                       else if(totipo_vert==0 && (ei->flag & IPO_SELECT)) ok2= 3;
-                       
-                       if(ok2) {
-                               bezt= ei->icu->bezt;
-                               a= ei->icu->totvert;
-                               while(a--) {
-                                       ok= 0;
-                                       if(totipo_vert) {
-                                                if(bezt->f2 & 1) ok= 1;
+                               if(ok) {
+                                       /* count amount */
+                                       if(event==1) tot= 1;
+                                       else {
+                                               ik= G.sipo->ipokey.first;
+                                               tot= 0;
+                                               while(ik) {
+                                                       if(ik->flag & 1) tot++;
+                                                       ik= ik->next;
+                                               }
                                        }
-                                       else ok= 1;
+                                       if(tot) {
                                        
-                                       if(ok) {
-                                               if(event==1) {
-                                                       bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
-                                                       if(bezt->h1==HD_AUTO || bezt->h1==HD_VECT) bezt->h1= HD_ALIGN;
-                                                       if(bezt->h2==HD_AUTO || bezt->h2==HD_VECT) bezt->h2= HD_ALIGN;
-                                               }
-                                               else if(event==2) {
-                                                       if(a) {
-                                                               bezt->vec[0][1]= bezt->vec[1][1]= bezt->vec[2][1]= (bezt+1)->vec[1][1];
-                                                               if(bezt->h1==HD_AUTO || bezt->h1==HD_VECT) bezt->h1= HD_ALIGN;
-                                                               if(bezt->h2==HD_AUTO || bezt->h2==HD_VECT) bezt->h2= HD_ALIGN;
+                                               /* correction for ob timeoffs */
+                                               cfra= frame_to_float(CFRA);
+                                               id= G.sipo->from;       
+                                               if(id && GS(id->name)==ID_OB ) {
+                                                       Object *ob= (Object *)id;
+                                                       if(ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
+                                                               cfra-= ob->sf*G.scene->r.framelen;
                                                        }
                                                }
-                                               else if(event==3) {
-                                                       bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5));
-                                               }
-                                               else if(event==4) {     /* to current frame */
+                                               else if(id && GS(id->name)==ID_SEQ) {
+                                                       extern Sequence *last_seq;      /* editsequence.c */
                                                        
-                                                       if(ok2==1 || ok2==2) {
-                                                               
-                                                               if(G.sipo->blocktype==ID_SEQ) {
-                                                                       Sequence *seq;
+                                                       if(last_seq) {
+                                                               cfra= (float)(100.0*(cfra-last_seq->startdisp)/((float)(last_seq->enddisp-last_seq->startdisp)));
+                                                       }
+                                               }
+                               
+                                               insertvals= MEM_mallocN(sizeof(float)*2*tot, "insertkey_editipo");
+                                               /* make sure icu->curval is correct */
+                                               calc_ipo(G.sipo->ipo, cfra);
+                                               
+                                               if(event==1) {
+                                                       insertvals[0]= cfra;
                                                        
-                                                                       seq= (Sequence *)G.sipo->from;
-                                                                       if(seq) {
-                                                                               dx= (float)(CFRA-seq->startdisp);
-                                                                               dx= (float)(100.0*dx/((float)(seq->enddisp-seq->startdisp)));
-                                                                               
-                                                                               dx-= bezt->vec[1][0];
-                                                                       }
+                                                       insertvals[1]= ei->icu->curval;
+                                               }
+                                               else {
+                                                       fp= insertvals;
+                                                       ik= G.sipo->ipokey.first;
+                                                       while(ik) {
+                                                               if(ik->flag & 1) {
+                                                                       calc_ipo(G.sipo->ipo, ik->val);
+
+                                                                       fp[0]= ik->val;
+                                                                       fp[1]= ei->icu->curval;
+                                                                       fp+= 2;
                                                                }
-                                                               else dx= G.scene->r.framelen*CFRA - bezt->vec[1][0];
-                                                               
-                                                               bezt->vec[0][0]+= dx;
-                                                               bezt->vec[1][0]+= dx;
-                                                               bezt->vec[2][0]+= dx;
+                                                               ik= ik->next;
                                                        }
                                                }
+                                               fp= insertvals;
+                                               for(a=0; a<tot; a++, fp+=2) {
+                                                       insert_vert_ipo(ei->icu, fp[0], fp[1]);
+                                               }
+                                               
+                                               MEM_freeN(insertvals);
+                                               calc_ipo(G.sipo->ipo, (float)CFRA);
                                        }
-                                       
-                                       bezt++;
                                }
-                               calchandles_ipocurve(ei->icu);
                        }
                }
        }
-       editipo_changed(G.sipo, 1);
-       BIF_undo_push("Snap Ipo");
+       BIF_undo_push("Insert Key Ipo");
+       allqueue (REDRAWACTION, 0);
+       allqueue(REDRAWNLA, 0);
+       allqueue(REDRAWIPO, 0);
+       allspace(REMAKEIPO, 0);
 }
 
 
-
-void mouse_select_ipo(void)
+void common_insertkey(void)
 {
+       Base *base;
        Object *ob;
-       Key *key;
-       KeyBlock *kb, *actkb=NULL, *curkb;
-       EditIpo *ei, *actei= 0;
+       Material *ma;
+       ID *id;
        IpoCurve *icu;
-       IpoKey *ik, *actik;
-       BezTriple *bezt;
-       float x, y, dist, mindist;
-       int a, oldflag = 0, hand, ok;
-       short mval[2], xo, yo;
-       
-       if(G.sipo->editipo==0) return;
-       
-       get_status_editipo();
-       
-       if(G.sipo->showkey) {
-               getmouseco_areawin(mval);
+       World *wo;
+       Lamp *la;
+       int tlay, map, event;
+       char menustr[256];
        
-               areamouseco_to_ipoco(G.v2d, mval, &x, &y);
-               actik= 0;
-               mindist= 1000.0;
-               ik= G.sipo->ipokey.first;
-               while(ik) {
-                       dist= (float)(fabs(ik->val-x));
-                       if(ik->flag & 1) dist+= 1.0;
-                       if(dist < mindist) {
-                               actik= ik;
-                               mindist= dist;
-                       }
-                       ik= ik->next;
-               }
-               if(actik) {
-                       oldflag= actik->flag;
-                       
-                       if(G.qual & LR_SHIFTKEY);
-                       else deselectall_editipo();
-                       
-                       if(G.qual & LR_SHIFTKEY) {
-                               if(oldflag & 1) actik->flag &= ~1;
-                               else actik->flag |= 1;
-                       }
-                       else {
-                               actik->flag |= 1;
-                       }
-               }
+       if(curarea->spacetype==SPACE_IPO) {
+               insertkey_editipo();
        }
-       else if(totipo_edit) {
-       
-               hand= findnearest_ipovert(&icu, &bezt);
-
-               if(G.qual & LR_SHIFTKEY) {
-                       if(bezt) {
-                               if(hand==1) {
-                                       if(BEZSELECTED(bezt)) {
-                                               bezt->f1= bezt->f2= bezt->f3= 0;
+       else if(curarea->spacetype==SPACE_BUTS) {
+               if(G.buts->mainb==CONTEXT_SHADING) {
+                       int tab= G.buts->tab[CONTEXT_SHADING];
+                       
+                       if(tab==TAB_SHADING_MAT) {
+                               id= G.buts->lockpoin;
+                               ma= G.buts->lockpoin;
+                               if(id) {
+                                       event= pupmenu("Insert Key %t|RGB%x0|Alpha%x1|Halo Size%x2|Mode %x3|All Color%x10|All Mirror%x14|Ofs%x12|Size%x13|All Mapping%x11");
+                                       if(event== -1) return;
+                                       
+                                       map= texchannel_to_adrcode(ma->texact);
+                                       
+                                       if(event==0 || event==10) {
+                                               insertkey(id, ID_MA, NULL, NULL, MA_COL_R);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_COL_G);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_COL_B);
                                        }
-                                       else {
-                                               bezt->f1= bezt->f2= bezt->f3= 1;
+                                       if(event==1 || event==10) {
+                                               insertkey(id, ID_MA, NULL, NULL, MA_ALPHA);
+                                       }
+                                       if(event==2 || event==10) {
+                                               insertkey(id, ID_MA, NULL, NULL, MA_HASIZE);
+                                       }
+                                       if(event==3 || event==10) {
+                                               insertkey(id, ID_MA, NULL, NULL, MA_MODE);
+                                       }
+                                       if(event==10) {
+                                               insertkey(id, ID_MA, NULL, NULL, MA_SPEC_R);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_SPEC_G);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_SPEC_B);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_REF);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_EMIT);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_AMB);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_SPEC);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_HARD);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_MODE);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_TRANSLU);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_ADD);
+                                       }
+                                       if(event==14) {
+                                               insertkey(id, ID_MA, NULL, NULL, MA_RAYM);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_FRESMIR);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_FRESMIRI);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_FRESTRA);
+                                               insertkey(id, ID_MA, NULL, NULL, MA_FRESTRAI);
+                                       }
+                                       if(event==12 || event==11) {
+                                               insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_X);
+                                               insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_Y);
+                                               insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_Z);
+                                       }
+                                       if(event==13 || event==11) {
+                                               insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_X);
+                                               insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_Y);
+                                               insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_Z);
+                                       }
+                                       if(event==11) {
+                                               insertkey(id, ID_MA, NULL, NULL, map+MAP_R);
+                                               insertkey(id, ID_MA, NULL, NULL, map+MAP_G);
+                                               insertkey(id, ID_MA, NULL, NULL, map+MAP_B);
+                                               insertkey(id, ID_MA, NULL, NULL, map+MAP_DVAR);
+                                               insertkey(id, ID_MA, NULL, NULL, map+MAP_COLF);
+                                               insertkey(id, ID_MA, NULL, NULL, map+MAP_NORF);
+                                               insertkey(id, ID_MA, NULL, NULL, map+MAP_VARF);
+                                               insertkey(id, ID_MA, NULL, NULL, map+MAP_DISP);
                                        }
                                }
-                               else if(hand==0) {
-                                       if(bezt->f1 & 1) bezt->f1= 0;
-                                       else bezt->f1= 1;
-                               }
-                               else {
-                                       if(bezt->f3 & 1) bezt->f3= 0;
-                                       else bezt->f3= 1;
+                       }
+                       else if(tab==TAB_SHADING_WORLD) {
+                               id= G.buts->lockpoin;
+                               wo= G.buts->lockpoin;
+                               if(id) {
+                                       event= pupmenu("Insert Key %t|Zenith RGB%x0|Horizon RGB%x1|Mist%x2|Stars %x3|Offset%x12|Size%x13");
+                                       if(event== -1) return;
+                                       
+                                       map= texchannel_to_adrcode(wo->texact);
+                                       
+                                       if(event==0) {
+                                               insertkey(id, ID_WO, NULL, NULL, WO_ZEN_R);
+                                               insertkey(id, ID_WO, NULL, NULL, WO_ZEN_G);
+                                               insertkey(id, ID_WO, NULL, NULL, WO_ZEN_B);
+                                       }
+                                       if(event==1) {
+                                               insertkey(id, ID_WO, NULL, NULL, WO_HOR_R);
+                                               insertkey(id, ID_WO, NULL, NULL, WO_HOR_G);
+                                               insertkey(id, ID_WO, NULL, NULL, WO_HOR_B);
+                                       }
+                                       if(event==2) {
+                                               insertkey(id, ID_WO, NULL, NULL, WO_MISI);
+                                               insertkey(id, ID_WO, NULL, NULL, WO_MISTDI);
+                                               insertkey(id, ID_WO, NULL, NULL, WO_MISTSTA);
+                                               insertkey(id, ID_WO, NULL, NULL, WO_MISTHI);
+                                       }
+                                       if(event==3) {
+                                               insertkey(id, ID_WO, NULL, NULL, WO_STAR_R);
+                                               insertkey(id, ID_WO, NULL, NULL, WO_STAR_G);
+                                               insertkey(id, ID_WO, NULL, NULL, WO_STAR_B);
+                                               insertkey(id, ID_WO, NULL, NULL, WO_STARDIST);
+                                               insertkey(id, ID_WO, NULL, NULL, WO_STARSIZE);
+                                       }
+                                       if(event==12) {
+                                               insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_X);
+                                               insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_Y);
+                                               insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_Z);
+                                       }
+                                       if(event==13) {
+                                               insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_X);
+                                               insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Y);
+                                               insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Z);
+                                       }
                                }
-                       }                               
-               }
-               else {
-                       deselectall_editipo();
-               
-                       if(bezt) {
-                               if(hand==1) {
-                                       bezt->f1|= 1; bezt->f2|= 1; bezt->f3|= 1;
+                       }
+                       else if(tab==TAB_SHADING_LAMP) {
+                               id= G.buts->lockpoin;
+                               la= G.buts->lockpoin;
+                               if(id) {
+                                       event= pupmenu("Insert Key %t|RGB%x0|Energy%x1|Spot Size%x2|Offset%x12|Size%x13");
+                                       if(event== -1) return;
+                                       
+                                       map= texchannel_to_adrcode(la->texact);
+                                       
+                                       if(event==0) {
+                                               insertkey(id, ID_LA, NULL, NULL, LA_COL_R);
+                                               insertkey(id, ID_LA, NULL, NULL, LA_COL_G);
+                                               insertkey(id, ID_LA, NULL, NULL, LA_COL_B);
+                                       }
+                                       if(event==1) {
+                                               insertkey(id, ID_LA, NULL, NULL, LA_ENERGY);
+                                       }
+                                       if(event==2) {
+                                               insertkey(id, ID_LA, NULL, NULL, LA_SPOTSI);
+                                       }
+                                       if(event==12) {
+                                               insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_X);
+                                               insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_Y);
+                                               insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_Z);
+                                       }
+                                       if(event==13) {
+                                               insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_X);
+                                               insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_Y);
+                                               insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_Z);
+                                       }
+
                                }
-                               else if(hand==0) bezt->f1|= 1;
-                               else bezt->f3|= 1;
                        }
                }
-       }
-       else {
-               
-               /* vertex keys ? */
-               if(G.sipo->blocktype==ID_KE && G.sipo->from) {
-                       int i, index= 1;
-                       
-                       key= (Key *)G.sipo->from;
+               else if(G.buts->mainb==CONTEXT_OBJECT) {
                        ob= OBACT;
-                       curkb= BLI_findlink(&key->block, ob->shapenr-1);
-                       
-                       ei= G.sipo->editipo;
-                       if(key->type==KEY_NORMAL || (ei->flag & IPO_VISIBLE)) {
-                               getmouseco_areawin(mval);
-                               
-                               areamouseco_to_ipoco(G.v2d, mval, &x, &y);
-                               /* how much is 20 pixels? */
-                               mindist= (float)(20.0*(G.v2d->cur.ymax-G.v2d->cur.ymin)/(float)curarea->winy);
-                               
-                               for(i=1, kb= key->block.first; kb; kb= kb->next, i++) {
-                                       dist= (float)(fabs(kb->pos-y));
-                                       if(kb==curkb) dist+= (float)0.01;
-                                       if(dist < mindist) {
-                                               actkb= kb;
-                                               mindist= dist;
-                                               index= i;
+                       if(ob && ob->type==OB_MESH) {
+                               id= (ID *) (ob);
+                               if(id) {
+                                       event= pupmenu("Insert Key %t|Surface Damping%x0|Random Damping%x1|Permeability%x2|Force Strength%x3|Force Falloff%x4");
+                                       if(event== -1) return;
+
+                                       if(event==0) {
+                                               insertkey(id, ID_OB, NULL, NULL, OB_PD_SDAMP);
                                        }
-                               }
-                               if(actkb) {
-                                       ok= TRUE;
-                                       if(G.obedit && actkb!=curkb) {
-                                               ok= okee("Copy key after leaving Edit Mode");
+                                       if(event==1) {
+                                               insertkey(id, ID_OB, NULL, NULL, OB_PD_RDAMP);
                                        }
-                                       if(ok) {
-                                               /* also does all keypos */
-                                               deselectall_editipo();
-                                               set_active_key(index);
-                                               set_active_editipo(ei+index-1);
+                                       if(event==2) {
+                                               insertkey(id, ID_OB, NULL, NULL, OB_PD_PERM);
                                        }
+                                       if(event==3) {
+                                               insertkey(id, ID_OB, NULL, NULL, OB_PD_FSTR);
+                                       }
+                                       if(event==4) {
+                                               insertkey(id, ID_OB, NULL, NULL, OB_PD_FFALL);
+                                       }
+
                                }
                        }
                }
-                       
-               /* select curve */
-               if(actkb==NULL) {
-                       if(totipo_vis==1) {
-                               ei= G.sipo->editipo;
-                               for(a=0; a<G.sipo->totipo; a++, ei++) {
-                                       if(ei->icu) {
-                                               if(ei->flag & IPO_VISIBLE) actei= ei;
+               else if(G.buts->mainb==CONTEXT_EDITING) {
+                       ob= OBACT;
+                       if(ob && ob->type==OB_CAMERA) {
+                               id= G.buts->lockpoin;
+                               if(id) {
+                                       /* yafray: insert key extended with aperture and focal distance */
+                                       if (G.scene->r.renderer==R_INTERN)
+                                               event= pupmenu("Insert Key %t|Lens%x0|Clipping%x1");
+                                       else
+                                               event= pupmenu("Insert Key %t|Lens%x0|Clipping%x1|Aperture%x2|FocalDistance%x3");
+                                       if(event== -1) return;
+
+                                       if(event==0) {
+                                               insertkey(id, ID_CA, NULL, NULL, CAM_LENS);
+                                       }
+                                       else if(event==1) {
+                                               insertkey(id, ID_CA, NULL, NULL, CAM_STA);
+                                               insertkey(id, ID_CA, NULL, NULL, CAM_END);
+                                       }
+                                       else if(event==2) {
+                                               insertkey(id, ID_CA, NULL, NULL, CAM_YF_APERT);
+                                       }
+                                       else if(event==3) {
+                                               insertkey(id, ID_CA, NULL, NULL, CAM_YF_FDIST);
                                        }
                                }
                        }
-                       else if(totipo_vis>1) {
-                               actei= select_proj_ipo(0, 0);
-                       }
-                       
-                       if(actei) oldflag= actei->flag;
-                       
-                       if(G.qual & LR_SHIFTKEY);
-                       else deselectall_editipo();
-                       
-                       if(actei) {
-                               if(G.qual & LR_SHIFTKEY) {
-                                       if(oldflag & IPO_SELECT) actei->flag &= ~IPO_SELECT;
-                                       else actei->flag |= IPO_SELECT;
-                               }
-                               else {
-                                       actei->flag |= IPO_SELECT;
+               }
+               else if(FALSE /* && G.buts->mainb==BUTS_SOUND */) {
+                       if(G.ssound) {
+                               id= G.buts->lockpoin;
+                               if(id) {
+                                       event= pupmenu("Insert Key %t|Volume%x0|Pitch%x1|Panning%x2|Attennuation%x3");
+                                       if(event== -1) return;
+
+                                       if(event==0) {
+                                               insertkey(id, ID_SO, NULL, NULL, SND_VOLUME);
+                                       }
+                                       if(event==1) {
+                                               insertkey(id, ID_SO, NULL, NULL, SND_PITCH);
+                                       }
+                                       if(event==2) {
+                                               insertkey(id, ID_SO, NULL, NULL, SND_PANNING);
+                                       }
+                                       if(event==3) {
+                                               insertkey(id, ID_SO, NULL, NULL, SND_ATTEN);
+                                       }
                                }
-                               set_active_editipo(actei);
                        }
                }
+               
+               BIF_undo_push("Insert Key Buttons");
+
+               allqueue(REDRAWACTION, 0);
+               allqueue(REDRAWNLA, 0);
+               allqueue(REDRAWIPO, 0);
+               allspace(REMAKEIPO, 0);
+
        }
-       
-       update_editipo_flags();
-       
-       force_draw(0);
-       BIF_undo_push("Select Ipo");
-       
-       if(G.sipo->showkey && G.sipo->blocktype==ID_OB) {
-               ob= OBACT;
-               if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
-       }
-       
-       getmouseco_areawin(mval);
-       xo= mval[0]; 
-       yo= mval[1];
+       else if(curarea->spacetype==SPACE_VIEW3D) {
+               ob= OBACT;
 
-       while(get_mbut()&R_MOUSE) {             
-               getmouseco_areawin(mval);
-               if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) {
-                       
-                       if(actkb) move_keys(OBACT);
-                       else transform_ipo('g');
-                       
+               if (ob && (ob->flag & OB_POSEMODE)) {
+                       strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Size%x2|LocRot%x3|LocRotSize%x4|Avail%x9");
+               }
+               else {
+                       base= FIRSTBASE;
+                       while(base) {
+                               if TESTBASELIB(base) break;
+                               base= base->next;
+                       }
+                       if(base==NULL) return;
+               
+                       strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Size%x2|LocRot%x3|LocRotSize%x4|Layer%x5|Avail%x9");
+               }
+               
+               if(ob) {
+                       if(ob->type==OB_MESH) strcat(menustr, "| %x6|Mesh%x7");
+                       else if(ob->type==OB_LATTICE) strcat(menustr, "| %x6|Lattice%x7");
+                       else if(ob->type==OB_CURVE) strcat(menustr, "| %x6|Curve%x7");
+                       else if(ob->type==OB_SURF) strcat(menustr, "| %x6|Surface%x7");
+                       if(ob->flag & OB_FROMGROUP)     strcat(menustr, "| %x6|Entire Group%x10");
+               }
+               
+               event= pupmenu(menustr);
+               if(event== -1) return;
+               
+               if(event==7) { // ob != NULL
+                       insert_shapekey(ob);
                        return;
                }
-               BIF_wait_for_statechange();
-       }
-}
+               
+               if(event==10) {
+                       Group *group= find_group(ob);
+                       if(group) {
+                               add_group_key(group);
+                               allqueue(REDRAWBUTSOBJECT, 0);
+                       }
+               }
+               
+               if (ob && (ob->flag & OB_POSEMODE)){
+                       bPoseChannel *pchan;
 
-static int icu_keys_bezier_loop(IpoCurve *icu,
-                         int (*bezier_function)(BezTriple *),
-                         void (ipocurve_function)(struct IpoCurve *icu)) 
-{
-    /*  This loops through the beziers in the Ipocurve, and executes 
-     *  the generic user provided 'bezier_function' on each one. 
-     *  Optionally executes the generic function ipocurve_function on the 
-     *  IPO curve after looping (eg. calchandles_ipocurve)
-     */
-
-    int b;
-    BezTriple *bezt;
-
-    b    = icu->totvert;
-    bezt = icu->bezt;
-
-    /* if bezier_function has been specified
-     * then loop through each bezier executing
-     * it.
-     */
-
-    if (bezier_function != NULL) {
-        while(b--) {
-            /* exit with return code 1 if the bezier function 
-             * returns 1 (good for when you are only interested
-             * in finding the first bezier that
-             * satisfies a condition).
-             */
-            if (bezier_function(bezt)) return 1;
-            bezt++;
-        }
-    }
-
-    /* if ipocurve_function has been specified 
-     * then execute it
-     */
-    if (ipocurve_function != NULL)
-        ipocurve_function(icu);
-
-    return 0;
+                       if (ob->action && ob->action->id.lib) {
+                               error ("Can't key libactions");
+                               return;
+                       }
+                       
+                       set_pose_keys(ob);  // sets pchan->flag to POSE_KEY if bone selected
+                       id= &ob->id;
+                       for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+                               if (pchan->flag & POSE_KEY){
+                                       if(event==0 || event==3 ||event==4) {
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X);
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y);
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z);
+                                       }
+                                       if(event==1 || event==3 ||event==4) {
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X);
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W);
+                                       }
+                                       if(event==2 || event==4) {
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X);
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y);
+                                               insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
+                                       }
+                                       if (event==9 && ob->action) {
+                                               bActionChannel *achan;
+                                               
+                                               for (achan = ob->action->chanbase.first; achan; achan=achan->next){
+                                                       if (achan->ipo && !strcmp (achan->name, pchan->name)){
+                                                               for (icu = achan->ipo->curve.first; icu; icu=icu->next){
+                                                                       insertkey(id, ID_PO, achan->name, NULL, icu->adrcode);
+                                                               }
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       remake_action_ipos(ob->action);
 
-}
+                       DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
 
-static int ipo_keys_bezier_loop(Ipo *ipo,
-                         int (*bezier_function)(BezTriple *),
-                         void (ipocurve_function)(struct IpoCurve *icu))
-{
-    /*  This loops through the beziers that are attached to
-     *  the selected keys on the Ipocurves of the Ipo, and executes 
-     *  the generic user provided 'bezier_function' on each one. 
-     *  Optionally executes the generic function ipocurve_function on a 
-     *  IPO curve after looping (eg. calchandles_ipocurve)
-     */
-
-    IpoCurve *icu;
-
-    /* Loop through each curve in the Ipo
-     */
-    for (icu=ipo->curve.first; icu; icu=icu->next){
-        if (icu_keys_bezier_loop(icu,bezier_function, ipocurve_function))
-            return 1;
-    }
-
-    return 0;
+                       allqueue(REDRAWIPO, 0);
+                       allqueue(REDRAWACTION, 0);
+                       allqueue(REDRAWNLA, 0);
+               }
+               else {
+                       base= FIRSTBASE;
+                       while(base) {
+                               if TESTBASELIB(base) {
+                                       char *actname= NULL;
+                                       
+                                       id= (ID *)(base->object);
+                                       
+                                       if(ob->ipoflag & OB_ACTION_OB)
+                                               actname= "Object";
+                                       
+                                       /* all curves in ipo deselect */
+                                       if(base->object->ipo) {
+                                               icu= base->object->ipo->curve.first;
+                                               while(icu) {
+                                                       icu->flag &= ~IPO_SELECT;
+                                                       if(event==9) insertkey(id, ID_OB, actname, NULL, icu->adrcode);
+                                                       icu= icu->next;
+                                               }
+                                       }
+                                       
+                                       if(event==0 || event==3 ||event==4) {
+                                               insertkey(id, ID_OB, actname, NULL, OB_LOC_X);
+                                               insertkey(id, ID_OB, actname, NULL, OB_LOC_Y);
+                                               insertkey(id, ID_OB, actname, NULL, OB_LOC_Z);
+                                       }
+                                       if(event==1 || event==3 ||event==4) {
+                                               insertkey(id, ID_OB, actname, NULL, OB_ROT_X);
+                                               insertkey(id, ID_OB, actname, NULL, OB_ROT_Y);
+                                               insertkey(id, ID_OB, actname, NULL, OB_ROT_Z);
+                                       }
+                                       if(event==2 || event==4) {
+                                               insertkey(id, ID_OB, actname, NULL, OB_SIZE_X);
+                                               insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y);
+                                               insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z);
+                                       }
+                                       if(event==5) {
+                                               /* remove localview  */
+                                               tlay= base->object->lay;
+                                               base->object->lay &= 0xFFFFFF;
+                                               insertkey(id, ID_OB, actname, NULL, OB_LAY);
+                                               base->object->lay= tlay;
+                                       }
+                               }
+                               base= base->next;
+                       }
+               }
+
+               if(event==0) BIF_undo_push("Insert Loc Key");
+               else if(event==1) BIF_undo_push("Insert Rot Key");
+               else if(event==2) BIF_undo_push("Insert Size Key");
+               else if(event==3) BIF_undo_push("Insert LocRot Key");
+               else if(event==4) BIF_undo_push("Insert LocRotSize Key");
+               else if(event==5) BIF_undo_push("Insert Layer Key");
+               else if(event==7) BIF_undo_push("Insert Vertex Key");
+               else if(event==9) BIF_undo_push("Insert Avail Key");
+
+               allspace(REMAKEIPO, 0);
+               allqueue(REDRAWIPO, 0);
+               allqueue(REDRAWVIEW3D, 0);
+               allqueue(REDRAWACTION, 0);
+               allqueue(REDRAWNLA, 0);
+       }
+       
 }
 
-static int selected_bezier_loop(int (*looptest)(EditIpo *),
-                         int (*bezier_function)(BezTriple *),
-                         void (ipocurve_function)(struct IpoCurve *icu))
-{
-       /*  This loops through the beziers that are attached to
-        *  selected keys in editmode in the IPO window, and executes 
-        *  the generic user-provided 'bezier_function' on each one 
-        *  that satisfies the 'looptest' function. Optionally executes
-        *  the generic function ipocurve_function on a IPO curve
-        *  after looping (eg. calchandles_ipocurve)
-        */
+/* ****************************************************************************** */
 
+void add_duplicate_editipo(void)
+{
+       Object *ob;
        EditIpo *ei;
-       BezTriple *bezt;
-       int a, b;
-
-       /* Get the first Edit Ipo from the selected Ipos
-        */
+       IpoCurve *icu;
+       BezTriple *bezt, *beztn, *newb;
+       int tot, a, b;
+       
+       get_status_editipo();
+       if(totipo_vertsel==0) return;
+       
        ei= G.sipo->editipo;
-
-       /* Loop throught all of the selected Ipo's
-        */
        for(a=0; a<G.sipo->totipo; a++, ei++) {
-               /* Do a user provided test on the Edit Ipo
-                * to determine whether we want to process it
-                */
-               if (looptest(ei)) {
-                       /* Loop through the selected
-                        * beziers on the Edit Ipo
-                        */
-                       bezt = ei->icu->bezt;
-                       b    = ei->icu->totvert;
-                       
-                       /* if bezier_function has been specified
-                        * then loop through each bezier executing
-                        * it.
-                        */
-                       if (bezier_function != NULL) {
+               if (ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt)) {
+                       if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
+                               icu= ei->icu;
+                               
+                               /* how many points */
+                               tot= 0;
+                               b= icu->totvert;
+                               bezt= icu->bezt;
                                while(b--) {
-                                       /* exit with return code 1 if the bezier function 
-                                        * returns 1 (good for when you are only interested
-                                        * in finding the first bezier that
-                                        * satisfies a condition).
-                                        */
-                                       if (bezier_function(bezt)) return 1;
+                                       if(bezt->f2 & 1) tot++;
                                        bezt++;
                                }
+                               
+                               if(tot) {
+                                       icu->totvert+= tot;
+                                       newb= beztn= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt");
+                                       bezt= icu->bezt;
+                                       b= icu->totvert-tot;
+                                       while(b--) {
+                                               *beztn= *bezt;
+                                               if(bezt->f2 & 1) {
+                                                       beztn->f1= beztn->f2= beztn->f3= 0;
+                                                       beztn++;
+                                                       *beztn= *bezt;
+                                               }
+                                               beztn++;
+                                               bezt++;
+                                       }
+                                       MEM_freeN(icu->bezt);
+                                       icu->bezt= newb;
+                                       
+                                       calchandles_ipocurve(icu);
+                               }
                        }
-
-                       /* if ipocurve_function has been specified 
-                        * then execute it
-                        */
-                       if (ipocurve_function != NULL)
-                               ipocurve_function(ei->icu);
-               }
-               /* nufte flourdje zim ploopydu <-- random dutch looking comment ;) */
-               /* looks more like russian to me! (ton) */
-       }
-
-       return 0;
-}
-
-int select_bezier_add(BezTriple *bezt) 
-{
-  /* Select the bezier triple */
-  bezt->f1 |= 1;
-  bezt->f2 |= 1;
-  bezt->f3 |= 1;
-  return 0;
-}
-
-int select_bezier_subtract(BezTriple *bezt) 
-{
-  /* Deselect the bezier triple */
-  bezt->f1 &= ~1;
-  bezt->f2 &= ~1;
-  bezt->f3 &= ~1;
-  return 0;
-}
-
-int select_bezier_invert(BezTriple *bezt) 
-{
-  /* Invert the selection for the bezier triple */
-  bezt->f2 ^= 1;
-  if ( bezt->f2 & 1 ) {
-    bezt->f1 |= 1;
-    bezt->f3 |= 1;
-  }
-  else {
-    bezt->f1 &= ~1;
-    bezt->f3 &= ~1;
-  }
-  return 0;
-}
-
-static int set_bezier_auto(BezTriple *bezt) 
-{
-       /* Sets the selected bezier handles to type 'auto' 
-        */
-
-       /* is a handle selected? If so
-        * set it to type auto
-        */
-       if(bezt->f1 || bezt->f3) {
-               if(bezt->f1) bezt->h1= 1; /* the secret code for auto */
-               if(bezt->f3) bezt->h2= 1;
-
-               /* if the handles are not of the same type, set them
-                * to type free
-                */
-               if(bezt->h1!=bezt->h2) {
-                       if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
-                       if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
                }
        }
-       return 0;
-}
-
-static int set_bezier_vector(BezTriple *bezt) 
-{
-       /* Sets the selected bezier handles to type 'vector' 
-        */
-
-       /* is a handle selected? If so
-        * set it to type vector
-        */
-       if(bezt->f1 || bezt->f3) {
-               if(bezt->f1) bezt->h1= 2; /* the code for vector */
-               if(bezt->f3) bezt->h2= 2;
-    
-               /* if the handles are not of the same type, set them
-                * to type free
-                */
-               if(bezt->h1!=bezt->h2) {
-                       if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
-                       if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
+       
+       if(G.sipo->showkey) {
+               make_ipokey();
+               if(G.sipo->blocktype==ID_OB) {
+                       ob= OBACT;
+                       if(ob && (ob->ipoflag & OB_DRAWKEY)) allqueue(REDRAWVIEW3D, 0);
                }
        }
-       return 0;
-}
-
-static int bezier_isfree(BezTriple *bezt) 
-{
-       /* queries whether the handle should be set
-        * to type 'free' (I think)
-        */
-       if(bezt->f1 && bezt->h1) return 1;
-       if(bezt->f3 && bezt->h2) return 1;
-       return 0;
-}
-
-static int set_bezier_free(BezTriple *bezt) 
-{
-       /* Sets selected bezier handles to type 'free' 
-        */
-       if(bezt->f1) bezt->h1= HD_FREE;
-       if(bezt->f3) bezt->h2= HD_FREE;
-       return 0;
-}
-
-static int set_bezier_align(BezTriple *bezt) 
-{
-       /* Sets selected bezier handles to type 'align' 
-        */
-       if(bezt->f1) bezt->h1= HD_ALIGN;
-       if(bezt->f3) bezt->h2= HD_ALIGN;
-       return 0;
-}
-
-static int vis_edit_icu_bez(EditIpo *ei) 
-{
-       /* A 4 part test for an EditIpo :
-        *   is it a) visible
-        *         b) in edit mode
-        *         c) does it contain an Ipo Curve
-        *         d) does that ipo curve have a bezier
-        *
-        * (The reason why I don't just use the macro
-        * is I need a pointer to a function.)
-        */
-       return ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt);
-}
-
-void select_ipo_bezier_keys(Ipo *ipo, int selectmode)
-{
-  /* Select all of the beziers in all
-   * of the Ipo curves belonging to the
-   * Ipo, using the selection mode.
-   */
-  switch (selectmode) {
-  case SELECT_ADD:
-    ipo_keys_bezier_loop(ipo, select_bezier_add, NULL);
-    break;
-  case SELECT_SUBTRACT:
-    ipo_keys_bezier_loop(ipo, select_bezier_subtract, NULL);
-    break;
-  case SELECT_INVERT:
-    ipo_keys_bezier_loop(ipo, select_bezier_invert, NULL);
-    break;
-  }
+       BIF_undo_push("Duplicate Ipo");
+       transform_ipo('g');
 }
 
-void sethandles_ipo_keys(Ipo *ipo, int code)
+void remove_doubles_ipo(void)
 {
-       /* this function lets you set bezier handles all to
-        * one type for some Ipo's (e.g. with hotkeys through
-        * the action window).
-        */ 
-
-       /* code==1: set autohandle */
-       /* code==2: set vectorhandle */
-       /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
-       
-       switch(code) {
-       case 1:
-               /*** Set to auto ***/
-               ipo_keys_bezier_loop(ipo, set_bezier_auto,
-                                                        calchandles_ipocurve);
-               break;
-       case 2:
-               /*** Set to vector ***/
-               ipo_keys_bezier_loop(ipo, set_bezier_vector,
-                         calchandles_ipocurve);
-               break;
-       default:
-               if ( ipo_keys_bezier_loop(ipo, bezier_isfree, NULL) ) {
-                       /*** Set to free ***/
-                       ipo_keys_bezier_loop(ipo, set_bezier_free,
-                           calchandles_ipocurve);
-               }
-               else {
-                       /*** Set to align ***/
-                       ipo_keys_bezier_loop(ipo, set_bezier_align,
-                           calchandles_ipocurve);
-               }
-               break;
-       }
-
-
-}
-
-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;
-       }
+       EditIpo *ei;
+       IpoKey *ik, *ikn;
+       BezTriple *bezt, *newb, *new1;
+       float val;
+       int mode, a, b;
        
        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;
+               if (ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt)) {
+                       
+                       /* OR the curve is selected OR in editmode OR in keymode */
+                       mode= 0;
+                       if(G.sipo->showkey || (ei->flag & IPO_EDIT)) mode= 1;
+                       else if(ei->flag & IPO_SELECT) mode= 2;
+                       
+                       if(mode) {
+                               bezt= ei->icu->bezt;
+                               newb= new1= MEM_mallocN(ei->icu->totvert*sizeof(BezTriple), "newbezt");
+                               *newb= *bezt;
+                               b= ei->icu->totvert-1;
+                               bezt++;
+                               while(b--) {
+                                       
+                                       /* can we remove? */
+                                       if(mode==2 || (bezt->f2 & 1)) {
+                                       
+                                               /* are the points different? */
+                                               if( fabs( bezt->vec[1][0]-newb->vec[1][0] ) > 0.9 ) {
+                                                       newb++;
+                                                       *newb= *bezt;
+                                               }
+                                               else {
+                                                       /* median */
+                                                       VecMidf(newb->vec[0], newb->vec[0], bezt->vec[0]);
+                                                       VecMidf(newb->vec[1], newb->vec[1], bezt->vec[1]);
+                                                       VecMidf(newb->vec[2], newb->vec[2], bezt->vec[2]);
+                                                       
+                                                       newb->h1= newb->h2= HD_FREE;
+                                                       
+                                                       ei->icu->totvert--;
+                                               }
+                                               
+                                       }
+                                       else {
+                                               newb++;
+                                               *newb= *bezt;
+                                       }
+                                       bezt++;
+                               }
+                               
+                               MEM_freeN(ei->icu->bezt);
+                               ei->icu->bezt= new1;
+                               
+                               calchandles_ipocurve(ei->icu);                          
+                       }
                }
        }
-       update_editipo_flags();
-}
-
-void sethandles_ipo(int code)
-{
-       /* this function lets you set bezier handles all to
-        * one type for some selected keys in edit mode in the
-        * IPO window (e.g. with hotkeys)
-        */ 
-
-       /* code==1: set autohandle */
-       /* code==2: set vectorhandle */
-       /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
-
-       if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
+       
+       editipo_changed(G.sipo, 1);     /* makes ipokeys again! */
 
-       switch(code) {
-       case 1:
-               /*** Set to auto ***/
-               selected_bezier_loop(vis_edit_icu_bez, set_bezier_auto,
-                         calchandles_ipocurve);
-               break;
-       case 2:
-               /*** Set to vector ***/
-               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();
+       /* remove double keys */
+       if(G.sipo->showkey) {
+               ik= G.sipo->ipokey.first;
+               ikn= ik->next;
                
-               break;
-       default:
-               if (selected_bezier_loop(vis_edit_icu_bez, bezier_isfree, NULL) ) {
-                       /*** Set to free ***/
-                       selected_bezier_loop(vis_edit_icu_bez, set_bezier_free,
-                                                                calchandles_ipocurve);
-               }
-               else {
-                       /*** Set to align ***/
-                       selected_bezier_loop(vis_edit_icu_bez, set_bezier_align,
-                                                                calchandles_ipocurve);
-               }
-               break;
-       }
-
-       editipo_changed(G.sipo, 1);
-       BIF_undo_push("Set handles Ipo");
-}
-
-
-static void set_ipocurve_constant(struct IpoCurve *icu) {
-       /* Sets the type of the IPO curve to constant
-        */
-       icu->ipo= IPO_CONST;
-}
+               while(ik && ikn) {
+                       if( (ik->flag & 1) && (ikn->flag & 1) ) {
+                               if( fabs(ik->val-ikn->val) < 0.9 ) {
+                                       val= (float)((ik->val + ikn->val)/2.0);
+                                       
+                                       for(a=0; a<G.sipo->totipo; a++) {
+                                               if(ik->data[a]) ik->data[a]->vec[1][0]= val;
+                                               if(ikn->data[a]) ikn->data[a]->vec[1][0]= val;                                          
+                                       }
+                               }
+                       }
+                       ik= ikn;
+                       ikn= ikn->next;
 
-static void set_ipocurve_linear(struct IpoCurve *icu) {
-       /* Sets the type of the IPO curve to linear
-        */
-       icu->ipo= IPO_LIN;
-}
+               }
+               
+               editipo_changed(G.sipo, 1);     /* makes ipokeys agian! */
 
-static void set_ipocurve_bezier(struct IpoCurve *icu) {
-       /* Sets the type of the IPO curve to bezier
-        */
-       icu->ipo= IPO_BEZ;
+       }
+       deselectall_editipo();
 }
 
-
-void setipotype_ipo(Ipo *ipo, int code)
+void join_ipo_menu(void)
 {
-       /* Sets the type of the each ipo curve in the
-        * Ipo to a value based on the code
-        */
-       switch (code) {
-       case 1:
-               ipo_keys_bezier_loop(ipo, NULL, set_ipocurve_constant);
-               break;
-       case 2:
-               ipo_keys_bezier_loop(ipo, NULL, set_ipocurve_linear);
-               break;
-       case 3:
-               ipo_keys_bezier_loop(ipo, NULL, set_ipocurve_bezier);
-               break;
-       }
+       int mode = 0;
+       mode= pupmenu("Join %t|All Selected %x1|Selected Doubles %x2");
+       
+       if (mode == -1) return;
+       
+       join_ipo(mode);
 }
 
-void set_ipotype(void)
+void join_ipo(int mode)
 {
        EditIpo *ei;
-       int a;
-       short event;
-
-       if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
-       if(G.sipo->showkey) return;
+       IpoKey *ik;
+       IpoCurve *icu;
+       BezTriple *bezt, *beztn, *newb;
+       float val;
+       int tot, a, b;
+       
        get_status_editipo();
        
-       if(G.sipo->blocktype==ID_KE && totipo_edit==0 && totipo_sel==0) {
-               Key *key= (Key *)G.sipo->from;
-               Object *ob= OBACT;
-               KeyBlock *kb;
-               
-               if(key==NULL) return;
-               kb= BLI_findlink(&key->block, ob->shapenr-1);
-               
-               event= pupmenu("Key Type %t|Linear %x1|Cardinal %x2|B Spline %x3");
-               if(event < 1) return;
-
-               kb->type= 0;
-               if(event==1) kb->type= KEY_LINEAR;
-               if(event==2) kb->type= KEY_CARDINAL;
-               if(event==3) kb->type= KEY_BSPLINE;
+       /* Mode events:
+        * All Selected: 1
+        * Selected Doubles: 2
+        */
+       
+       if( mode==2 ) {
+               remove_doubles_ipo();
+               return;
        }
-       else {
-               event= pupmenu("Ipo Type %t|Constant %x1|Linear %x2|Bezier %x3");
-               if(event < 1) return;
-               
-               ei= G.sipo->editipo;
-               for(a=0; a<G.sipo->totipo; a++, ei++) {
-                       if ISPOIN3(ei, flag & IPO_VISIBLE, flag & IPO_SELECT, icu) {
-                               if(event==1) ei->icu->ipo= IPO_CONST;
-                               else if(event==2) ei->icu->ipo= IPO_LIN;
-                               else ei->icu->ipo= IPO_BEZ;
+       
+       /* first: multiple selected verts in 1 curve */
+       ei= G.sipo->editipo;
+       for(a=0; a<G.sipo->totipo; a++, ei++) {
+               if (ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt)) {
+                       if(G.sipo->showkey || (ei->flag & IPO_EDIT)) {
+                               icu= ei->icu;
+                               
+                               /* how many points */
+                               tot= 0;
+                               b= icu->totvert;
+                               bezt= icu->bezt;
+                               while(b--) {
+                                       if(bezt->f2 & 1) tot++;
+                                       bezt++;
+                               }
+                               
+                               if(tot>1) {
+                                       tot--;
+                                       icu->totvert-= tot;
+                                       
+                                       newb= MEM_mallocN(icu->totvert*sizeof(BezTriple), "bezt");
+                                       /* the first point is the new one */
+                                       beztn= newb+1;
+                                       tot= 0;
+                                       
+                                       bezt= icu->bezt;
+                                       b= icu->totvert+tot+1;
+                                       while(b--) {
+                                               
+                                               if(bezt->f2 & 1) {
+                                                       if(tot==0) *newb= *bezt;
+               &nbs