bugfix [#21036] crash with glsl shading
[blender.git] / source / blender / blenkernel / intern / key.c
index 595ba37e09c1037d3b2d3a22299f9b14760ef9c1..1e1c945d386acfd9811fbbac7a0ec601bbba8ffa 100644 (file)
 
 #include <math.h>
 #include <string.h>
+#include <stddef.h>
 
 #include "MEM_guardedalloc.h"
 
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
 #include "DNA_anim_types.h"
 #include "DNA_curve_types.h"
 #include "DNA_key_types.h"
@@ -48,6 +52,7 @@
 #include "BKE_action.h"
 #include "BKE_blender.h"
 #include "BKE_curve.h"
+#include "BKE_customdata.h"
 #include "BKE_global.h"
 #include "BKE_key.h"
 #include "BKE_lattice.h"
@@ -57,7 +62,7 @@
 #include "BKE_object.h"
 #include "BKE_utildefines.h"
 
-#include "BLI_blenlib.h"
+#include "RNA_access.h"
 
 
 #ifdef HAVE_CONFIG_H
@@ -166,7 +171,7 @@ Key *copy_key(Key *key)
        while(kbn) {
                
                if(kbn->data) kbn->data= MEM_dupallocN(kbn->data);
-               if( kb==key->refkey ) keyn->refkey= kbn;
+               if(kb==key->refkey) keyn->refkey= kbn;
                
                kbn= kbn->next;
                kb= kb->next;
@@ -266,66 +271,91 @@ void sort_keys(Key *key)
 
 /**************** do the key ****************/
 
+void key_curve_position_weights(float t, float *data, int type)
+{
+       float t2, t3, fc;
+       
+       if(type==KEY_LINEAR) {
+               data[0]=                  0.0f;
+               data[1]= -t             + 1.0f;
+               data[2]= t;
+               data[3]=                  0.0f;
+       }
+       else if(type==KEY_CARDINAL) {
+               t2= t*t;
+               t3= t2*t;
+               fc= 0.71f;
+               
+               data[0]= -fc*t3                 + 2.0f*fc*t2            - fc*t;
+               data[1]= (2.0f-fc)*t3   + (fc-3.0f)*t2                                  + 1.0f;
+               data[2]= (fc-2.0f)*t3   + (3.0f-2.0f*fc)*t2     + fc*t;
+               data[3]= fc*t3                  - fc*t2;
+       }
+       else if(type==KEY_BSPLINE) {
+               t2= t*t;
+               t3= t2*t;
+
+               data[0]= -0.16666666f*t3        + 0.5f*t2       - 0.5f*t        + 0.16666666f;
+               data[1]= 0.5f*t3                        - t2                                    + 0.6666666f;
+               data[2]= -0.5f*t3                       + 0.5f*t2       + 0.5f*t        + 0.16666666f;
+               data[3]= 0.16666666f*t3;
+       }
+}
 
-void set_four_ipo(float d, float *data, int type)
+/* first derivative */
+void key_curve_tangent_weights(float t, float *data, int type)
 {
-       float d2, d3, fc;
+       float t2, fc;
        
        if(type==KEY_LINEAR) {
                data[0]= 0.0f;
-               data[1]= 1.0f-d;
-               data[2]= d;
+               data[1]= -1.0f;
+               data[2]= 1.0f;
                data[3]= 0.0f;
        }
-       else {
-               d2= d*d;
-               d3= d2*d;
+       else if(type==KEY_CARDINAL) {
+               t2= t*t;
+               fc= 0.71f;
                
-               if(type==KEY_CARDINAL) {
-
-                       fc= 0.71f;
-                       
-                       data[0]= -fc*d3         +2.0f*fc*d2             -fc*d;
-                       data[1]= (2.0f-fc)*d3   +(fc-3.0f)*d2                           +1.0f;
-                       data[2]= (fc-2.0f)*d3   +(3.0f-2.0f*fc)*d2 +fc*d;
-                       data[3]= fc*d3                  -fc*d2;
-               }
-               else if(type==KEY_BSPLINE) {
+               data[0]= -3.0f*fc*t2            +4.0f*fc*t                              - fc;
+               data[1]= 3.0f*(2.0f-fc)*t2      +2.0f*(fc-3.0f)*t;
+               data[2]= 3.0f*(fc-2.0f)*t2      +2.0f*(3.0f-2.0f*fc)*t  + fc;
+               data[3]= 3.0f*fc*t2                     -2.0f*fc*t;
+       }
+       else if(type==KEY_BSPLINE) {
+               t2= t*t;
 
-                       data[0]= -0.16666666f*d3        +0.5f*d2        -0.5f*d +0.16666666f;
-                       data[1]= 0.5f*d3                -d2                             +0.6666666f;
-                       data[2]= -0.5f*d3               +0.5f*d2        +0.5f*d +0.16666666f;
-                       data[3]= 0.16666666f*d3                 ;
-               }
+               data[0]= -0.5f*t2       + t                     - 0.5f;
+               data[1]= 1.5f*t2        - 2.0f*t;
+               data[2]= -1.5f*t2       + t                     + 0.5f;
+               data[3]= 0.5f*t2;
        }
 }
 
-void set_afgeleide_four_ipo(float d, float *data, int type)
+/* second derivative */
+void key_curve_normal_weights(float t, float *data, int type)
 {
-       float d2, fc;
+       float fc;
        
        if(type==KEY_LINEAR) {
-
+               data[0]= 0.0f;
+               data[1]= 0.0f;
+               data[2]= 0.0f;
+               data[3]= 0.0f;
        }
-       else {
-               d2= d*d;
+       else if(type==KEY_CARDINAL) {
+               fc= 0.71f;
                
-               if(type==KEY_CARDINAL) {
-
-                       fc= 0.71f;
-                       
-                       data[0]= -3.0f*fc*d2            +4.0f*fc*d              -fc;
-                       data[1]= 3.0f*(2.0f-fc)*d2      +2.0f*(fc-3.0f)*d;
-                       data[2]= 3.0f*(fc-2.0f)*d2      +2.0f*(3.0f-2.0f*fc)*d +fc;
-                       data[3]= 3.0f*fc*d2                     -2.0f*fc*d;
-               }
-               else if(type==KEY_BSPLINE) {
-
-                       data[0]= -0.16666666f*3.0f*d2   +d      -0.5f;
-                       data[1]= 1.5f*d2                -2.0f*d;
-                       data[2]= -1.5f*d2               +d      +0.5f;
-                       data[3]= 0.16666666f*3.0f*d2                    ;
-               }
+               data[0]= -6.0f*fc*t                     + 4.0f*fc;
+               data[1]= 6.0f*(2.0f-fc)*t       + 2.0f*(fc-3.0f);
+               data[2]= 6.0f*(fc-2.0f)*t       + 2.0f*(3.0f-2.0f*fc);
+               data[3]= 6.0f*fc*t                      - 2.0f*fc;
+       }
+       else if(type==KEY_BSPLINE) {
+               data[0]= -1.0f*t        + 1.0f;
+               data[1]= 3.0f*t         - 2.0f;
+               data[2]= -3.0f*t        + 1.0f;
+               data[3]= 1.0f*t;
        }
 }
 
@@ -436,10 +466,10 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl)
 
        /* interpolation */
        
-       set_four_ipo(d, t, k[1]->type);
+       key_curve_position_weights(d, t, k[1]->type);
 
        if(k[1]->type != k[2]->type) {
-               set_four_ipo(d, fval, k[2]->type);
+               key_curve_position_weights(d, fval, k[2]->type);
                
                temp= 1.0f-d;
                t[0]= temp*t[0]+ d*fval[0];
@@ -470,48 +500,77 @@ static void rel_flerp(int aantal, float *in, float *ref, float *out, float fac)
        }
 }
 
-static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *k, float *weights, int mode)
+static char *key_block_get_data(Key *key, KeyBlock *actkb, KeyBlock *kb, char **freedata)
+{
+       if(kb == actkb) {
+               /* this hack makes it possible to edit shape keys in
+                  edit mode with shape keys blending applied */
+               if(GS(key->from->name) == ID_ME) {
+                       Mesh *me;
+                       EditVert *eve;
+                       float (*co)[3];
+                       int a;
+
+                       me= (Mesh*)key->from;
+
+                       if(me->edit_mesh && me->edit_mesh->totvert == kb->totelem) {
+                               a= 0;
+                               co= MEM_callocN(sizeof(float)*3*me->edit_mesh->totvert, "key_block_get_data");
+
+                               for(eve=me->edit_mesh->verts.first; eve; eve=eve->next, a++)
+                                       VECCOPY(co[a], eve->co);
+
+                               *freedata= (char*)co;
+                               return (char*)co;
+                       }
+               }
+       }
+
+       *freedata= NULL;
+       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)
 {
        float ktot = 0.0, kd = 0.0;
        int elemsize, poinsize = 0, a, *ofsp, ofs[32], flagflo=0;
-       char *k1, *kref;
+       char *k1, *kref, *freek1, *freekref;
        char *cp, elemstr[8];
 
        if(key->from==NULL) return;
 
        if( GS(key->from->name)==ID_ME ) {
-               ofs[0]= sizeof(MVert);
+               ofs[0]= sizeof(float)*3;
                ofs[1]= 0;
                poinsize= ofs[0];
        }
        else if( GS(key->from->name)==ID_LT ) {
-               ofs[0]= sizeof(BPoint);
+               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(BPoint);
-               else ofs[0]= sizeof(BezTriple);
+               if(mode==KEY_BPOINT) ofs[0]= sizeof(float)*4;
+               else ofs[0]= sizeof(float)*10;
                
                ofs[1]= 0;
                poinsize= ofs[0];
        }
 
-
        if(end>tot) end= tot;
        
-       k1= k->data;
-       kref= key->refkey->data;
-       
-       if(tot != k->totelem) {
+       if(tot != kb->totelem) {
                ktot= 0.0;
                flagflo= 1;
-               if(k->totelem) {
-                       kd= k->totelem/(float)tot;
+               if(kb->totelem) {
+                       kd= kb->totelem/(float)tot;
                }
                else return;
        }
 
+       k1= key_block_get_data(key, actkb, kb, &freek1);
+       kref= key_block_get_data(key, actkb, key->refkey, &freekref);
+
        /* this exception is needed for slurphing */
        if(start!=0) {
                
@@ -548,33 +607,24 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                        
                        switch(cp[1]) {
                        case IPO_FLOAT:
-                               
                                if(weights) {
-                                       memcpy(poin, kref, sizeof(float)*cp[0]);
+                                       memcpy(poin, kref, sizeof(float)*3);
                                        if(*weights!=0.0f)
                                                rel_flerp(cp[0], (float *)poin, (float *)kref, (float *)k1, *weights);
                                        weights++;
                                }
                                else 
-                                       memcpy(poin, k1, sizeof(float)*cp[0]);
-
-                               poin+= ofsp[0];
-
+                                       memcpy(poin, k1, sizeof(float)*3);
                                break;
                        case IPO_BPOINT:
-                               memcpy(poin, k1, 3*sizeof(float));
-                               memcpy(poin+4*sizeof(float), k1+3*sizeof(float), sizeof(float));
-                               
-                               poin+= ofsp[0];                         
-
+                               memcpy(poin, k1, sizeof(float)*4);
                                break;
                        case IPO_BEZTRIPLE:
                                memcpy(poin, k1, sizeof(float)*10);
-                               poin+= ofsp[0]; 
-
                                break;
                        }
                        
+                       poin+= ofsp[0]; 
                        cp+= 2; ofsp++;
                }
                
@@ -594,71 +644,63 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                
                if(mode==KEY_BEZTRIPLE) a+=2;
        }
+
+       if(freek1) MEM_freeN(freek1);
+       if(freekref) MEM_freeN(freekref);
 }
 
-void cp_cu_key(Curve *cu, KeyBlock *kb, int start, int end)
+static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, int start, int end, char *out, int tot)
 {
        Nurb *nu;
-       int a, step = 0, tot, a1, a2;
        char *poin;
+       int a, step, a1, a2;
 
-       tot= count_curveverts(&cu->nurb);
-       nu= cu->nurb.first;
-       a= 0;
-       while(nu) {
+       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= (char *)nu->bp->vec;
-                       poin -= a*sizeof(BPoint);
-                       
+                       poin= out - a*sizeof(float)*4;
                        a1= MAX2(a, start);
                        a2= MIN2(a+step, end);
                        
-                       if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, NULL, KEY_BPOINT);
+                       if(a1<a2) cp_key(a1, a2, tot, poin, key, actkb, kb, NULL, KEY_BPOINT);
                }
                else if(nu->bezt) {
-                       
                        step= 3*nu->pntsu;
                        
-                       poin= (char *)nu->bezt->vec;
-                       poin -= a*sizeof(BezTriple);
-
+                       poin= out - a*sizeof(float)*10;
                        a1= MAX2(a, start);
                        a2= MIN2(a+step, end);
 
-                       if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, NULL, KEY_BEZTRIPLE);
-                       
+                       if(a1<a2) cp_key(a1, a2, tot, poin, key, actkb, kb, NULL, KEY_BEZTRIPLE);
                }
