Cycles: svn merge -r39870:r40266 https://svn.blender.org/svnroot/bf-blender/trunk...
[blender-staging.git] / source / blender / blenkernel / intern / key.c
index 3822e0322f76c67d1ddbedc7387a14807f3d9e7c..2aef5b39c71866112d4706cb090d37b8a78c0b2b 100644 (file)
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/blenkernel/intern/key.c
+ *  \ingroup bke
+ */
+
+
 #include <math.h>
 #include <string.h>
+#include <stddef.h>
 
 #include "MEM_guardedalloc.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_editVert.h"
+#include "BLI_math_vector.h"
+#include "BLI_utildefines.h"
 
 #include "DNA_anim_types.h"
-#include "DNA_curve_types.h"
 #include "DNA_key_types.h"
 #include "DNA_lattice_types.h"
-#include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 
 #include "BKE_animsys.h"
-#include "BKE_action.h"
-#include "BKE_blender.h"
 #include "BKE_curve.h"
+#include "BKE_customdata.h"
+#include "BKE_deform.h"
 #include "BKE_global.h"
 #include "BKE_key.h"
 #include "BKE_lattice.h"
 #include "BKE_library.h"
-#include "BKE_mesh.h"
 #include "BKE_main.h"
 #include "BKE_object.h"
-#include "BKE_utildefines.h"
-
-#include "RNA_access.h"
+#include "BKE_deform.h"
 
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include "RNA_access.h"
 
-#define KEY_BPOINT             1
-#define KEY_BEZTRIPLE  2
+#define KEY_MODE_DUMMY         0 /* use where mode isn't checked for */
+#define KEY_MODE_BPOINT                1
+#define KEY_MODE_BEZTRIPLE     2
 
        // old defines from DNA_ipo_types.h for data-type
 #define IPO_FLOAT              4
@@ -154,14 +156,10 @@ Key *copy_key(Key *key)
        Key *keyn;
        KeyBlock *kbn, *kb;
        
-       if(key==0) return 0;
+       if(key==NULL) return NULL;
        
        keyn= copy_libblock(key);
        
-#if 0 // XXX old animation system
-       keyn->ipo= copy_ipo(key->ipo);
-#endif // XXX old animation system
-       
        BLI_duplicatelist(&keyn->block, &key->block);
        
        kb= key->block.first;
@@ -181,18 +179,14 @@ Key *copy_key(Key *key)
 void make_local_key(Key *key)
 {
 
-    /* - only lib users: do nothing
-    * - only local users: set flag
-    * - mixed: make copy
-    */
-    if(key==0) return;
+       /* - only lib users: do nothing
+       * - only local users: set flag
+       * - mixed: make copy
+       */
+       if(key==NULL) return;
        
-       key->id.lib= 0;
-       new_id(0, (ID *)key, 0);
-
-#if 0 // XXX old animation system
-       make_local_ipo(key->ipo);
-#endif // XXX old animation system
+       key->id.lib= NULL;
+       new_id(NULL, (ID *)key, NULL);
 }
 
 /* Sort shape keys and Ipo curves after a change.  This assumes that at most
@@ -377,14 +371,14 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl)
 
        /* if(fac<0.0 || fac>1.0) return 1; */
 
-       if(k1->next==0) return 1;
+       if(k1->next==NULL) return 1;
 
        if(cycl) {      /* pre-sort */
                k[2]= k1->next;
                k[3]= k[2]->next;
-               if(k[3]==0) k[3]=k1;
+               if(k[3]==NULL) k[3]=k1;
                while(k1) {
-                       if(k1->next==0) k[0]=k1;
+                       if(k1->next==NULL) k[0]=k1;
                        k1=k1->next;
                }
                k1= k[1];
@@ -405,13 +399,13 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl)
                k[2]= k1->next;
                t[2]= k[2]->pos;
                k[3]= k[2]->next;
-               if(k[3]==0) k[3]= k[2];
+               if(k[3]==NULL) k[3]= k[2];
                t[3]= k[3]->pos;
                k1= k[3];
        }
        
        while( t[2]<fac ) {     /* find correct location */
-               if(k1->next==0) {
+               if(k1->next==NULL) {
                        if(cycl) {
                                k1= firstkey;
                                ofs+= dpos;
@@ -429,7 +423,7 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl)
                t[3]= k1->pos+ofs; 
                k[3]= k1;
 
-               if(ofs>2.1+lastpos) break;
+               if(ofs > 2.1f + lastpos) break;
        }
        
        bsplinetype= 0;
@@ -455,7 +449,7 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl)
        }
 
        d= t[2]-t[1];
-       if(d==0.0) {
+       if(d == 0.0f) {
                if(bsplinetype==0) {
                        return 1;       /* both keys equal */
                }
@@ -480,20 +474,20 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl)
 
 }
 
