2.5 / Nodes / Transformations
[blender.git] / source / blender / editors / transform / transform_conversions.c
index 36deae8b98e054354a8677fad5fbc97f52f4a50b..6b9c635779f1c3a38157ca0d2fd59e72e18eee81 100644 (file)
  * ***** END GPL LICENSE BLOCK *****
  */
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #ifndef WIN32
 #include <unistd.h>
 #else
@@ -56,6 +52,7 @@
 #include "DNA_meta_types.h"
 #include "DNA_modifier_types.h"
 #include "DNA_nla_types.h"
+#include "DNA_node_types.h"
 #include "DNA_object_types.h"
 #include "DNA_object_force.h"
 #include "DNA_particle_types.h"
 #include "ED_keyframing.h"
 #include "ED_keyframes_edit.h"
 #include "ED_view3d.h"
+#include "ED_mesh.h"
 
 #include "UI_view2d.h"
 
@@ -162,8 +160,6 @@ void transform_aspect_ratio_tface_uv(float *a1, float *a2) {}
 
 /* local function prototype - for Object/Bone Constraints */
 static short constraints_list_needinv(TransInfo *t, ListBase *list);
-/* local function prototype - for finding number of keyframes that are selected for editing */
-static int count_ipo_keys(Ipo *ipo, char side, float cfra);
 
 /* ************************** Functions *************************** */
 