-               a+= step;
-               nu=nu->next;
+               else
+                       step= 0;
        }
 }
 
 
-void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode)
+void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock *actkb, 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 (G.f & G_DEBUG) printf("do_rel_key() \n");
-       
        if( GS(key->from->name)==ID_ME ) {
-               ofs[0]= sizeof(MVert);
+               ofs[0]= sizeof(float)*3;
                ofs[1]= 0;
        }
        else if( GS(key->from->name)==ID_LT ) {
-               ofs[0]= sizeof(BPoint);
+               ofs[0]= sizeof(float)*3;
                ofs[1]= 0;
        }
        else if( GS(key->from->name)==ID_CU ) {
-               if(mode==KEY_BPOINT) ofs[0]= sizeof(BPoint);
-               else ofs[0]= sizeof(BezTriple);
+               if(mode==KEY_BPOINT) ofs[0]= sizeof(float)*4;
+               else ofs[0]= sizeof(float)*10;
                
                ofs[1]= 0;
        }
@@ -675,7 +717,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode
        if(mode==KEY_BEZTRIPLE) elemsize*= 3;
 
        /* step 1 init */
-       cp_key(start, end, tot, basispoin, key, key->refkey, NULL, mode);
+       cp_key(start, end, tot, basispoin, key, actkb, key->refkey, NULL, mode);
        
        /* step 2: do it */
        