-static void flerp(int aantal, float *in, float *f0, float *f1, float *f2, float *f3, float *t) 
+static void flerp(int tot, float *in, float *f0, float *f1, float *f2, float *f3, float *t)
 {
        int a;
 
-       for(a=0; a<aantal; a++) {
+       for(a=0; a<tot; a++) {
                in[a]= t[0]*f0[a]+t[1]*f1[a]+t[2]*f2[a]+t[3]*f3[a];
        }
 }
 
-static void rel_flerp(int aantal, float *in, float *ref, float *out, float fac)
+static void rel_flerp(int tot, float *in, float *ref, float *out, float fac)
 {
        int a;
        
-       for(a=0; a<aantal; a++) {
+       for(a=0; a<tot; a++) {
                in[a]-= fac*(ref[a]-out[a]);
        }
 }
@@ -528,32 +522,53 @@ static char *key_block_get_data(Key *key, KeyBlock *actkb, KeyBlock *kb, char **
        return kb->data;
 }
 
-static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock *kb, float *weights, int mode)
+
+/* currently only the first value of 'ofs' may be set. */
+static short key_pointer_size(const Key *key, const int mode, int *poinsize, int *ofs)
+{
+       if(key->from==NULL) {
+               return FALSE;
+       }
+
+       switch(GS(key->from->name)) {
+       case ID_ME:
+               *ofs= sizeof(float)*3;
+               *poinsize= *ofs;
+               break;
+       case ID_LT:
+               *ofs= sizeof(float)*3;
+               *poinsize= *ofs;
+               break;
+       case ID_CU:
+               if(mode == KEY_MODE_BPOINT) {
+                       *ofs= sizeof(float)*4;
+                       *poinsize= *ofs;
+               } else {
+                       ofs[0]= sizeof(float)*12;
+                       *poinsize= (*ofs) / 3;
+               }
+
+               break;
+       default:
+               BLI_assert(!"invalid 'key->from' ID type");
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static void cp_key(const int start, int end, const int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock *kb, float *weights, const int mode)
 {
        float ktot = 0.0, kd = 0.0;
        int elemsize, poinsize = 0, a, *ofsp, ofs[32], flagflo=0;
        char *k1, *kref, *freek1, *freekref;
        char *cp, elemstr[8];
 
-       if(key->from==NULL) return;
+       /* currently always 0, in future key_pointer_size may assign */
+       ofs[1]= 0;
 
-       if( GS(key->from->name)==ID_ME ) {
-               ofs[0]= sizeof(float)*3;
-               ofs[1]= 0;
-               poinsize= ofs[0];
-       }
-       else if( GS(key->from->name)==ID_LT ) {
-               ofs[0]= sizeof(float)*3;
-               ofs[1]= 0;
-               poinsize= ofs[0];
-       }
-       else if( GS(key->from->name)==ID_CU ) {
-               if(mode==KEY_BPOINT) ofs[0]= sizeof(float)*4;
-               else ofs[0]= sizeof(float)*10;
-               
-               ofs[1]= 0;
-               poinsize= ofs[0];
-       }
+       if(!key_pointer_size(key, mode, &poinsize, &ofs[0]))
+               return;
 
        if(end>tot) end= tot;
        
@@ -585,7 +600,7 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                else k1+= start*key->elemsize;
        }       
        
-       if(mode==KEY_BEZTRIPLE) {
+       if(mode == KEY_MODE_BEZTRIPLE) {
                elemstr[0]= 1;
                elemstr[1]= IPO_BEZTRIPLE;
                elemstr[2]= 0;
@@ -593,11 +608,11 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
        
        /* just do it here, not above! */
        elemsize= key->elemsize;
-       if(mode==KEY_BEZTRIPLE) elemsize*= 3;
+       if(mode == KEY_MODE_BEZTRIPLE) elemsize*= 3;
 
        for(a=start; a<end; a++) {
                cp= key->elemstr;
-               if(mode==KEY_BEZTRIPLE) cp= elemstr;
+               if(mode == KEY_MODE_BEZTRIPLE) cp= elemstr;
 
                ofsp= ofs;
                
@@ -618,10 +633,16 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                                memcpy(poin, k1, sizeof(float)*4);
                                break;
                        case IPO_BEZTRIPLE:
-                               memcpy(poin, k1, sizeof(float)*10);
+                               memcpy(poin, k1, sizeof(float)*12);
                                break;
+                       default:
+                               /* should never happen */
+                               if(freek1) MEM_freeN(freek1);
+                               if(freekref) MEM_freeN(freekref);
+                               BLI_assert(!"invalid 'cp[1]'");
+                               return;
                        }
-                       
+
                        poin+= ofsp[0]; 
                        cp+= 2; ofsp++;
                }
@@ -629,8 +650,8 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                /* are we going to be nasty? */
                if(flagflo) {
                        ktot+= kd;
-                       while(ktot>=1.0) {
-                               ktot-= 1.0;
+                       while(ktot >= 1.0f) {
+                               ktot -= 1.0f;
                                k1+= elemsize;
                                kref+= elemsize;
                        }
@@ -640,71 +661,57 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                        kref+= elemsize;
                }
                
-               if(mode==KEY_BEZTRIPLE) a+=2;
+               if(mode == KEY_MODE_BEZTRIPLE) a+=2;
        }
 
        if(freek1) MEM_freeN(freek1);
        if(freekref) MEM_freeN(freekref);
 }
 
-static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, int start, int end, char *out, int tot)
+static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const int start, int end, char *out, const int tot)
 {
        Nurb *nu;
-       char *poin;
        int a, step, a1, a2;
 
        for(a=0, nu=cu->nurb.first; nu; nu=nu->next, a+=step) {
                if(nu->bp) {
                        step= nu->pntsu*nu->pntsv;
-                       
-                       /* exception because keys prefer to work with complete blocks */
-                       poin= out - a*sizeof(float)*4;
+
                        a1= MAX2(a, start);
                        a2= MIN2(a+step, end);
-                       
-                       if(a1<a2) cp_key(a1, a2, tot, poin, key, actkb, kb, NULL, KEY_BPOINT);
+
+                       if(a1<a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BPOINT);
                }
                else if(nu->bezt) {
                        step= 3*nu->pntsu;
-                       
-                       poin= out - a*sizeof(float)*10;
+
+                       /* exception because keys prefer to work with complete blocks */
                        a1= MAX2(a, start);
                        a2= MIN2(a+step, end);
 
-                       if(a1<a2) cp_key(a1, a2, tot, poin, key, actkb, kb, NULL, KEY_BEZTRIPLE);
+                       if(a1<a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_MODE_BEZTRIPLE);
                }
                else
                        step= 0;
        }
 }
 
-
-void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock *actkb, int mode)
+void do_rel_key(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb, const int mode)
 {
        KeyBlock *kb;
        int *ofsp, ofs[3], elemsize, b;
        char *cp, *poin, *reffrom, *from, elemstr[8];
        char *freefrom, *freereffrom;
-       
-       if(key->from==NULL) return;
-       
-       if( GS(key->from->name)==ID_ME ) {
-               ofs[0]= sizeof(float)*3;
-               ofs[1]= 0;
-       }
-       else if( GS(key->from->name)==ID_LT ) {
-               ofs[0]= sizeof(float)*3;
-               ofs[1]= 0;
-       }
-       else if( GS(key->from->name)==ID_CU ) {
-               if(mode==KEY_BPOINT) ofs[0]= sizeof(float)*4;
-               else ofs[0]= sizeof(float)*10;
-               
-               ofs[1]= 0;
-       }
-       
+       int poinsize;
+
+       /* currently always 0, in future key_pointer_size may assign */
+       ofs[1]= 0;
+
+       if(!key_pointer_size(key, mode, &poinsize, &ofs[0]))
+               return;
+
        if(end>tot) end= tot;
-       
+
        /* in case of beztriple */
        elemstr[0]= 1;                          /* nr of ipofloats */
        elemstr[1]= IPO_BEZTRIPLE;
@@ -712,7 +719,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock
 
        /* just here, not above! */
        elemsize= key->elemsize;
-       if(mode==KEY_BEZTRIPLE) elemsize*= 3;
+       if(mode == KEY_MODE_BEZTRIPLE) elemsize*= 3;
 
        /* step 1 init */
        cp_key(start, end, tot, basispoin, key, actkb, key->refkey, NULL, mode);
@@ -736,7 +743,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock
                                from= key_block_get_data(key, actkb, kb, &freefrom);
                                reffrom= key_block_get_data(key, actkb, refb, &freereffrom);
                                
-                               poin+= start*ofs[0];
+                               poin+= start*poinsize;
                                reffrom+= key->elemsize*start;  // key elemsize yes!
                                from+= key->elemsize*start;
                                
@@ -748,7 +755,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock
                                                weight= icuval;
                                        
                                        cp= key->elemstr;       
-                                       if(mode==KEY_BEZTRIPLE) cp= elemstr;
+                                       if(mode == KEY_MODE_BEZTRIPLE) cp= elemstr;
                                        
                                        ofsp= ofs;
                                        
@@ -762,10 +769,16 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock
                                                        rel_flerp(4, (float *)poin, (float *)reffrom, (float *)from, weight);
                                                        break;
                                                case IPO_BEZTRIPLE:
-                                                       rel_flerp(10, (float *)poin, (float *)reffrom, (float *)from, weight);
+                                                       rel_flerp(12, (float *)poin, (float *)reffrom, (float *)from, weight);
                                                        break;
+                                               default:
+                                                       /* should never happen */
+                                                       if(freefrom) MEM_freeN(freefrom);
+                                                       if(freereffrom) MEM_freeN(freereffrom);
+                                                       BLI_assert(!"invalid 'cp[1]'");
+                                                       return;
                                                }