@@ -345,7 +341,6 @@ static void createTransTexspace(bContext *C, TransInfo *t)
 static void createTransEdge(bContext *C, TransInfo *t) {
 #if 0  // TRANSFORM_FIX_ME
        TransData *td = NULL;
-       EditMesh *em = G.editMesh;
        EditEdge *eed;
        float mtx[3][3], smtx[3][3];
        int count=0, countsel=0;
@@ -370,7 +365,7 @@ static void createTransEdge(bContext *C, TransInfo *t) {
 
        td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
 
-       Mat3CpyMat4(mtx, G.obedit->obmat);
+       Mat3CpyMat4(mtx, t->obedit->obmat);
        Mat3Inv(smtx, mtx);
 
        for(eed= em->edges.first; eed; eed= eed->next) {
@@ -1028,7 +1023,7 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t)
        // TRANSFORM_FIX_ME
 #if 0
        EditBone *ebo;
-       bArmature *arm= G.obedit->data;
+       bArmature *arm= t->obedit->data;
        TransData *td;
        float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
 
@@ -1054,7 +1049,7 @@ static void createTransArmatureVerts(bContext *C, TransInfo *t)
 
     if (!t->total) return;
        
-       Mat3CpyMat4(mtx, G.obedit->obmat);
+       Mat3CpyMat4(mtx, t->obedit->obmat);
        Mat3Inv(smtx, mtx);
 
     td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
@@ -1226,7 +1221,7 @@ static void createTransMBallVerts(bContext *C, TransInfo *t)
        td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
        tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
 
-       Mat3CpyMat4(mtx, G.obedit->obmat);
+       Mat3CpyMat4(mtx, t->obedit->obmat);
        Mat3Inv(smtx, mtx);
     
        for(ml= editelems.first; ml; ml= ml->next) {
@@ -1377,7 +1372,7 @@ static void createTransCurveVerts(bContext *C, TransInfo *t)
        else t->total = countsel;
        t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
 
-       Mat3CpyMat4(mtx, G.obedit->obmat);
+       Mat3CpyMat4(mtx, t->obedit->obmat);
        Mat3Inv(smtx, mtx);
        
     td = t->data;
@@ -1565,7 +1560,7 @@ static void createTransLatticeVerts(bContext *C, TransInfo *t)
        else t->total = countsel;
        t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
        
-       Mat3CpyMat4(mtx, G.obedit->obmat);
+       Mat3CpyMat4(mtx, t->obedit->obmat);
        Mat3Inv(smtx, mtx);
 
        td = t->data;
@@ -1761,9 +1756,8 @@ void flushTransParticles(TransInfo *t)
 #define E_VEC(a)       (vectors + (3 * (a)->tmp.l))
 #define E_NEAR(a)      (nears[((a)->tmp.l)])
 #define THRESHOLD      0.0001f
-static void editmesh_set_connectivity_distance(int total, float *vectors, EditVert **nears)
+static void editmesh_set_connectivity_distance(EditMesh *em, int total, float *vectors, EditVert **nears)
 {
-       EditMesh *em = G.editMesh;
        EditVert *eve;
        EditEdge *eed;
        int i= 0, done= 1;
@@ -1874,9 +1868,8 @@ static void editmesh_set_connectivity_distance(int total, float *vectors, EditVe
 }
 
 /* loop-in-a-loop I know, but we need it! (ton) */
-static void get_face_center(float *cent, EditVert *eve)
+static void get_face_center(float *cent, EditMesh *em, EditVert *eve)
 {
-       EditMesh *em = G.editMesh;
        EditFace *efa;
        
        for(efa= em->faces.first; efa; efa= efa->next)
@@ -1890,7 +1883,7 @@ static void get_face_center(float *cent, EditVert *eve)
 
 //way to overwrite what data is edited with transform
 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
-static void VertsToTransData(TransData *td, EditVert *eve)
+static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve)
 {
        td->flag = 0;
        //if(key)
@@ -1899,9 +1892,8 @@ static void VertsToTransData(TransData *td, EditVert *eve)
        td->loc = eve->co;
        
        VECCOPY(td->center, td->loc);
-// TRANSFORM_FIX_ME    
-//     if(G.vd->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE))
-//             get_face_center(td->center, eve);
+       if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))
+               get_face_center(td->center, em, eve);
        VECCOPY(td->iloc, td->loc);
 
        // Setting normals
@@ -1917,7 +1909,7 @@ static void VertsToTransData(TransData *td, EditVert *eve)
        td->tdi = NULL;
        td->val = NULL;
        td->extra = NULL;
-       if (BIF_GetTransInfo()->mode == TFM_BWEIGHT) {
+       if (t->mode == TFM_BWEIGHT) {
                td->val = &(eve->bweight);
                td->ival = eve->bweight;
        }
@@ -1958,19 +1950,20 @@ static int modifiers_disable_subsurf_temporary(Object *ob)
 }
 
 /* disable subsurf temporal, get mapped cos, and enable it */
-static float *get_crazy_mapped_editverts(void)
+static float *get_crazy_mapped_editverts(TransInfo *t)
 {
+       Mesh *me= t->obedit->data;
        DerivedMesh *dm;
        float *vertexcos;
 
        /* disable subsurf temporal, get mapped cos, and enable it */
-       if(modifiers_disable_subsurf_temporary(G.obedit)) {
+       if(modifiers_disable_subsurf_temporary(t->obedit)) {
                /* need to make new derivemesh */
-               makeDerivedMesh(G.obedit, CD_MASK_BAREMESH);
+               makeDerivedMesh(t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
        }
 
        /* now get the cage */
-       dm= editmesh_get_derived_cage(CD_MASK_BAREMESH);
+       dm= editmesh_get_derived_cage(t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
 
        vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
        dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
@@ -1978,7 +1971,7 @@ static float *get_crazy_mapped_editverts(void)
        dm->release(dm);
        
        /* set back the flag, no new cage needs to be built, transform does it */
-       modifiers_disable_subsurf_temporary(G.obedit);
+       modifiers_disable_subsurf_temporary(t->obedit);
        
        return vertexcos;
 }
@@ -2001,9 +1994,8 @@ static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3,
 }
 #undef TAN_MAKE_VEC
 
-static void set_crazyspace_quats(float *origcos, float *mappedcos, float *quats)
+static void set_crazyspace_quats(EditMesh *em, float *origcos, float *mappedcos, float *quats)
 {
-       EditMesh *em = G.editMesh;
        EditVert *eve, *prev;
        EditFace *efa;
        float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
@@ -2100,10 +2092,9 @@ void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
 
 static void createTransEditVerts(bContext *C, TransInfo *t)
 {
-       // TRANSFORM_FIX_ME
-#if 0
+       Scene *scene = CTX_data_scene(C);
        TransData *tob = NULL;
-       EditMesh *em = G.editMesh;
+       EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
        EditVert *eve;
        EditVert **nears = NULL;
        EditVert *eve_act = NULL;
@@ -2113,13 +2104,13 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
        int propmode = t->flag & T_PROP_EDIT;
        int mirror = 0;
        
-       if ((t->options & CTX_NO_MIRROR) == 0 && (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
+       if ((t->options & CTX_NO_MIRROR) == 0 && (scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
        {
                mirror = 1;
        }
 
        // transform now requires awareness for select mode, so we tag the f1 flags in verts
-       if(G.scene->selectmode & SCE_SELECT_VERTEX) {
+       if(scene->selectmode & SCE_SELECT_VERTEX) {
                for(eve= em->verts.first; eve; eve= eve->next) {
                        if(eve->h==0 && (eve->f & SELECT)) 
                                eve->f1= SELECT;
@@ -2127,7 +2118,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
                                eve->f1= 0;
                }
        }
-       else if(G.scene->selectmode & SCE_SELECT_EDGE) {
+       else if(scene->selectmode & SCE_SELECT_EDGE) {
                EditEdge *eed;
                for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
                for(eed= em->edges.first; eed; eed= eed->next) {
@@ -2158,8 +2149,8 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
        if (countsel==0) return;
        
        /* check active */
-       if (G.editMesh->selected.last) {
-               EditSelection *ese = G.editMesh->selected.last;
+       if (em->selected.last) {
+               EditSelection *ese = em->selected.last;
                if ( ese->type == EDITVERT ) {
                        eve_act = (EditVert *)ese->data;
                }
@@ -2176,26 +2167,26 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
        else t->total = countsel;
        tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
        
-       Mat3CpyMat4(mtx, G.obedit->obmat);
+       Mat3CpyMat4(mtx, t->obedit->obmat);
        Mat3Inv(smtx, mtx);
 
-       if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
+       if(propmode) editmesh_set_connectivity_distance(em, t->total, vectors, nears);
        
        /* detect CrazySpace [tm] */
        if(propmode==0) {
-               if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
-                       if(modifiers_isDeformed(G.obedit)) {
+               if(modifiers_getCageIndex(t->obedit, NULL)>=0) {
+                       if(modifiers_isDeformed(t->obedit)) {
                                /* check if we can use deform matrices for modifier from the
                                   start up to stack, they are more accurate than quats */
-                               totleft= editmesh_get_first_deform_matrices(&defmats, &defcos);
+                               totleft= editmesh_get_first_deform_matrices(t->obedit, em, &defmats, &defcos);
 
                                /* if we still have more modifiers, also do crazyspace
                                   correction with quats, relative to the coordinates after
                                   the modifiers that support deform matrices (defcos) */
                                if(totleft > 0) {
-                                       mappedcos= get_crazy_mapped_editverts();
+                                       mappedcos= get_crazy_mapped_editverts(t);
                                        quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
-                                       set_crazyspace_quats((float*)defcos, mappedcos, quats);
+                                       set_crazyspace_quats(em, (float*)defcos, mappedcos, quats);
                                        if(mappedcos)
                                                MEM_freeN(mappedcos);
                                }
@@ -2220,7 +2211,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
        for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
                if(eve->h==0) {
                        if(propmode || eve->f1) {
-                               VertsToTransData(tob, eve);
+                               VertsToTransData(t, tob, em, eve);
                                
                                /* selected */
                                if(eve->f1) tob->flag |= TD_SELECTED;
@@ -2270,7 +2261,7 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
                                
                                /* Mirror? */
                                if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
-                                       EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc);        /* initializes octree on first call */
+                                       EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, tob->iloc);   /* initializes octree on first call */
                                        if(vmir != eve) tob->extra = vmir;
                                }
                                tob++;
@@ -2286,7 +2277,19 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
                MEM_freeN(quats);
        if(defmats)
                MEM_freeN(defmats);
-#endif
+}
+
+/* *** NODE EDITOR *** */
+void flushTransNodes(TransInfo *t)
+{
+       int a;
+       TransData2D *td;
+       
+       /* flush to 2d vector from internally used 3d vector */
+       for(a=0, td= t->data2d; a<t->total; a++, td++) {
+               td->loc2d[0]= td->loc[0];
+               td->loc2d[1]= td->loc[1];
+       }
 }
 
 /* ********************* UV ****************** */
@@ -2338,7 +2341,7 @@ static void createTransUVs(bContext *C, TransInfo *t)
        int propmode = t->flag & T_PROP_EDIT;
        int efa_s1,efa_s2,efa_s3,efa_s4;
 
-       EditMesh *em = G.editMesh;
+       EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
        EditFace *efa;
        
        if(is_uv_tface_editing_allowed()==0) return;
@@ -2472,7 +2475,7 @@ void flushTransUVs(TransInfo *t)
        TransData2D *td;
        int a, width, height;
        Object *ob= OBACT;
-       EditMesh *em = G.editMesh;
+       EditMesh *em = ((Mesh *)ob->data)->edit_mesh;
        float aspx, aspy, invx, invy;
 
        transform_aspect_ratio_tface_uv(&aspx, &aspy);
@@ -2575,6 +2578,8 @@ void flushTransIpoData(TransInfo *t)
        
        /* flush to 2d vector from internally used 3d vector */
        for (a=0, td= t->data2d; a<t->total; a++, td++) {
+               // FIXME: autosnap needs to be here...
+               
                /* we need to unapply the nla-scaling from the time in some situations */
                if (NLA_IPO_SCALED)
                        td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
@@ -2680,66 +2685,79 @@ static void posttrans_gpd_clean (bGPdata *gpd)
        }
 }
 
-/* Called by special_aftertrans_update to make sure selected keyframes replace
+/* Called during special_aftertrans_update to make sure selected keyframes replace
  * any other keyframes which may reside on that frame (that is not selected).
  */
-static void posttrans_ipo_clean (Ipo *ipo)
+static void posttrans_icu_clean (IpoCurve *icu)
 {
-       IpoCurve *icu;
-       int i;
+       float *selcache;        /* cache for frame numbers of selected frames (icu->totvert*sizeof(float)) */
+       int len, index, i;      /* number of frames in cache, item index */
        
-       /* delete any keyframes that occur on same frame as selected keyframe, but is not selected */
-       for (icu= ipo->curve.first; icu; icu= icu->next) {
-               float *selcache;        /* cache for frame numbers of selected frames (icu->totvert*sizeof(float)) */
-               int len, index;         /* number of frames in cache, item index */
-               
-               /* allocate memory for the cache */
-               // TODO: investigate using GHash for this instead?
-               if (icu->totvert == 0) 
-                       continue;
-               selcache= MEM_callocN(sizeof(float)*icu->totvert, "IcuSelFrameNums");
-               len= 0;
-               index= 0;
+       /* allocate memory for the cache */
+       // TODO: investigate using GHash for this instead?
+       if (icu->totvert == 0) 
+               return;
+       selcache= MEM_callocN(sizeof(float)*icu->totvert, "IcuSelFrameNums");
+       len= 0;
+       index= 0;
+       
+       /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting 
+        * as there is no guarantee what order the keyframes are exactly, even though 
+        * they have been sorted by time.
+        */
+        
+       /*      Loop 1: find selected keyframes   */
+       for (i = 0; i < icu->totvert; i++) {
+               BezTriple *bezt= &icu->bezt[i];
                
-               /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting 
-                * as there is no guarantee what order the keyframes are exactly, even though 
-                * they have been sorted by time.
-                */
-                
-               /*      Loop 1: find selected keyframes   */
+               if (BEZSELECTED(bezt)) {
+                       selcache[index]= bezt->vec[1][0];
+                       index++;
+                       len++;
+               }
+       }
+       
+       /* Loop 2: delete unselected keyframes on the same frames (if any keyframes were found) */
+       if (len) {
                for (i = 0; i < icu->totvert; i++) {
                        BezTriple *bezt= &icu->bezt[i];
                        
-                       if (BEZSELECTED(bezt)) {
-                               selcache[index]= bezt->vec[1][0];
-                               index++;
-                               len++;
-                       }
-               }
-               
-               /* Loop 2: delete unselected keyframes on the same frames (if any keyframes were found) */
-               if (len) {
-                       for (i = 0; i < icu->totvert; i++) {
-                               BezTriple *bezt= &icu->bezt[i];
-                               
-                               if (BEZSELECTED(bezt) == 0) {
-                                       /* check beztriple should be removed according to cache */
-                                       for (index= 0; index < len; index++) {
-                                               if (IS_EQ(bezt->vec[1][0], selcache[index])) {
-                                                       delete_icu_key(icu, i, 0);
-                                                       break;
-                                               }
-                                               else if (bezt->vec[1][0] > selcache[index])
-                                                       break;
+                       if (BEZSELECTED(bezt) == 0) {
+                               /* check beztriple should be removed according to cache */
+                               for (index= 0; index < len; index++) {
+                                       if (IS_EQ(bezt->vec[1][0], selcache[index])) {
+                                               delete_icu_key(icu, i, 0);
+                                               break;
                                        }
+                                       else if (bezt->vec[1][0] > selcache[index])
+                                               break;
                                }
                        }
-                       
-                       testhandles_ipocurve(icu);
                }
                
-               /* free cache */
-               MEM_freeN(selcache);
+               testhandles_ipocurve(icu);
+       }
+       
+       /* free cache */
+       MEM_freeN(selcache);
+}
+
+/* Called by special_aftertrans_update to make sure selected keyframes replace
+ * any other keyframes which may reside on that frame (that is not selected).
+ * remake_action_ipos should have already been called 
+ */
+static void posttrans_ipo_clean (Ipo *ipo)
+{
+       IpoCurve *icu;
+       
+       if (ipo == NULL)
+               return;
+       
+       /* loop through relevant data, removing keyframes from the ipocurves
+        *      - all keyframes are converted in/out of global time 
+        */
+       for (icu= ipo->curve.first; icu; icu= icu->next) {
+               posttrans_icu_clean(icu);
        }
 }
 
@@ -2754,7 +2772,7 @@ static void posttrans_action_clean (bAnimContext *ac, bAction *act)
        int filter;
        
        /* filter data */
-       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
+       filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ONLYICU);
        ANIM_animdata_filter(&anim_data, filter, act, ANIMCONT_ACTION);
        
        /* loop through relevant data, removing keyframes from the ipo-blocks that were attached 
@@ -2764,107 +2782,18 @@ static void posttrans_action_clean (bAnimContext *ac, bAction *act)
                Object *nob= ANIM_nla_mapping_get(ac, ale);
                
                if (nob) {
-                       ANIM_nla_mapping_apply(nob, ale->key_data, 0, 1); 
-                       posttrans_ipo_clean(ale->key_data);
-                       ANIM_nla_mapping_apply(nob, ale->key_data, 1, 1);
+                       ANIM_nla_mapping_apply_ipocurve(nob, ale->key_data, 0, 1); 
+                       posttrans_icu_clean(ale->key_data);
+                       ANIM_nla_mapping_apply_ipocurve(nob, ale->key_data, 1, 1);
                }
                else 
-                       posttrans_ipo_clean(ale->key_data);
+                       posttrans_icu_clean(ale->key_data);
        }
        
        /* free temp data */
        BLI_freelistN(&anim_data);
 }
 
-/* Called by special_aftertrans_update to make sure selected keyframes replace
- * any other keyframes which may reside on that frame (that is not selected).
- * remake_all_ipos should have already been called 
- */
-static void posttrans_nla_clean (TransInfo *t)
-{
-#if 0 // TRANSFORM_FIX_ME
-       Base *base;
-       Object *ob;
-       bActionStrip *strip;
-       bActionChannel *achan;
-       bConstraintChannel *conchan;
-       float cfra;
-       char side;
-       int i;
-       
-       /* which side of the current frame should be allowed */
-       if (t->mode == TFM_TIME_EXTEND) {
-               /* only side on which mouse is gets transformed */
-               float xmouse, ymouse;
-               
-               areamouseco_to_ipoco(G.v2d, t->imval, &xmouse, &ymouse);
-               side = (xmouse > CFRA) ? 'R' : 'L';
-       }
-       else {
-               /* normal transform - both sides of current frame are considered */
-               side = 'B';
-       }
-       
-       /* only affect keyframes */
-       for (base=G.scene->base.first; base; base=base->next) {
-               ob= base->object;
-               
-               /* Check object ipos */
-               i= count_ipo_keys(ob->ipo, side, (float)CFRA);
-               if (i) posttrans_ipo_clean(ob->ipo);
-               
-               /* Check object constraint ipos */
-               for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next) {
-                       i= count_ipo_keys(conchan->ipo, side, (float)CFRA);     
-                       if (i) posttrans_ipo_clean(conchan->ipo);
-               }
-               
-               /* skip actions and nlastrips if object is collapsed */
-               if (ob->nlaflag & OB_NLA_COLLAPSED)
-                       continue;
-               
-               /* Check action ipos */
-               if (ob->action) {
-                       /* exclude if strip is selected too */
-                       for (strip=ob->nlastrips.first; strip; strip=strip->next) {
-                               if (strip->flag & ACTSTRIP_SELECT) {
-                                       if (strip->act == ob->action)
-                                               break;
-                               }
-                       }
-                       if (strip==NULL) {
-                               cfra = get_action_frame(ob, (float)CFRA);
-                               
-                               for (achan=ob->action->chanbase.first; achan; achan=achan->next) {
-                                       if (EDITABLE_ACHAN(achan)) {
-                                               i= count_ipo_keys(achan->ipo, side, cfra);
-                                               if (i) {
-                                                       actstrip_map_ipo_keys(ob, achan->ipo, 0, 1); 
-                                                       posttrans_ipo_clean(achan->ipo);
-                                                       actstrip_map_ipo_keys(ob, achan->ipo, 1, 1);
-                                               }
-                                               
-                                               /* Check action constraint ipos */
-                                               if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
-                                                       for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
-                                                               if (EDITABLE_CONCHAN(conchan)) {
-                                                                       i = count_ipo_keys(conchan->ipo, side, cfra);
-                                                                       if (i) {
-                                                                               actstrip_map_ipo_keys(ob, conchan->ipo, 0, 1); 
-                                                                               posttrans_ipo_clean(conchan->ipo);
-                                                                               actstrip_map_ipo_keys(ob, conchan->ipo, 1, 1);
-                                                                       }
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-                       }               
-               }
-       }
-#endif
-}
-
 /* ----------------------------- */
 
 /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
@@ -2881,27 +2810,24 @@ static short FrameOnMouseSide(char side, float frame, float cframe)
 }
 
 /* fully select selected beztriples, but only include if it's on the right side of cfra */
-static int count_ipo_keys(Ipo *ipo, char side, float cfra)
+static int count_icu_keys(IpoCurve *icu, char side, float cfra)
 {
-       IpoCurve *icu;
        BezTriple *bezt;
        int i, count = 0;
        
-       if (ipo == NULL)
+       if (icu == NULL)
                return count;
        
        /* only include points that occur on the right side of cfra */
-       for (icu= ipo->curve.first; icu; icu= icu->next) {
-               for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
-                       if (bezt->f2 & SELECT) {
-                               /* fully select the other two keys */
-                               bezt->f1 |= SELECT;
-                               bezt->f3 |= SELECT;
-                               
-                               /* increment by 3, as there are 3 points (3 * x-coordinates) that need transform */
-                               if (FrameOnMouseSide(side, bezt->vec[1][0], cfra))
-                                       count += 3;
-                       }
+       for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
+               if (bezt->f2 & SELECT) {
+                       /* fully select the other two keys */
+                       bezt->f1 |= SELECT;
+                       bezt->f3 |= SELECT;
+                       
+                       /* increment by 3, as there are 3 points (3 * x-coordinates) that need transform */
+                       if (FrameOnMouseSide(side, bezt->vec[1][0], cfra))
+                               count += 3;
                }
        }
        
@@ -2944,38 +2870,35 @@ static void TimeToTransData(TransData *td, float *time, Object *ob)
 
 /* This function advances the address to which td points to, so it must return
  * the new address so that the next time new transform data is added, it doesn't
- * overwrite the existing ones...  i.e.   td = IpoToTransData(td, ipo, ob, side, cfra);
+ * overwrite the existing ones...  i.e.   td = IcuToTransData(td, icu, ob, side, cfra);
  *
  * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
  * on the named side are used. 
  */
-static TransData *IpoToTransData(TransData *td, Ipo *ipo, Object *ob, char side, float cfra)
+static TransData *IcuToTransData(TransData *td, IpoCurve *icu, Object *ob, char side, float cfra)
 {
-       IpoCurve *icu;
        BezTriple *bezt;
        int i;
        
-       if (ipo == NULL)
+       if (icu == NULL)
                return td;
-       
-       for (icu= ipo->curve.first; icu; icu= icu->next) {
-               for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
-                       /* only add selected keyframes (for now, proportional edit is not enabled) */
-                       if (BEZSELECTED(bezt)) {
-                               /* only add if on the right 'side' of the current frame */
-                               if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
-                                       /* each control point needs to be added separetely */
-                                       TimeToTransData(td, bezt->vec[0], ob);
-                                       td++;
-                                       
-                                       TimeToTransData(td, bezt->vec[1], ob);
-                                       td++;
-                                       
-                                       TimeToTransData(td, bezt->vec[2], ob);
-                                       td++;
-                               }
-                       }       
-               }
+               
+       for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
+               /* only add selected keyframes (for now, proportional edit is not enabled) */
+               if (BEZSELECTED(bezt)) {
+                       /* only add if on the right 'side' of the current frame */
+                       if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
+                               /* each control point needs to be added separetely */
+                               TimeToTransData(td, bezt->vec[0], ob);
+                               td++;
+                               
+                               TimeToTransData(td, bezt->vec[1], ob);
+                               td++;
+                               
+                               TimeToTransData(td, bezt->vec[2], ob);
+                               td++;
+                       }
+               }       
        }
        
        return td;
@@ -3062,7 +2985,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
        if (ac.datatype == ANIMCONT_GPENCIL)
                filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT);
        else
-               filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
+               filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ONLYICU);
        ANIM_animdata_filter(&anim_data, filter, ac.data, ac.datatype);
                
        /* which side of the current frame should be allowed */
@@ -3093,7 +3016,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
                //if (ale->type == ANIMTYPE_GPLAYER)
                //      count += count_gplayer_frames(ale->data, side, cfra);
                //else
-                       count += count_ipo_keys(ale->key_data, side, cfra);
+                       count += count_icu_keys(ale->key_data, side, cfra);
        }
        
        /* stop if trying to build list if nothing selected */
@@ -3134,7 +3057,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
                //}
                //else {
                        Object *nob= ANIM_nla_mapping_get(&ac, ale);
-                       Ipo *ipo= (Ipo *)ale->key_data;
+                       IpoCurve *icu= (IpoCurve *)ale->key_data;
                        
                        /* convert current-frame to action-time (slightly less accurate, espcially under
                         * higher scaling ratios, but is faster than converting all points) 
@@ -3144,7 +3067,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
                        else
                                cfra = (float)CFRA;
                        
-                       td= IpoToTransData(td, ipo, nob, side, cfra);
+                       td= IcuToTransData(td, icu, nob, side, cfra);
                //}
        }
        
@@ -3171,162 +3094,6 @@ static void createTransActionData(bContext *C, TransInfo *t)
        BLI_freelistN(&anim_data);
 }
 
-static void createTransNlaData(bContext *C, TransInfo *t)
-{
-       // TRANSFORM_FIX_ME
-#if 0
-       Base *base;
-       bActionStrip *strip;
-       bActionChannel *achan;
-       bConstraintChannel *conchan;
-       
-       TransData *td = NULL;
-       int count=0, i;
-       float cfra;
-       char side;
-       
-       /* which side of the current frame should be allowed */
-       if (t->mode == TFM_TIME_EXTEND) {
-               /* only side on which mouse is gets transformed */
-               float xmouse, ymouse;
-               
-               areamouseco_to_ipoco(G.v2d, t->imval, &xmouse, &ymouse);
-               side = (xmouse > CFRA) ? 'R' : 'L';
-       }
-       else {
-               /* normal transform - both sides of current frame are considered */
-               side = 'B';
-       }
-       
-       /* Ensure that partial selections result in beztriple selections */
-       for (base=G.scene->base.first; base; base=base->next) {
-               /* Check object ipos */
-               i= count_ipo_keys(base->object->ipo, side, (float)CFRA);
-               if (i) base->flag |= BA_HAS_RECALC_OB;
-               count += i;
-               
-               /* Check object constraint ipos */
-               for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
-                       count += count_ipo_keys(conchan->ipo, side, (float)CFRA);                       
-               
-               /* skip actions and nlastrips if object is collapsed */
-               if (base->object->nlaflag & OB_NLA_COLLAPSED)
-                       continue;
-               
-               /* Check action ipos */
-               if (base->object->action) {
-                       /* exclude if strip is selected too */
-                       for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
-                               if (strip->flag & ACTSTRIP_SELECT) {
-                                       if (strip->act == base->object->action)
-                                               break;
-                               }
-                       }
-                       if (strip==NULL) {
-                               cfra = get_action_frame(base->object, (float)CFRA);
-                               
-                               for (achan=base->object->action->chanbase.first; achan; achan=achan->next) {
-                                       if (EDITABLE_ACHAN(achan)) {
-                                               i= count_ipo_keys(achan->ipo, side, cfra);
-                                               if (i) base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
-                                               count += i;
-                                               
-                                               /* Check action constraint ipos */
-                                               if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
-                                                       for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
-                                                               if (EDITABLE_CONCHAN(conchan))
-                                                                       count += count_ipo_keys(conchan->ipo, side, cfra);
-                                                       }
-                                               }
-                                       }
-                               }
-                       }               
-               }
-               
-               /* Check nlastrips */
-               for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
-                       if (strip->flag & ACTSTRIP_SELECT) {
-                               base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
-                               
-                               if (FrameOnMouseSide(side, strip->start, (float)CFRA)) count++;
-                               if (FrameOnMouseSide(side, strip->end, (float)CFRA)) count++;
-                       }
-               }
-       }
-       
-       /* If nothing is selected, bail out */
-       if (count == 0)
-               return;
-       
-       /* allocate memory for data */
-       t->total= count;
-       t->data= MEM_callocN(t->total*sizeof(TransData), "TransData (NLA Editor)");
-       
-       /* build the transdata structure */
-       td= t->data;
-       for (base=G.scene->base.first; base; base=base->next) {
-               /* Manipulate object ipos */
-               /*      - no scaling of keyframe times is allowed here  */
-               td= IpoToTransData(td, base->object->ipo, NULL, side, (float)CFRA);
-               
-               /* Manipulate object constraint ipos */
-               /*      - no scaling of keyframe times is allowed here  */
-               for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
-                       td= IpoToTransData(td, conchan->ipo, NULL, side, (float)CFRA);
-               
-               /* skip actions and nlastrips if object collapsed */
-               if (base->object->nlaflag & OB_NLA_COLLAPSED)
-                       continue;
-                       
-               /* Manipulate action ipos */
-               if (base->object->action) {
-                       /* exclude if strip that active action belongs to is selected too */
-                       for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
-                               if (strip->flag & ACTSTRIP_SELECT) {
-                                       if (strip->act == base->object->action)
-                                               break;
-                               }
-                       }
-                       
-                       /* can include if no strip found */
-                       if (strip==NULL) {
-                               cfra = get_action_frame(base->object, (float)CFRA);
-                               
-                               for (achan=base->object->action->chanbase.first; achan; achan=achan->next) {
-                                       if (EDITABLE_ACHAN(achan)) {
-                                               td= IpoToTransData(td, achan->ipo, base->object, side, cfra);
-                                               
-                                               /* Manipulate action constraint ipos */
-                                               if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
-                                                       for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
-                                                               if (EDITABLE_CONCHAN(conchan))
-                                                                       td= IpoToTransData(td, conchan->ipo, base->object, side, cfra);
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-               
-               /* Manipulate nlastrips */
-               for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
-                       if (strip->flag & ACTSTRIP_SELECT) {
-                               /* first TransData is the start, second is the end */
-                               if (FrameOnMouseSide(side, strip->start, (float)CFRA)) {
-                                       td->val = &strip->start;
-                                       td->ival = strip->start;
-                                       td++;
-                               }
-                               if (FrameOnMouseSide(side, strip->end, (float)CFRA)) {
-                                       td->val = &strip->end;
-                                       td->ival = strip->end;
-                                       td++;
-                               }
-                       }
-               }
-       }
-#endif
-}
 
 /* **************** IpoKey stuff, for Object TransData ********** */
 
@@ -3953,13 +3720,12 @@ static void recalc_all_ipos(void)
 void special_aftertrans_update(TransInfo *t)
 {
        Object *ob;
-       Base *base;
-       short redrawipo=0, resetslowpar=1;
+//     short redrawipo=0, resetslowpar=1;
        int cancelled= (t->state == TRANS_CANCEL);
        short duplicate= (t->undostr && strstr(t->undostr, "Duplicate")) ? 1 : 0;
        
        if (t->spacetype==SPACE_VIEW3D) {
-               if (G.obedit) {
+               if (t->obedit) {
                        if (cancelled==0) {
 #if 0 // TRANSFORM_FIX_ME
                                EM_automerge(1);
@@ -3974,23 +3740,27 @@ void special_aftertrans_update(TransInfo *t)
        
        if (t->spacetype == SPACE_ACTION) {
                SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
-               Scene *scene= NULL;
+               Scene *scene;
                bAnimContext ac;
                
-               /* determine what type of data we are operating on */
-               if (ANIM_animdata_get_context(t->context, &ac) == 0) {
-                       printf("space action transform -> special aftertrans exit. no context \n"); // XXX
-                       return;
-               }
+               /* initialise relevant anim-context 'context' data from TransInfo data */
+                       /* NOTE: sync this with the code in ANIM_animdata_get_context() */
+               memset(&ac, 0, sizeof(bAnimContext));
+               
+               scene= ac.scene= t->scene;
+               ob= ac.obact= OBACT;
+               ac.sa= t->sa;
+               ac.ar= t->ar;
+               ac.spacetype= (t->sa)? t->sa->spacetype : 0;
+               ac.regiontype= (t->ar)? t->ar->regiontype : 0;
                
-               /* get pointers to useful data */
-               scene= ac.scene;
-               ob = OBACT;
+               if (ANIM_animdata_context_getdata(&ac) == 0)
+                       return;
                
                if (ac.datatype == ANIMCONT_DOPESHEET) {
                        ListBase anim_data = {NULL, NULL};
                        bAnimListElem *ale;
-                       short filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
+                       short filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ONLYICU);
                        
                        /* get channels to work on */
                        ANIM_animdata_filter(&anim_data, filter, ac.data, ac.datatype);
@@ -3998,19 +3768,18 @@ void special_aftertrans_update(TransInfo *t)
                        /* these should all be ipo-blocks */
                        for (ale= anim_data.first; ale; ale= ale->next) {
                                Object *nob= ANIM_nla_mapping_get(&ac, ale);
-                               Ipo *ipo= ale->key_data;
-                               IpoCurve *icu;
+                               IpoCurve *icu= (IpoCurve *)ale->key_data;
                                
                                if ( (saction->flag & SACTION_NOTRANSKEYCULL)==0 && 
                                     ((cancelled == 0) || (duplicate)) )
                                {
                                        if (nob) {
-                                               ANIM_nla_mapping_apply(nob, ipo, 0, 1); 
-                                               posttrans_ipo_clean(ipo);
-                                               ANIM_nla_mapping_apply(nob, ipo, 1, 1);
+                                               ANIM_nla_mapping_apply_ipocurve(nob, icu, 0, 1); 
+                                               posttrans_icu_clean(icu);
+                                               ANIM_nla_mapping_apply_ipocurve(nob, icu, 1, 1);
                                        }
                                        else
-                                               posttrans_ipo_clean(ipo);
+                                               posttrans_icu_clean(icu);
                                }
                        }
                        
@@ -4041,8 +3810,6 @@ void special_aftertrans_update(TransInfo *t)
                        Key *key= (Key *)ac.data;
                        
                        if (key->ipo) {
-                               IpoCurve *icu;
-                               
                                if ( (saction->flag & SACTION_NOTRANSKEYCULL)==0 && 
                                     ((cancelled == 0) || (duplicate)) )
                                {
@@ -4115,12 +3882,12 @@ void special_aftertrans_update(TransInfo *t)
                if (G.sipo->blocktype==ID_SEQ)
                        resetslowpar= 0;
        }
-       else if (G.obedit) {
+       else if (t->obedit) {
                if (t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
                        allqueue(REDRAWBUTSEDIT, 0);
                
                /* table needs to be created for each edit command, since vertices can move etc */
-               mesh_octree_table(G.obedit, NULL, 'e');
+               mesh_octree_table(t->obedit, NULL, 'e');
        }
        else if ((t->flag & T_POSE) && (t->poseobj)) {
                bArmature *arm;
@@ -4353,6 +4120,47 @@ static void createTransObject(bContext *C, TransInfo *t)
        }
 }
 
+/* transcribe given node into TransData2D for Transforming */
+static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node)
+// static void NodeToTransData(bContext *C, TransInfo *t, TransData2D *td, bNode *node) 
+{
+       td2d->loc[0] = node->locx; /* hold original location */
+       td2d->loc[1] = node->locy;
+       td2d->loc[2] = 0.0f;
+       td2d->loc2d = &node->locx; /* current location */
+
+       td->flag = 0;
+       td->loc = td2d->loc;
+       VECCOPY(td->center, td->loc);
+       VECCOPY(td->iloc, td->loc);
+
+       memset(td->axismtx, 0, sizeof(td->axismtx));
+       td->axismtx[2][2] = 1.0f;
+
+       td->ext= NULL; td->tdi= NULL; td->val= NULL;
+
+       td->flag |= TD_SELECTED;
+       td->dist= 0.0;
+
+       Mat3One(td->mtx);
+       Mat3One(td->smtx);
+}
+
+void createTransNodeData(bContext *C, TransInfo *t)
+{
+       TransData *td;
+       TransData2D *td2d;
+       
+       CTX_DATA_COUNT(C, selected_nodes, t->total)
+       
+       td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransNode TransData");
+       td2d = t->data2d = MEM_callocN(t->total*sizeof(TransData2D), "TransNode TransData2D");
+       
+       CTX_DATA_BEGIN(C, bNode *, selnode, selected_nodes)
+               NodeToTransData(td++, td2d++, selnode);
+       CTX_DATA_END
+}
+
 void createTransData(bContext *C, TransInfo *t) 
 {
        Scene *scene = CTX_data_scene(C);
@@ -4391,7 +4199,8 @@ void createTransData(bContext *C, TransInfo *t)
        }
        else if (t->spacetype == SPACE_NLA) {
                t->flag |= T_POINTS|T_2D_EDIT;
-               createTransNlaData(C, t);
+               // TRANSFORM_FIX_ME
+               //createTransNlaData(C, t);
        }
        else if (t->spacetype == SPACE_IPO) {
                t->flag |= T_POINTS|T_2D_EDIT;
@@ -4402,23 +4211,25 @@ void createTransData(bContext *C, TransInfo *t)
                        sort_trans_data_dist(t);
                }
        }
-       else if (0) { // // TRANSFORM_FIX_ME (G.obedit) {
-               Object *obedit = NULL; // TRANSFORM_FIX_ME
-               
+       else if(t->spacetype == SPACE_NODE) {
+               t->flag |= T_2D_EDIT|T_POINTS;
+               createTransNodeData(C, t);
+       }
+       else if (t->obedit) {
                t->ext = NULL;
-               if (obedit->type == OB_MESH) {
+               if (t->obedit->type == OB_MESH) {
                        createTransEditVerts(C, t);     
                }
-               else if ELEM(obedit->type, OB_CURVE, OB_SURF) {
+               else if ELEM(t->obedit->type, OB_CURVE, OB_SURF) {
                        createTransCurveVerts(C, t);
                }
-               else if (obedit->type==OB_LATTICE) {
+               else if (t->obedit->type==OB_LATTICE) {
                        createTransLatticeVerts(C, t);
                }
-               else if (obedit->type==OB_MBALL) {
+               else if (t->obedit->type==OB_MBALL) {
                        createTransMBallVerts(C, t);
                }
-               else if (obedit->type==OB_ARMATURE) {
+               else if (t->obedit->type==OB_ARMATURE) {
                        t->flag &= ~T_PROP_EDIT;
                        createTransArmatureVerts(C, t);
                }                                                       
@@ -4427,7 +4238,7 @@ void createTransData(bContext *C, TransInfo *t)
                }
 
                if(t->data && t->flag & T_PROP_EDIT) {
-                       if (ELEM(obedit->type, OB_CURVE, OB_MESH)) {
+                       if (ELEM(t->obedit->type, OB_CURVE, OB_MESH)) {
                                sort_trans_data(t);     // makes selected become first in array
                                set_prop_dist(t, 0);
                                sort_trans_data_dist(t);