@@ -683,21 +725,18 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode
                if(kb!=key->refkey) {
                        float icuval= kb->curval;
                        
-                       if (G.f & G_DEBUG) printf("\tdo rel key %s : %s = %f \n", key->id.name+2, kb->name, icuval);
-                       
                        /* only with value, and no difference allowed */
                        if(!(kb->flag & KEYBLOCK_MUTE) && icuval!=0.0f && kb->totelem==tot) {
                                KeyBlock *refb;
                                float weight, *weights= kb->weights;
-                               
-                               if (G.f & G_DEBUG) printf("\t\tnot skipped \n");
-                               
-                               poin= basispoin;
-                               from= kb->data;
+
                                /* reference now can be any block */
                                refb= BLI_findlink(&key->block, kb->relative);
                                if(refb==NULL) continue;
-                               reffrom= refb->data;
+                               
+                               poin= basispoin;
+                               from= key_block_get_data(key, actkb, kb, &freefrom);
+                               reffrom= key_block_get_data(key, actkb, refb, &freereffrom);
                                
                                poin+= start*ofs[0];
                                reffrom+= key->elemsize*start;  // key elemsize yes!
@@ -719,17 +758,13 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode
                                                
                                                switch(cp[1]) {
                                                case IPO_FLOAT:
-                                                       rel_flerp(cp[0], (float *)poin, (float *)reffrom, (float *)from, weight);
-                                                       
+                                                       rel_flerp(3, (float *)poin, (float *)reffrom, (float *)from, weight);
                                                        break;
                                                case IPO_BPOINT:
-                                                       rel_flerp(3, (float *)poin, (float *)reffrom, (float *)from, icuval);
-                                                       rel_flerp(1, (float *)(poin+16), (float *)(reffrom+16), (float *)(from+16), icuval);
-                       
+                                                       rel_flerp(4, (float *)poin, (float *)reffrom, (float *)from, weight);
                                                        break;
                                                case IPO_BEZTRIPLE:
-                                                       rel_flerp(9, (float *)poin, (float *)reffrom, (float *)from, icuval);
-                       
+                                                       rel_flerp(10, (float *)poin, (float *)reffrom, (float *)from, weight);
                                                        break;
                                                }
                                                
@@ -745,38 +780,39 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode
                                        if(mode==KEY_BEZTRIPLE) b+= 2;
                                        if(weights) weights++;
                                }
+
+                               if(freefrom) MEM_freeN(freefrom);
+                               if(freereffrom) MEM_freeN(freereffrom);
                        }
                }
        }
 }
 
 