-                                               
+
                                                poin+= ofsp[0];                         
                                                
                                                cp+= 2;
@@ -775,7 +788,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock
                                        reffrom+= elemsize;
                                        from+= elemsize;
                                        
-                                       if(mode==KEY_BEZTRIPLE) b+= 2;
+                                       if(mode == KEY_MODE_BEZTRIPLE) b+= 2;
                                        if(weights) weights++;
                                }
 
@@ -787,7 +800,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock
 }
 
 
-static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, int mode)
+static void do_key(const int start, int end, const int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, const int mode)
 {
        float k1tot = 0.0, k2tot = 0.0, k3tot = 0.0, k4tot = 0.0;
        float k1d = 0.0, k2d = 0.0, k3d = 0.0, k4d = 0.0;
@@ -796,25 +809,11 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
        char *k1, *k2, *k3, *k4, *freek1, *freek2, *freek3, *freek4;
        char *cp, elemstr[8];;
 
-       if(key->from==0) return;
+       /* currently always 0, in future key_pointer_size may assign */
+       ofs[1]= 0;
 
-       if( GS(key->from->name)==ID_ME ) {
-               ofs[0]= sizeof(float)*3;
-               ofs[1]= 0;
-               poinsize= ofs[0];
-       }
-       else if( GS(key->from->name)==ID_LT ) {
-               ofs[0]= sizeof(float)*3;
-               ofs[1]= 0;
-               poinsize= ofs[0];
-       }
-       else if( GS(key->from->name)==ID_CU ) {
-               if(mode==KEY_BPOINT) ofs[0]= sizeof(float)*4;
-               else ofs[0]= sizeof(float)*10;
-               
-               ofs[1]= 0;
-               poinsize= ofs[0];
-       }
+       if(!key_pointer_size(key, mode, &poinsize, &ofs[0]))
+               return;
        
        if(end>tot) end= tot;
 
@@ -916,12 +915,12 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
 
        /* only here, not above! */
        elemsize= key->elemsize;
-       if(mode==KEY_BEZTRIPLE) elemsize*= 3;
+       if(mode == KEY_MODE_BEZTRIPLE) elemsize*= 3;
 
        for(a=start; a<end; a++) {
        
                cp= key->elemstr;       
-               if(mode==KEY_BEZTRIPLE) cp= elemstr;
+               if(mode == KEY_MODE_BEZTRIPLE) cp= elemstr;
                
                ofsp= ofs;
                
@@ -935,8 +934,16 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                                flerp(4, (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
                                break;
                        case IPO_BEZTRIPLE:
-                               flerp(10, (void *)poin, (void *)k1, (void *)k2, (void *)k3, (void *)k4, t);
+                               flerp(12, (void *)poin, (void *)k1, (void *)k2, (void *)k3, (void *)k4, t);
                                break;
+                       default:
+                               /* should never happen */
+                               if(freek1) MEM_freeN(freek1);
+                               if(freek2) MEM_freeN(freek2);
+                               if(freek3) MEM_freeN(freek3);
+                               if(freek4) MEM_freeN(freek4);
+                               BLI_assert(!"invalid 'cp[1]'");
+                               return;
                        }
                        
                        poin+= ofsp[0];                         
@@ -947,8 +954,8 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                if(flagdo & 1) {
                        if(flagflo & 1) {
                                k1tot+= k1d;
-                               while(k1tot>=1.0) {
-                                       k1tot-= 1.0;
+                               while(k1tot >= 1.0f) {
+                                       k1tot -= 1.0f;
                                        k1+= elemsize;
                                }
                        }
@@ -957,8 +964,8 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                if(flagdo & 2) {
                        if(flagflo & 2) {
                                k2tot+= k2d;
-                               while(k2tot>=1.0) {
-                                       k2tot-= 1.0;
+                               while(k2tot >= 1.0f) {
+                                       k2tot -= 1.0f;
                                        k2+= elemsize;
                                }
                        }
@@ -967,8 +974,8 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                if(flagdo & 4) {
                        if(flagflo & 4) {
                                k3tot+= k3d;
-                               while(k3tot>=1.0) {
-                                       k3tot-= 1.0;
+                               while(k3tot >= 1.0f) {
+                                       k3tot -= 1.0f;
                                        k3+= elemsize;
                                }
                        }
@@ -977,15 +984,15 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                if(flagdo & 8) {
                        if(flagflo & 8) {
                                k4tot+= k4d;
-                               while(k4tot>=1.0) {
-                                       k4tot-= 1.0;
+                               while(k4tot >= 1.0f) {
+                                       k4tot -= 1.0f;
                                        k4+= elemsize;
                                }
                        }
                        else k4+= elemsize;
                }
                
-               if(mode==KEY_BEZTRIPLE) a+= 2;
+               if(mode == KEY_MODE_BEZTRIPLE) a+= 2;
        }
 
        if(freek1) MEM_freeN(freek1);
@@ -996,9 +1003,10 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
 
 static float *get_weights_array(Object *ob, char *vgroup)
 {
-       bDeformGroup *curdef;
        MDeformVert *dvert= NULL;
-       int totvert= 0, index= 0;
+       EditMesh *em= NULL;
+       EditVert *eve;
+       int totvert= 0, defgrp_index= 0;
        
        /* no vgroup string set? */
        if(vgroup[0]==0) return NULL;
@@ -1008,6 +1016,9 @@ static float *get_weights_array(Object *ob, char *vgroup)
                Mesh *me= ob->data;
                dvert= me->dvert;
                totvert= me->totvert;
+
+               if(me->edit_mesh && me->edit_mesh->totvert == totvert)
+                       em= me->edit_mesh;
        }
        else if(ob->type==OB_LATTICE) {
                Lattice *lt= ob->data;
@@ -1018,30 +1029,34 @@ static float *get_weights_array(Object *ob, char *vgroup)
        if(dvert==NULL) return NULL;
        
        /* find the group (weak loop-in-loop) */
-       for (curdef = ob->defbase.first; curdef; curdef=curdef->next, index++)
-               if (!strcmp(curdef->name, vgroup))
-                       break;
-
-       if(curdef) {
+       defgrp_index= defgroup_name_index(ob, vgroup);
+       if(defgrp_index >= 0) {
                float *weights;
-               int i, j;
+               int i;
                
                weights= MEM_callocN(totvert*sizeof(float), "weights");
-               
-               for (i=0; i < totvert; i++, dvert++) {
-                       for(j=0; j<dvert->totweight; j++) {
-                               if (dvert->dw[j].def_nr == index) {
-                                       weights[i]= dvert->dw[j].weight;
-                                       break;
+
+               if(em) {
+                       for(i=0, eve=em->verts.first; eve; eve=eve->next, i++) {
+                               dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
+
+                               if(dvert) {
+                                       weights[i]= defvert_find_weight(dvert, defgrp_index);
                                }
                        }
                }
+               else {
+                       for(i=0; i < totvert; i++, dvert++) {
+                               weights[i]= defvert_find_weight(dvert, defgrp_index);
+                       }
+               }
+
                return weights;
        }
        return NULL;
 }
 
-static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
+static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
 {
        KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
        float cfra, ctime, t[4], delta;
@@ -1062,7 +1077,7 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
                
                for(a=0; a<tot; a+=step, cfra+= delta) {
                        
-                       ctime= bsystem_time(scene, 0, cfra, 0.0); // xxx  ugly cruft!
+                       ctime= bsystem_time(scene, NULL, cfra, 0.0); // xxx  ugly cruft!
 #if 0 // XXX old animation system
                        if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
                                ctime /= 100.0;
@@ -1076,9 +1091,9 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
                        flag= setkeys(ctime, &key->block, k, t, 0);
 
                        if(flag==0)
-                               do_key(a, a+step, tot, (char *)out, key, actkb, k, t, 0);
+                               do_key(a, a+step, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
                        else
-                               cp_key(a, a+step, tot, (char *)out, key, actkb, k[2], NULL, 0);
+                               cp_key(a, a+step, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
                }
        }
        else {
@@ -1088,7 +1103,7 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
                        for(kb= key->block.first; kb; kb= kb->next)
                                kb->weights= get_weights_array(ob, kb->vgroup);
 
-                       do_rel_key(0, tot, tot, (char *)out, key, actkb, 0);
+                       do_rel_key(0, tot, tot, (char *)out, key, actkb, KEY_MODE_DUMMY);
                        
                        for(kb= key->block.first; kb; kb= kb->next) {
                                if(kb->weights) MEM_freeN(kb->weights);
@@ -1111,92 +1126,112 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
                        flag= setkeys(ctime, &key->block, k, t, 0);
 
                        if(flag==0)
-                               do_key(0, tot, tot, (char *)out, key, actkb, k, t, 0);
+                               do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
                        else
-                               cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, 0);
+                               cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
                }
        }
 }
 
-static void do_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, char *out, int tot)
+static void do_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, char *out, const int tot)
 {
        Nurb *nu;
-       char *poin;
        int a, step;
        
        for(a=0, nu=cu->nurb.first; nu; nu=nu->next, a+=step) {
                if(nu->bp) {
                        step= nu->pntsu*nu->pntsv;
-                       poin= out - a*sizeof(float)*4;
-                       do_key(a, a+step, tot, poin, key, actkb, k, t, KEY_BPOINT);
+                       do_key(a, a+step, tot, out, key, actkb, k, t, KEY_MODE_BPOINT);
                }
                else if(nu->bezt) {
                        step= 3*nu->pntsu;
-                       poin= out - a*sizeof(float)*10;
-                       do_key(a, a+step, tot, poin, key, actkb, k, t, KEY_BEZTRIPLE);
+                       do_key(a, a+step, tot, out, key, actkb, k, t, KEY_MODE_BEZTRIPLE);
                }
                else
                        step= 0;
        }
 }
 
-static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, float ctime, char *out, int tot)
+static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, float UNUSED(ctime), char *out, const int tot)
 {
        Nurb *nu;
-       char *poin;
        int a, step;
        
        for(a=0, nu=cu->nurb.first; nu; nu=nu->next, a+=step) {
                if(nu->bp) {
                        step= nu->pntsu*nu->pntsv;
-                       poin= out - a*sizeof(float)*3;
-                       do_rel_key(a, a+step, tot, out, key, actkb, KEY_BPOINT);
+                       do_rel_key(a, a+step, tot, out, key, actkb, KEY_MODE_BPOINT);
                }
                else if(nu->bezt) {
                        step= 3*nu->pntsu;
-                       poin= out - a*sizeof(float)*10;
-                       do_rel_key(a, a+step, tot, poin, key, actkb, KEY_BEZTRIPLE);
+                       do_rel_key(a, a+step, tot, out, key, actkb, KEY_MODE_BEZTRIPLE);
                }
                else
                        step= 0;
        }
 }
 
-static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
+static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
 {
        Curve *cu= ob->data;
        KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
        float cfra, ctime, t[4], delta;
        int a, flag = 0, step = 0;
-       
-       if(key->slurph) {
-               delta= key->slurph;
-               delta/= tot;
-               
+
+       if(key->slurph  && key->type!=KEY_RELATIVE) {
+               Nurb *nu;
+               int mode=0, i= 0, remain= 0, estep=0, count=0;
+
+               delta= (float)key->slurph / tot;
+
                step= 1;
                if(tot>100 && slurph_opt) {
                        step= tot/50;
                        delta*= step;
                        /* in do_key and cp_key the case a>tot has been handled */
                }
-               
+
                cfra= (float)scene->r.cfra;
-               
-               for(a=0; a<tot; a+=step, cfra+= delta) {
-                       ctime= bsystem_time(scene, 0, cfra, 0.0f); // XXX old cruft
-#if 0 // XXX old animation system
-                       if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
-                               ctime /= 100.0;
-                               CLAMP(ctime, 0.0, 1.0);
+
+               for(nu=cu->nurb.first; nu; nu=nu->next) {
+                       if(nu->bp) {
+                               mode= KEY_MODE_BPOINT;
+                               estep= nu->pntsu*nu->pntsv;
+                       }
+                       else if(nu->bezt) {
+                               mode= KEY_MODE_BEZTRIPLE;
+                               estep= 3*nu->pntsu;
                        }
-#endif // XXX old animation system
-               
-                       flag= setkeys(ctime, &key->block, k, t, 0);
-                       
-                       if(flag==0)
-                               do_key(a, a+step, tot, (char *)out, key, actkb, k, t, 0);
                        else
-                               cp_key(a, a+step, tot, (char *)out, key, actkb, k[2], NULL, 0);
+                               step= 0;
+
+                       a= 0;
+                       while (a < estep) {
+                               if (remain <= 0) {
+                                       cfra+= delta;
+                                       ctime= bsystem_time(scene, NULL, cfra, 0.0f); // XXX old cruft
+
+                                       ctime /= 100.0f;
+                                       CLAMP(ctime, 0.0f, 1.0f); // XXX for compat, we use this, but this clamping was confusing
+                                       flag= setkeys(ctime, &key->block, k, t, 0);
+
+                                       remain= step;
+                               }
+
+                               count= MIN2(remain, estep);
+                               if (mode == KEY_MODE_BEZTRIPLE) {
+                                       count += 3 - count % 3;
+                               }
+
+                               if(flag==0)
+                                       do_key(i, i+count, tot, (char *)out, key, actkb, k, t, mode);
+                               else
+                                       cp_key(i, i+count, tot, (char *)out, key, actkb, k[2], NULL, mode);
+
+                               a += count;
+                               i += count;
+                               remain -= count;
+                       }
                }
        }
        else {
@@ -1222,7 +1257,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
        }
 }
 
-static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
+static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int tot)
 {
        Lattice *lt= ob->data;
        KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
@@ -1237,7 +1272,7 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
                
                for(a=0; a<tot; a++, cfra+= delta) {
                        
-                       ctime= bsystem_time(scene, 0, cfra, 0.0); // XXX old cruft
+                       ctime= bsystem_time(scene, NULL, cfra, 0.0); // XXX old cruft
 #if 0 // XXX old animation system
                        if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
                                ctime /= 100.0;
@@ -1248,9 +1283,9 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
                        flag= setkeys(ctime, &key->block, k, t, 0);
 
                        if(flag==0)
-                               do_key(a, a+1, tot, (char *)out, key, actkb, k, t, 0);
+                               do_key(a, a+1, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
                        else
-                               cp_key(a, a+1, tot, (char *)out, key, actkb, k[2], NULL, 0);
+                               cp_key(a, a+1, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
                }               
        }
        else {
@@ -1260,7 +1295,7 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
                        for(kb= key->block.first; kb; kb= kb->next)
                                kb->weights= get_weights_array(ob, kb->vgroup);
                        
-                       do_rel_key(0, tot, tot, (char *)out, key, actkb, 0);
+                       do_rel_key(0, tot, tot, (char *)out, key, actkb, KEY_MODE_DUMMY);
                        
                        for(kb= key->block.first; kb; kb= kb->next) {
                                if(kb->weights) MEM_freeN(kb->weights);
@@ -1280,9 +1315,9 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
                        flag= setkeys(ctime, &key->block, k, t, 0);
 
                        if(flag==0)
-                               do_key(0, tot, tot, (char *)out, key, actkb, k, t, 0);
+                               do_key(0, tot, tot, (char *)out, key, actkb, k, t, KEY_MODE_DUMMY);
                        else
-                               cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, 0);
+                               cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, KEY_MODE_DUMMY);
                }
        }
        
@@ -1320,11 +1355,11 @@ float *do_ob_key(Scene *scene, Object *ob)
                for(nu=cu->nurb.first; nu; nu=nu->next) {
                        if(nu->bezt) {
                                tot += 3*nu->pntsu;
-                               size += nu->pntsu*10*sizeof(float);
+                               size += nu->pntsu*12*sizeof(float);
                        }
                        else if(nu->bp) {
                                tot += nu->pntsu*nu->pntsv;
-                               size += nu->pntsu*nu->pntsv*10*sizeof(float);
+                               size += nu->pntsu*nu->pntsv*12*sizeof(float);
                        }
                }
        }
@@ -1365,7 +1400,7 @@ float *do_ob_key(Scene *scene, Object *ob)
                /* do shapekey local drivers */
                float ctime= (float)scene->r.cfra; // XXX this needs to be checked
                
-               BKE_animsys_evaluate_animdata(&key->id, key->adt, ctime, ADT_RECALC_DRIVERS);
+               BKE_animsys_evaluate_animdata(scene, &key->id, key->adt, ctime, ADT_RECALC_DRIVERS);
                
                if(ob->type==OB_MESH) do_mesh_key(scene, ob, key, out, tot);
                else if(ob->type==OB_LATTICE) do_latt_key(scene, ob, key, out, tot);
@@ -1395,6 +1430,55 @@ Key *ob_get_key(Object *ob)
        return NULL;
 }
 
+KeyBlock *add_keyblock(Key *key, const char *name)
+{
+       KeyBlock *kb;
+       float curpos= -0.1;
+       int tot;
+       
+       kb= key->block.last;
+       if(kb) curpos= kb->pos;
+       
+       kb= MEM_callocN(sizeof(KeyBlock), "Keyblock");
+       BLI_addtail(&key->block, kb);
+       kb->type= KEY_CARDINAL;
+       
+       tot= BLI_countlist(&key->block);
+       if(name) {
+               strncpy(kb->name, name, sizeof(kb->name));
+       } else {
+               if(tot==1) strcpy(kb->name, "Basis");
+               else sprintf(kb->name, "Key %d", tot-1);
+       }
+
+       BLI_uniquename(&key->block, kb, "Key", '.', offsetof(KeyBlock, name), sizeof(kb->name));
+
+       // XXX this is old anim system stuff? (i.e. the 'index' of the shapekey)
+       kb->adrcode= tot-1;
+       
+       key->totkey++;
+       if(key->totkey==1) key->refkey= kb;
+       
+       kb->slidermin= 0.0f;
+       kb->slidermax= 1.0f;
+       
+       // XXX kb->pos is the confusing old horizontal-line RVK crap in old IPO Editor...
+       if(key->type == KEY_RELATIVE) 
+               kb->pos= curpos + 0.1f;
+       else {
+#if 0 // XXX old animation system
+               curpos= bsystem_time(scene, 0, (float)CFRA, 0.0);
+               if(calc_ipo_spec(key->ipo, KEY_SPEED, &curpos)==0) {
+                       curpos /= 100.0;
+               }
+               kb->pos= curpos;
+               
+               sort_keys(key);
+#endif // XXX old animation system
+       }
+       return kb;
+}
+
 /* only the active keyblock */
 KeyBlock *ob_get_keyblock(Object *ob) 
 {
@@ -1441,14 +1525,8 @@ KeyBlock *key_get_keyblock(Key *key, int index)
 /* get the appropriate KeyBlock given a name to search for */
 KeyBlock *key_get_named_keyblock(Key *key, const char name[])
 {
-       KeyBlock *kb;
-       
-       if (key && name) {
-               for (kb= key->block.first; kb; kb= kb->next) {
-                       if (strcmp(name, kb->name)==0)
-                               return kb;
-               }
-       }
+       if (key && name)
+               return BLI_findstring(&key->block, name, offsetof(KeyBlock, name));
        
        return NULL;
 }
@@ -1473,3 +1551,387 @@ char *key_get_curValue_rnaPath(Key *key, KeyBlock *kb)
        /* return the path */
        return RNA_path_from_ID_to_property(&ptr, prop);
 }
+
+
+/* conversion functions */
+
+/************************* Lattice ************************/
+void latt_to_key(Lattice *lt, KeyBlock *kb)
+{
+       BPoint *bp;
+       float *fp;
+       int a, tot;
+
+       tot= lt->pntsu*lt->pntsv*lt->pntsw;
+       if(tot==0) return;
+
+       if(kb->data) MEM_freeN(kb->data);
+
+       kb->data= MEM_callocN(lt->key->elemsize*tot, "kb->data");
+       kb->totelem= tot;
+
+       bp= lt->def;
+       fp= kb->data;
+       for(a=0; a<kb->totelem; a++, fp+=3, bp++) {
+               VECCOPY(fp, bp->vec);
+       }
+}
+
+void key_to_latt(KeyBlock *kb, Lattice *lt)
+{
+       BPoint *bp;
+       float *fp;
+       int a, tot;
+
+       bp= lt->def;
+       fp= kb->data;
+
+       tot= lt->pntsu*lt->pntsv*lt->pntsw;
+       tot= MIN2(kb->totelem, tot);
+
+       for(a=0; a<tot; a++, fp+=3, bp++) {
+               VECCOPY(bp->vec, fp);
+       }
+}
+
+/************************* Curve ************************/
+void curve_to_key(Curve *cu, KeyBlock *kb, ListBase *nurb)
+{
+       Nurb *nu;
+       BezTriple *bezt;
+       BPoint *bp;
+       float *fp;
+       int a, tot;
+
+       /* count */
+       tot= count_curveverts(nurb);
+       if(tot==0) return;
+
+       if(kb->data) MEM_freeN(kb->data);
+
+       kb->data= MEM_callocN(cu->key->elemsize*tot, "kb->data");
+       kb->totelem= tot;
+
+       nu= nurb->first;
+       fp= kb->data;
+       while(nu) {
+
+               if(nu->bezt) {
+                       bezt= nu->bezt;
+                       a= nu->pntsu;
+                       while(a--) {
+                               VECCOPY(fp, bezt->vec[0]);
+                               fp+= 3;
+                               VECCOPY(fp, bezt->vec[1]);
+                               fp+= 3;
+                               VECCOPY(fp, bezt->vec[2]);
+                               fp+= 3;
+                               fp[0]= bezt->alfa;
+                               fp+= 3; /* alphas */
+                               bezt++;
+                       }
+               }
+               else {
+                       bp= nu->bp;
+                       a= nu->pntsu*nu->pntsv;
+                       while(a--) {
+                               VECCOPY(fp, bp->vec);
+                               fp[3]= bp->alfa;
+
+                               fp+= 4;
+                               bp++;
+                       }
+               }
+               nu= nu->next;
+       }
+}
+
+void key_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb)
+{
+       Nurb *nu;
+       BezTriple *bezt;
+       BPoint *bp;
+       float *fp;
+       int a, tot;
+
+       nu= nurb->first;
+       fp= kb->data;
+
+       tot= count_curveverts(nurb);
+
+       tot= MIN2(kb->totelem, tot);
+
+       while(nu && tot>0) {
+
+               if(nu->bezt) {
+                       bezt= nu->bezt;
+                       a= nu->pntsu;
+                       while(a-- && tot>0) {
+                               VECCOPY(bezt->vec[0], fp);
+                               fp+= 3;
+                               VECCOPY(bezt->vec[1], fp);
+                               fp+= 3;
+                               VECCOPY(bezt->vec[2], fp);
+                               fp+= 3;
+                               bezt->alfa= fp[0];
+                               fp+= 3; /* alphas */
+
+                               tot-= 3;
+                               bezt++;
+                       }
+               }
+               else {
+                       bp= nu->bp;
+                       a= nu->pntsu*nu->pntsv;
+                       while(a-- && tot>0) {
+                               VECCOPY(bp->vec, fp);
+                               bp->alfa= fp[3];
+
+                               fp+= 4;
+                               tot--;
+                               bp++;
+                       }
+               }
+               nu= nu->next;
+       }
+}
+
+/************************* Mesh ************************/
+void mesh_to_key(Mesh *me, KeyBlock *kb)
+{
+       MVert *mvert;
+       float *fp;
+       int a;
+
+       if(me->totvert==0) return;
+
+       if(kb->data) MEM_freeN(kb->data);
+
+       kb->data= MEM_callocN(me->key->elemsize*me->totvert, "kb->data");
+       kb->totelem= me->totvert;
+
+       mvert= me->mvert;
+       fp= kb->data;
+       for(a=0; a<kb->totelem; a++, fp+=3, mvert++) {
+               VECCOPY(fp, mvert->co);
+
+       }
+}
+
+void key_to_mesh(KeyBlock *kb, Mesh *me)
+{
+       MVert *mvert;
+       float *fp;
+       int a, tot;
+
+       mvert= me->mvert;
+       fp= kb->data;
+
+       tot= MIN2(kb->totelem, me->totvert);
+
+       for(a=0; a<tot; a++, fp+=3, mvert++) {
+               VECCOPY(mvert->co, fp);
+       }
+}
+
+/************************* vert coords ************************/
+float (*key_to_vertcos(Object *ob, KeyBlock *kb))[3]
+{
+       float (*vertCos)[3], *co;
+       float *fp= kb->data;
+       int tot= 0, a;
+
+       /* Count of vertex coords in array */
+       if(ob->type == OB_MESH) {
+               Mesh *me= (Mesh*)ob->data;
+               tot= me->totvert;
+       } else if(ob->type == OB_LATTICE) {
+               Lattice *lt= (Lattice*)ob->data;
+               tot= lt->pntsu*lt->pntsv*lt->pntsw;
+       } else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
+               Curve *cu= (Curve*)ob->data;
+               tot= count_curveverts(&cu->nurb);
+       }
+
+       if (tot == 0) return NULL;
+
+       vertCos= MEM_callocN(tot*sizeof(*vertCos), "key_to_vertcos vertCos");
+
+       /* Copy coords to array */
+       co= (float*)vertCos;
+
+       if(ELEM(ob->type, OB_MESH, OB_LATTICE)) {
+               for (a= 0; a<tot; a++, fp+=3, co+=3) {
+                       copy_v3_v3(co, fp);
+               }
+       } else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
+               Curve *cu= (Curve*)ob->data;
+               Nurb *nu= cu->nurb.first;
+               BezTriple *bezt;
+               BPoint *bp;
+
+               while (nu) {
+                       if(nu->bezt) {
+                               int i;
+                               bezt= nu->bezt;
+                               a= nu->pntsu;
+
+                               while (a--) {
+                                       for (i= 0; i<3; i++) {
+                                               copy_v3_v3(co, fp);
+                                               fp+= 3; co+= 3;
+                                       }
+
+                                       fp+= 3; /* skip alphas */
+
+                                       bezt++;
+                               }
+                       }
+                       else {
+                               bp= nu->bp;
+                               a= nu->pntsu*nu->pntsv;
+
+                               while (a--) {
+                                       copy_v3_v3(co, fp);
+
+                                       fp+= 4;
+                                       co+= 3;
+
+                                       bp++;
+                               }
+                       }
+
+                       nu= nu->next;
+               }
+       }
+
+       return vertCos;
+}
+
+void vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
+{
+       float *co= (float*)vertCos, *fp;
+       int tot= 0, a, elemsize;
+
+       if (kb->data) MEM_freeN(kb->data);
+
+       /* Count of vertex coords in array */
+       if(ob->type == OB_MESH) {
+               Mesh *me= (Mesh*)ob->data;
+               tot= me->totvert;
+               elemsize= me->key->elemsize;
+       } else if(ob->type == OB_LATTICE) {
+               Lattice *lt= (Lattice*)ob->data;
+               tot= lt->pntsu*lt->pntsv*lt->pntsw;
+               elemsize= lt->key->elemsize;
+       } else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
+               Curve *cu= (Curve*)ob->data;
+               elemsize= cu->key->elemsize;
+               tot= count_curveverts(&cu->nurb);
+       }
+
+       if (tot == 0) {
+               kb->data= NULL;
+               return;
+       }
+
+       fp= kb->data= MEM_callocN(tot*elemsize, "key_to_vertcos vertCos");
+
+       /* Copy coords to keyblock */
+
+       if(ELEM(ob->type, OB_MESH, OB_LATTICE)) {
+               for (a= 0; a<tot; a++, fp+=3, co+=3) {
+                       copy_v3_v3(fp, co);
+               }
+       } else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
+               Curve *cu= (Curve*)ob->data;
+               Nurb *nu= cu->nurb.first;
+               BezTriple *bezt;
+               BPoint *bp;
+
+               while (nu) {
+                       if(nu->bezt) {
+                               int i;
+                               bezt= nu->bezt;
+                               a= nu->pntsu;
+
+                               while (a--) {
+                                       for (i= 0; i<3; i++) {
+                                               copy_v3_v3(fp, co);
+                                               fp+= 3; co+= 3;
+                                       }
+
+                                       fp+= 3; /* skip alphas */
+
+                                       bezt++;
+                               }
+                       }
+                       else {
+                               bp= nu->bp;
+                               a= nu->pntsu*nu->pntsv;
+
+                               while (a--) {
+                                       copy_v3_v3(fp, co);
+
+                                       fp+= 4;
+                                       co+= 3;
+
+                                       bp++;
+                               }
+                       }
+
+                       nu= nu->next;
+               }
+       }
+}
+
+void offset_to_key(Object *ob, KeyBlock *kb, float (*ofs)[3])
+{
+       int a;
+       float *co= (float*)ofs, *fp= kb->data;
+
+       if(ELEM(ob->type, OB_MESH, OB_LATTICE)) {
+               for (a= 0; a<kb->totelem; a++, fp+=3, co+=3) {
+                       add_v3_v3(fp, co);
+               }
+       } else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
+               Curve *cu= (Curve*)ob->data;
+               Nurb *nu= cu->nurb.first;
+               BezTriple *bezt;
+               BPoint *bp;
+
+               while (nu) {
+                       if(nu->bezt) {
+                               int i;
+                               bezt= nu->bezt;
+                               a= nu->pntsu;
+
+                               while (a--) {
+                                       for (i= 0; i<3; i++) {
+                                               add_v3_v3(fp, co);
+                                               fp+= 3; co+= 3;
+                                       }
+
+                                       fp+= 3; /* skip alphas */
+
+                                       bezt++;
+                               }
+                       }
+                       else {
+                               bp= nu->bp;
+                               a= nu->pntsu*nu->pntsv;
+
+                               while (a--) {
+                                       add_v3_v3(fp, co);
+
+                                       fp+= 4;
+                                       co+= 3;
+
+                                       bp++;
+                               }
+                       }
+
+                       nu= nu->next;
+               }
+       }
+}