-static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock **k, float *t, int mode)
+static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, 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;
        int a, ofs[32], *ofsp;
        int flagdo= 15, flagflo=0, elemsize, poinsize=0;
-       char *k1, *k2, *k3, *k4;
+       char *k1, *k2, *k3, *k4, *freek1, *freek2, *freek3, *freek4;
        char *cp, elemstr[8];;
 
        if(key->from==0) return;
 
-       if (G.f & G_DEBUG) printf("do_key() \n");
-       
        if( GS(key->from->name)==ID_ME ) {
-               ofs[0]= sizeof(MVert);
+               ofs[0]= sizeof(float)*3;
                ofs[1]= 0;
                poinsize= ofs[0];
        }
        else if( GS(key->from->name)==ID_LT ) {
-               ofs[0]= sizeof(BPoint);
+               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(BPoint);
-               else ofs[0]= sizeof(BezTriple);
+               if(mode==KEY_BPOINT) ofs[0]= sizeof(float)*4;
+               else ofs[0]= sizeof(float)*10;
                
                ofs[1]= 0;
                poinsize= ofs[0];
@@ -784,10 +820,10 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
        
        if(end>tot) end= tot;
 
-       k1= k[0]->data;
-       k2= k[1]->data;
-       k3= k[2]->data;
-       k4= k[3]->data;
+       k1= key_block_get_data(key, actkb, k[0], &freek1);
+       k2= key_block_get_data(key, actkb, k[1], &freek2);
+       k3= key_block_get_data(key, actkb, k[2], &freek3);
+       k4= key_block_get_data(key, actkb, k[3], &freek4);
 
        /*  test for more or less points (per key!) */
        if(tot != k[0]->totelem) {
@@ -895,26 +931,17 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                        
                        switch(cp[1]) {
                        case IPO_FLOAT:
-                               flerp(cp[0], (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
-                               poin+= ofsp[0];                         
-
+                               flerp(3, (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
                                break;
                        case IPO_BPOINT:
-                               flerp(3, (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
-                               flerp(1, (float *)(poin+16), (float *)(k1+12), (float *)(k2+12), (float *)(k3+12), (float *)(k4+12), t);
-                               
-                               poin+= ofsp[0];                         
-
+                               flerp(4, (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
                                break;
                        case IPO_BEZTRIPLE:
-                               flerp(9, (void *)poin, (void *)k1, (void *)k2, (void *)k3, (void *)k4, t);
-                               flerp(1, (float *)(poin+36), (float *)(k1+36), (float *)(k2+36), (float *)(k3+36), (float *)(k4+36), t);
-                               poin+= ofsp[0];                         
-
+                               flerp(10, (void *)poin, (void *)k1, (void *)k2, (void *)k3, (void *)k4, t);
                                break;
                        }
                        
-
+                       poin+= ofsp[0];                         
                        cp+= 2;
                        ofsp++;
                }
@@ -962,12 +989,19 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                
                if(mode==KEY_BEZTRIPLE) a+= 2;
        }
+
+       if(freek1) MEM_freeN(freek1);
+       if(freek2) MEM_freeN(freek2);
+       if(freek3) MEM_freeN(freek3);
+       if(freek4) MEM_freeN(freek4);
 }
 
 static float *get_weights_array(Object *ob, char *vgroup)
 {
        bDeformGroup *curdef;
        MDeformVert *dvert= NULL;
+       EditMesh *em= NULL;
+       EditVert *eve;
        int totvert= 0, index= 0;
        
        /* no vgroup string set? */
@@ -978,6 +1012,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;
@@ -997,55 +1034,61 @@ static float *get_weights_array(Object *ob, char *vgroup)
                int i, j;
                
                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) {
+                                       for(j=0; j<dvert->totweight; j++) {
+                                               if(dvert->dw[j].def_nr == index) {
+                                                       weights[i]= dvert->dw[j].weight;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               else {
+                       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;
+                                       }
                                }
                        }
                }
+
                return weights;
        }
        return NULL;
 }
 
-static int do_mesh_key(Scene *scene, Object *ob, Mesh *me)
+static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
 {
-       KeyBlock *k[4];
-       float cfra, ctime, t[4], delta, loc[3], size[3];
+       KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
+       float cfra, ctime, t[4], delta;
        int a, flag = 0, step;
        
-       if(me->totvert==0) return 0;
-       if(me->key==NULL) return 0;
-       if(me->key->block.first==NULL) return 0;
-       
-       /* prevent python from screwing this up? anyhoo, the from pointer could be dropped */
-       me->key->from= (ID *)me;
-       
-       if (G.f & G_DEBUG) printf("do mesh key ob:%s me:%s ke:%s \n", ob->id.name+2, me->id.name+2, me->key->id.name+2);
-       
-       if(me->key->slurph && me->key->type!=KEY_RELATIVE ) {
-               if (G.f & G_DEBUG) printf("\tslurph key\n");
-               
-               delta= me->key->slurph;
-               delta/= me->totvert;
+       if(key->slurph && key->type!=KEY_RELATIVE ) {
+               delta= key->slurph;
+               delta/= tot;
                
                step= 1;
-               if(me->totvert>100 && slurph_opt) {
-                       step= me->totvert/50;
+               if(tot>100 && slurph_opt) {
+                       step= tot/50;
                        delta*= step;
                        /* in do_key and cp_key the case a>tot is handled */
                }
                
                cfra= (float)scene->r.cfra;
                
-               for(a=0; a<me->totvert; a+=step, cfra+= delta) {
+               for(a=0; a<tot; a+=step, cfra+= delta) {
                        
                        ctime= bsystem_time(scene, 0, cfra, 0.0); // xxx  ugly cruft!
 #if 0 // XXX old animation system
-                       if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) {
+                       if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
                                ctime /= 100.0;
                                CLAMP(ctime, 0.0, 1.0);
                        }
@@ -1054,42 +1097,33 @@ static int do_mesh_key(Scene *scene, Object *ob, Mesh *me)
                        ctime /= 100.0f;
                        CLAMP(ctime, 0.0f, 1.0f); // XXX for compat, we use this, but this clamping was confusing
                
-                       flag= setkeys(ctime, &me->key->block, k, t, 0);
-                       if(flag==0) {
-                               
-                               do_key(a, a+step, me->totvert, (char *)me->mvert->co, me->key, k, t, 0);
-                       }
-                       else {
-                               cp_key(a, a+step, me->totvert, (char *)me->mvert->co, me->key, k[2], NULL, 0);
-                       }
+                       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);
                }
-               
-               if(flag && k[2]==me->key->refkey) tex_space_mesh(me);
-               else boundbox_mesh(me, loc, size);
        }
        else {
-               if(me->key->type==KEY_RELATIVE) {
+               if(key->type==KEY_RELATIVE) {
                        KeyBlock *kb;
                        
-                       if (G.f & G_DEBUG) printf("\tdo relative \n");
-                       
-                       for(kb= me->key->block.first; kb; kb= kb->next)
+                       for(kb= key->block.first; kb; kb= kb->next)
                                kb->weights= get_weights_array(ob, kb->vgroup);
 
-                       do_rel_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, 0);
+                       do_rel_key(0, tot, tot, (char *)out, key, actkb, 0);
                        
-                       for(kb= me->key->block.first; kb; kb= kb->next) {
+                       for(kb= key->block.first; kb; kb= kb->next) {
                                if(kb->weights) MEM_freeN(kb->weights);
                                kb->weights= NULL;
                        }
                }
                else {
-                       if (G.f & G_DEBUG) printf("\tdo absolute \n");
-                       
                        ctime= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0f); // xxx old cruft
                        
 #if 0 // XXX old animation system
-                       if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) {
+                       if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
                                ctime /= 100.0;
                                CLAMP(ctime, 0.0, 1.0);
                        }
@@ -1098,106 +1132,69 @@ static int do_mesh_key(Scene *scene, Object *ob, Mesh *me)
                        ctime /= 100.0f;
                        CLAMP(ctime, 0.0f, 1.0f); // XXX for compat, we use this, but this clamping was confusing
                        
-                       flag= setkeys(ctime, &me->key->block, k, t, 0);
-                       if(flag==0) {
-                               do_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k, t, 0);
-                       }
-                       else {
-                               cp_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k[2], NULL, 0);
-                       }
-                       
-                       if(flag && k[2]==me->key->refkey) tex_space_mesh(me);
-                       else boundbox_mesh(me, loc, size);
+                       flag= setkeys(ctime, &key->block, k, t, 0);
+
+                       if(flag==0)
+                               do_key(0, tot, tot, (char *)out, key, actkb, k, t, 0);
+                       else
+                               cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, 0);
                }
        }
-       return 1;
 }
 
-static void do_cu_key(Curve *cu, KeyBlock **k, float *t)
+static void do_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, char *out, int tot)
 {
        Nurb *nu;
-       int a, step = 0, tot;
        char *poin;
+       int a, step;
        
-       tot= count_curveverts(&cu->nurb);
-       nu= cu->nurb.first;
-       a= 0;
-       
-       while(nu) {
+       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= (char *)nu->bp->vec;
-                       poin -= a*sizeof(BPoint);
-                       
-                       do_key(a, a+step, tot, poin, cu->key, k, t, KEY_BPOINT);
+                       poin= out - a*sizeof(float)*4;
+                       do_key(a, a+step, tot, poin, key, actkb, k, t, KEY_BPOINT);
                }
                else if(nu->bezt) {
-                       
                        step= 3*nu->pntsu;
-                       
-                       poin= (char *)nu->bezt->vec;
-                       poin -= a*sizeof(BezTriple);
-
-                       do_key(a, a+step, tot, poin, cu->key, k, t, KEY_BEZTRIPLE);
-                       
+                       poin= out - a*sizeof(float)*10;
+                       do_key(a, a+step, tot, poin, key, actkb, k, t, KEY_BEZTRIPLE);
                }
-               a+= step;
-               nu=nu->next;
+               else
+                       step= 0;
        }
 }
 
-static void do_rel_cu_key(Curve *cu, float ctime)
+static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, float ctime, char *out, int tot)
 {
        Nurb *nu;
-       int a, step = 0, tot;
        char *poin;
+       int a, step;
        
-       tot= count_curveverts(&cu->nurb);
-       nu= cu->nurb.first;
-       a= 0;
-       while(nu) {
+       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= (char *)nu->bp->vec;
-                       poin -= a*sizeof(BPoint);
-                       
-                       do_rel_key(a, a+step, tot, poin, cu->key, KEY_BPOINT);
+                       poin= out - a*sizeof(float)*3;
+                       do_rel_key(a, a+step, tot, out, key, actkb, KEY_BPOINT);
                }
                else if(nu->bezt) {
-                       
                        step= 3*nu->pntsu;
-                       
-                       poin= (char *)nu->bezt->vec;
-                       poin -= a*sizeof(BezTriple);
-
-                       do_rel_key(a, a+step, tot, poin, cu->key, KEY_BEZTRIPLE);
+                       poin= out - a*sizeof(float)*10;
+                       do_rel_key(a, a+step, tot, poin, key, actkb, KEY_BEZTRIPLE);
                }
-               a+= step;
-               
-               nu=nu->next;
+               else
+                       step= 0;
        }
 }
 
-static int do_curve_key(Scene *scene, Curve *cu)
+static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
 {
-       KeyBlock *k[4];
+       Curve *cu= ob->data;
+       KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
        float cfra, ctime, t[4], delta;
-       int a, flag = 0, step = 0, tot;
-       
-       tot= count_curveverts(&cu->nurb);
+       int a, flag = 0, step = 0;
        
-       if(tot==0) return 0;
-       if(cu->key==NULL) return 0;
-       if(cu->key->block.first==NULL) return 0;
-       
-       if(cu->key->slurph) {
-               delta= cu->key->slurph;
+       if(key->slurph) {
+               delta= key->slurph;
                delta/= tot;
                
                step= 1;
@@ -1212,66 +1209,52 @@ static int do_curve_key(Scene *scene, Curve *cu)
                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(cu->key->ipo, KEY_SPEED, &ctime)==0) {
+                       if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
                                ctime /= 100.0;
                                CLAMP(ctime, 0.0, 1.0);
                        }
 #endif // XXX old animation system
                
-                       flag= setkeys(ctime, &cu->key->block, k, t, 0);
-                       if(flag==0) {
-                               
-                               /* do_key(a, a+step, tot, (char *)cu->mvert->co, cu->key, k, t, 0); */
-                       }
-                       else {
-                               /* cp_key(a, a+step, tot, (char *)cu->mvert->co, cu->key, k[2],0); */
-                       }
+                       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);
                }
-
-               if(flag && k[2]==cu->key->refkey) tex_space_curve(cu);
-               
-               
        }
        else {
                
                ctime= bsystem_time(scene, NULL, (float)scene->r.cfra, 0.0);
                
-               if(cu->key->type==KEY_RELATIVE) {
-                       do_rel_cu_key(cu, ctime);
+               if(key->type==KEY_RELATIVE) {
+                       do_rel_cu_key(cu, cu->key, actkb, ctime, out, tot);
                }
                else {
 #if 0 // XXX old animation system
-                       if(calc_ipo_spec(cu->key->ipo, KEY_SPEED, &ctime)==0) {
+                       if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
                                ctime /= 100.0;
                                CLAMP(ctime, 0.0, 1.0);
                        }
 #endif // XXX old animation system
                        
-                       flag= setkeys(ctime, &cu->key->block, k, t, 0);
+                       flag= setkeys(ctime, &key->block, k, t, 0);
                        
-                       if(flag==0) do_cu_key(cu, k, t);
-                       else cp_cu_key(cu, k[2], 0, tot);
-                                       
-                       if(flag && k[2]==cu->key->refkey) tex_space_curve(cu);
+                       if(flag==0) do_cu_key(cu, key, actkb, k, t, out, tot);
+                       else cp_cu_key(cu, key, actkb, k[2], 0, tot, out, tot);
                }
        }
-       
-       return 1;
 }
 
-static int do_latt_key(Scene *scene, Object *ob, Lattice *lt)
+static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
 {
-       KeyBlock *k[4];
+       Lattice *lt= ob->data;
+       KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
        float delta, cfra, ctime, t[4];
-       int a, tot, flag;
+       int a, flag;
        
-       if(lt->key==NULL) return 0;
-       if(lt->key->block.first==NULL) return 0;
-
-       tot= lt->pntsu*lt->pntsv*lt->pntsw;
-
-       if(lt->key->slurph) {
-               delta= lt->key->slurph;
+       if(key->slurph) {
+               delta= key->slurph;
                delta/= (float)tot;
                
                cfra= (float)scene->r.cfra;
@@ -1280,74 +1263,110 @@ static int do_latt_key(Scene *scene, Object *ob, Lattice *lt)
                        
                        ctime= bsystem_time(scene, 0, cfra, 0.0); // XXX old cruft
 #if 0 // XXX old animation system
-                       if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &ctime)==0) {
+                       if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
                                ctime /= 100.0;
                                CLAMP(ctime, 0.0, 1.0);
                        }
 #endif // XXX old animation system
                
-                       flag= setkeys(ctime, &lt->key->block, k, t, 0);
-                       if(flag==0) {
-                               
-                               do_key(a, a+1, tot, (char *)lt->def->vec, lt->key, k, t, 0);
-                       }
-                       else {
-                               cp_key(a, a+1, tot, (char *)lt->def->vec, lt->key, k[2], NULL, 0);
-                       }
+                       flag= setkeys(ctime, &key->block, k, t, 0);
+
+                       if(flag==0)
+                               do_key(a, a+1, tot, (char *)out, key, actkb, k, t, 0);
+                       else
+                               cp_key(a, a+1, tot, (char *)out, key, actkb, k[2], NULL, 0);
                }               
        }
        else {
-               ctime= bsystem_time(scene, NULL, (float)scene->r.cfra, 0.0);
-       
-               if(lt->key->type==KEY_RELATIVE) {
+               if(key->type==KEY_RELATIVE) {
                        KeyBlock *kb;
                        
-                       for(kb= lt->key->block.first; kb; kb= kb->next)
+                       for(kb= key->block.first; kb; kb= kb->next)
                                kb->weights= get_weights_array(ob, kb->vgroup);
                        
-                       do_rel_key(0, tot, tot, (char *)lt->def->vec, lt->key, 0);
+                       do_rel_key(0, tot, tot, (char *)out, key, actkb, 0);
                        
-                       for(kb= lt->key->block.first; kb; kb= kb->next) {
+                       for(kb= key->block.first; kb; kb= kb->next) {
                                if(kb->weights) MEM_freeN(kb->weights);
                                kb->weights= NULL;
                        }
                }
                else {
+                       ctime= bsystem_time(scene, NULL, (float)scene->r.cfra, 0.0);
+
 #if 0 // XXX old animation system
-                       if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &ctime)==0) {
+                       if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
                                ctime /= 100.0;
                                CLAMP(ctime, 0.0, 1.0);
                        }
 #endif // XXX old animation system
                        
-                       flag= setkeys(ctime, &lt->key->block, k, t, 0);
-                       if(flag==0) {
-                               do_key(0, tot, tot, (char *)lt->def->vec, lt->key, k, t, 0);
-                       }
-                       else {
-                               cp_key(0, tot, tot, (char *)lt->def->vec, lt->key, k[2], NULL, 0);
-                       }
+                       flag= setkeys(ctime, &key->block, k, t, 0);
+
+                       if(flag==0)
+                               do_key(0, tot, tot, (char *)out, key, actkb, k, t, 0);
+                       else
+                               cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, 0);
                }
        }
        
        if(lt->flag & LT_OUTSIDE) outside_lattice(lt);
-       
-       return 1;
 }
 
-/* returns 1 when key applied */
-int do_ob_key(Scene *scene, Object *ob)
+/* returns key coordinates (+ tilt) when key applied, NULL otherwise */
+float *do_ob_key(Scene *scene, Object *ob)
 {
        Key *key= ob_get_key(ob);
+       KeyBlock *actkb= ob_get_keyblock(ob);
+       char *out;
+       int tot= 0, size= 0;
        
-       if(key==NULL)
-               return 0;
+       if(key==NULL || key->block.first==NULL)
+               return NULL;
+
+       /* compute size of output array */
+       if(ob->type == OB_MESH) {
+               Mesh *me= ob->data;
+
+               tot= me->totvert;
+               size= tot*3*sizeof(float);
+       }
+       else if(ob->type == OB_LATTICE) {
+               Lattice *lt= ob->data;
+
+               tot= lt->pntsu*lt->pntsv*lt->pntsw;
+               size= tot*3*sizeof(float);
+       }
+       else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
+               Curve *cu= ob->data;
+               Nurb *nu;
+
+               for(nu=cu->nurb.first; nu; nu=nu->next) {
+                       if(nu->bezt) {
+                               tot += 3*nu->pntsu;
+                               size += nu->pntsu*10*sizeof(float);
+                       }
+                       else if(nu->bp) {
+                               tot += nu->pntsu*nu->pntsv;
+                               size += nu->pntsu*nu->pntsv*10*sizeof(float);
+                       }
+               }
+       }
+
+       /* if nothing to interpolate, cancel */
+       if(tot == 0 || size == 0)
+               return NULL;
+       
+       /* allocate array */
+       out= MEM_callocN(size, "do_ob_key out");
+
+       /* prevent python from screwing this up? anyhoo, the from pointer could be dropped */
+       key->from= (ID *)ob->data;
                
-       if(ob->shapeflag & (OB_SHAPE_LOCK|OB_SHAPE_TEMPLOCK)) {
+       if(ob->shapeflag & OB_SHAPE_LOCK) {
+               /* shape locked, copy the locked shape instead of blending */
                KeyBlock *kb= BLI_findlink(&key->block, ob->shapenr-1);
                
-               if (G.f & G_DEBUG) printf("ob %s, key %s locked \n", ob->id.name+2, key->id.name+2);
-               
                if(kb && (kb->flag & KEYBLOCK_MUTE))
                        kb= key->refkey;
 
@@ -1356,53 +1375,29 @@ int do_ob_key(Scene *scene, Object *ob)
                        ob->shapenr= 1;
                }
                
-               if(ob->type==OB_MESH) {
-                       Mesh *me= ob->data;
+               if(ELEM(ob->type, OB_MESH, OB_LATTICE)) {
                        float *weights= get_weights_array(ob, kb->vgroup);
 
-                       cp_key(0, me->totvert, me->totvert, (char *)me->mvert->co, key, kb, weights, 0);
-                       
-                       if(weights) MEM_freeN(weights);
-               }
-               else if(ob->type==OB_LATTICE) {
-                       Lattice *lt= ob->data;
-                       float *weights= get_weights_array(ob, kb->vgroup);
-                       int tot= lt->pntsu*lt->pntsv*lt->pntsw;
-                       
-                       cp_key(0, tot, tot, (char *)lt->def->vec, key, kb, weights, 0);
-                       
+                       cp_key(0, tot, tot, (char*)out, key, actkb, kb, weights, 0);
+
                        if(weights) MEM_freeN(weights);
                }
-               else if ELEM(ob->type, OB_CURVE, OB_SURF) {
-                       Curve *cu= ob->data;
-                       int tot= count_curveverts(&cu->nurb);
-                       
-                       cp_cu_key(cu, kb, 0, tot);
-               }
-               return 1;
+               else if(ELEM(ob->type, OB_CURVE, OB_SURF))
+                       cp_cu_key(ob->data, key, actkb, kb, 0, tot, out, tot);
        }
        else {
-#if 0 // XXX old animation system
-               // NOTE: this stuff was NEVER reliable at all...
-               if(ob->ipoflag & OB_ACTION_KEY)
-                       do_all_object_actions(scene, ob);
-               else {
-                       calc_ipo(key->ipo, bsystem_time(scene, ob, scene->r.cfra, 0.0));
-                       execute_ipo((ID *)key, key->ipo);
-               }
-#endif // XXX old animation system
                /* do shapekey local drivers */
                float ctime= (float)scene->r.cfra; // XXX this needs to be checked
-               if (G.f & G_DEBUG) printf("ob %s - do shapekey (%s) drivers \n", ob->id.name+2, key->id.name+2);
+               
                BKE_animsys_evaluate_animdata(&key->id, key->adt, ctime, ADT_RECALC_DRIVERS);
                
-               if(ob->type==OB_MESH) return do_mesh_key(scene, ob, ob->data);
-               else if(ob->type==OB_CURVE) return do_curve_key(scene, ob->data);
-               else if(ob->type==OB_SURF) return do_curve_key(scene, ob->data);
-               else if(ob->type==OB_LATTICE) return do_latt_key(scene, ob, ob->data);
+               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);
+               else if(ob->type==OB_CURVE) do_curve_key(scene, ob, key, out, tot);
+               else if(ob->type==OB_SURF) do_curve_key(scene, ob, key, out, tot);
        }
        
-       return 0;
+       return (float*)out;
 }
 
 Key *ob_get_key(Object *ob)
@@ -1424,6 +1419,55 @@ Key *ob_get_key(Object *ob)
        return NULL;
 }
 
+KeyBlock *add_keyblock(Key *key, 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.1;
+       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) 
 {
@@ -1437,6 +1481,16 @@ KeyBlock *ob_get_keyblock(Object *ob)
        return NULL;
 }
 
+KeyBlock *ob_get_reference_keyblock(Object *ob)
+{
+       Key *key= ob_get_key(ob);
+       
+       if (key)
+               return key->refkey;
+
+       return NULL;
+}
+
 /* get the appropriate KeyBlock given an index */
 KeyBlock *key_get_keyblock(Key *key, int index)
 {
@@ -1471,3 +1525,206 @@ KeyBlock *key_get_named_keyblock(Key *key, const char name[])
        
        return NULL;
 }
+
+/* Get RNA-Path for 'value' setting of the given ShapeKey 
+ * NOTE: the user needs to free the returned string once they're finishe with it
+ */
+char *key_get_curValue_rnaPath(Key *key, KeyBlock *kb)
+{
+       PointerRNA ptr;
+       PropertyRNA *prop;
+       
+       /* sanity checks */
+       if ELEM(NULL, key, kb)
+               return NULL;
+       
+       /* create the RNA pointer */
+       RNA_pointer_create(&key->id, &RNA_ShapeKey, kb, &ptr);
+       /* get pointer to the property too */
+       prop= RNA_struct_find_property(&ptr, "value");
+       
+       /* 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  *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);
+       }
+}