Removal of old transform() <sob> part one.
[blender.git] / source / blender / src / editobject.c
index 6b9344a5014b64835ae817ba0963d0254473d65d..89f21c471c572dcc0f7d589c496f11804a5dc1e0 100644 (file)
@@ -47,7 +47,6 @@
 #include <unistd.h>
 #else
 #include <io.h>
-#include "BLI_winstuff.h"
 #endif
 #include "MEM_guardedalloc.h"
 #include "PIL_time.h"
 
 #include "IMB_imbuf_types.h"
 
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
 #include "DNA_camera_types.h"
+#include "DNA_constraint_types.h"
 #include "DNA_curve_types.h"
 #include "DNA_effect_types.h"
 #include "DNA_ika_types.h"
@@ -66,6 +68,7 @@
 #include "DNA_key_types.h"
 #include "DNA_lamp_types.h"
 #include "DNA_lattice_types.h"
+#include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_meta_types.h"
 #include "DNA_userdef_types.h"
 #include "DNA_property_types.h"
 #include "DNA_vfont_types.h"
-#include "DNA_constraint_types.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
 #include "BLI_editVert.h"
 #include "BLI_ghash.h"
 
-#include "BKE_nla.h"
+#include "BKE_constraint.h"
+#include "BKE_action.h"
+#include "BKE_armature.h"
 #include "BKE_utildefines.h"
 #include "BKE_anim.h"
 #include "BKE_blender.h"
+#include "BKE_booleanops.h"
 #include "BKE_curve.h"
 #include "BKE_displist.h"
+#include "BKE_DerivedMesh.h"
 #include "BKE_effect.h"
 #include "BKE_font.h"
 #include "BKE_global.h"
 #include "BKE_material.h"
 #include "BKE_mball.h"
 #include "BKE_mesh.h"
+#include "BKE_nla.h"
 #include "BKE_object.h"
 #include "BKE_property.h"
 #include "BKE_sca.h"
 #include "BKE_scene.h"
+#include "BKE_softbody.h"
 #include "BKE_subsurf.h"
 #include "BKE_texture.h"
-#include "BKE_booleanops.h"
+#include "BKE_utildefines.h"
 
 #include "BIF_gl.h"
 #include "BIF_graphics.h"
 #include "BIF_space.h"
 #include "BIF_toets.h"
 #include "BIF_butspace.h"
+#include "BIF_editconstraint.h"
 #include "BIF_editdeform.h"
 #include "BIF_editfont.h"
 #include "BIF_editika.h"
 #include "BSE_editipo.h"
 #include "BSE_filesel.h"       /* For activate_databrowse() */
 #include "BSE_view.h"
+#include "BSE_drawview.h"
 #include "BSE_trans_types.h"
 #include "BSE_editipo_types.h"
 
 #include "BDR_editobject.h"
 #include "BDR_drawobject.h"
 #include "BDR_editcurve.h"
+#include "BDR_unwrapper.h"
 
-#include "render.h"
 #include <time.h>
 #include "mydevice.h"
 #include "nla.h"
 
 #include "blendef.h"
 
-#include "BKE_constraint.h"
-#include "BIF_editconstraint.h"
+#include "BIF_transform.h"
 
-#include "BKE_action.h"
-#include "DNA_action_types.h"
-#include "BKE_armature.h"
-#include "DNA_armature_types.h"
 #include "BIF_poseobject.h"
 
 /*  extern Lattice *copy_lattice(Lattice *lt); */
@@ -185,7 +190,14 @@ float centre[3], centroid[3];
 
 void mirrormenu(void);
 
-void add_object_draw(int type) /* for toolbox */
+/* local prototypes -------------*/
+int pose_flags_reset_done(Object *); /* used in transform_generic.c */
+void figure_bone_nocalc(Object *); /* used in transform.c */
+void figure_pose_updating(void); /* used in transform.c */
+void constline_callback(void);  /* used in drawview.c */
+/* --------------------------------- */
+
+void add_object_draw(int type) /* for toolbox or menus, only non-editmode stuff */
 {
        Object *ob;
        
@@ -193,23 +205,50 @@ void add_object_draw(int type)    /* for toolbox */
        setcursor_space(SPACE_VIEW3D, CURSOR_STD);
 
        if ELEM3(curarea->spacetype, SPACE_VIEW3D, SPACE_BUTS, SPACE_INFO) {
-               if (G.obedit) exit_editmode(1);
+               if (G.obedit) exit_editmode(2); // freedata, and undo
                ob= add_object(type);
                base_init_from_view3d(BASACT, G.vd);
-
+               
+               /* only undo pushes on objects without editmode... */
+               if(type==OB_EMPTY) BIF_undo_push("Add Empty");
+               else if(type==OB_LAMP) {
+                       BIF_undo_push("Add Lamp");
+                       if(G.vd->drawtype == OB_SHADED) reshadeall_displist();
+               }
+               else if(type==OB_LATTICE) BIF_undo_push("Add Lattice");
+               else if(type==OB_CAMERA) BIF_undo_push("Add Camera");
+               
                allqueue(REDRAWVIEW3D, 0);
        }
 
-       redraw_test_buttons(BASACT);
+       redraw_test_buttons(OBACT);
 
        allqueue(REDRAWALL, 0);
 
        deselect_all_area_oops();
        set_select_flag_oops();
        allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
+}
+
+void add_objectLamp(short type)
+{
+       Lamp *la;
+
+       /* this function also comes from an info window */
+       if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return;
+       
+       if(G.obedit==0) {
+               add_object_draw(OB_LAMP);
+               base_init_from_view3d(BASACT, G.vd);
+       }
+       
+       la = BASACT->object->data;
+       la->type = type;        
 
+       allqueue(REDRAWALL, 0);
 }
 
+// really bad, doesnt do constraints, that has been coded in test_scene_constraints();
 void free_and_unlink_base(Base *base)
 {
        if (base==BASACT)
@@ -223,20 +262,19 @@ void free_and_unlink_base(Base *base)
 void delete_obj(int ok)
 {
        Base *base;
-extern int undo_push(char *);
+       int islamp= 0;
        
        if(G.obpose) return;
        if(G.obedit) return;
        if(G.scene->id.lib) return;
        
-//if (undo_push("Erase")) return;      
-       
        base= FIRSTBASE;
        while(base) {
                Base *nbase= base->next;
 
                if TESTBASE(base) {
-                       if(ok==0 &&  (ok=okee("ERASE SELECTED"))==0) return;
+                       if(ok==0 &&  (ok=okee("Erase selected"))==0) return;
+                       if(base->object->type==OB_LAMP) islamp= 1;
                        
                        free_and_unlink_base(base);
                }
@@ -248,17 +286,399 @@ extern int undo_push(char *);
        G.f &= ~(G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT);
        setcursor_space(SPACE_VIEW3D, CURSOR_STD);
        
-       test_scene_constraints();
+       if(islamp && G.vd->drawtype==OB_SHADED) reshadeall_displist();
+
+       test_scene_constraints(); // do because of delete obj
+       
        allqueue(REDRAWVIEW3D, 0);
-       redraw_test_buttons(BASACT);
+       redraw_test_buttons(OBACT);
        allqueue (REDRAWACTION, 0);
        allqueue(REDRAWIPO, 0);
        allqueue(REDRAWDATASELECT, 0);
        allqueue(REDRAWOOPS, 0);
        allqueue(REDRAWACTION, 0);
        allqueue(REDRAWNLA, 0);
+       
+       BIF_undo_push("Delete object(s)");
+}
+
+static int return_editmesh_indexar(int **indexar, float *cent)
+{
+       EditMesh *em = G.editMesh;
+       EditVert *eve;
+       int *index, nr, totvert=0;
+       
+       for(eve= em->verts.first; eve; eve= eve->next) {
+               if(eve->f & SELECT) totvert++;
+       }
+       if(totvert==0) return 0;
+       
+       *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
+       nr= 0;
+       cent[0]= cent[1]= cent[2]= 0.0;
+       
+       for(eve= em->verts.first; eve; eve= eve->next) {
+               if(eve->f & SELECT) {
+                       *index= nr; index++;
+                       VecAddf(cent, cent, eve->co);
+               }
+               nr++;
+       }
+       
+       VecMulf(cent, 1.0/(float)totvert);
+       
+       return totvert;
+}
+
+static void select_editmesh_hook(ObHook *hook)
+{
+       EditMesh *em = G.editMesh;
+       EditVert *eve;
+       int index=0, nr=0;
+       
+       for(eve= em->verts.first; eve; eve= eve->next, nr++) {
+               if(nr==hook->indexar[index]) {
+                       eve->f |= SELECT;
+                       if(index < hook->totindex-1) index++;
+               }
+       }
+       EM_select_flush();
+}
+
+static int return_editlattice_indexar(int **indexar, float *cent)
+{
+       BPoint *bp;
+       int *index, nr, totvert=0, a;
+       
+       // count
+       a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+       bp= editLatt->def;
+       while(a--) {
+               if(bp->f1 & SELECT) {
+                       if(bp->hide==0) totvert++;
+               }
+               bp++;
+       }
+
+       if(totvert==0) return 0;
+       
+       *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
+       nr= 0;
+       cent[0]= cent[1]= cent[2]= 0.0;
+       
+       a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+       bp= editLatt->def;
+       while(a--) {
+               if(bp->f1 & SELECT) {
+                       if(bp->hide==0) {
+                               *index= nr; index++;
+                               VecAddf(cent, cent, bp->vec);
+                       }
+               }
+               bp++;
+               nr++;
+       }
+       
+       VecMulf(cent, 1.0/(float)totvert);
+       
+       return totvert;
+}
+
+static void select_editlattice_hook(ObHook *hook)
+{
+       BPoint *bp;
+       int index=0, nr=0, a;
+       
+       // count
+       a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+       bp= editLatt->def;
+       while(a--) {
+               if(hook->indexar[index]==nr) {
+                       bp->f1 |= SELECT;
+                       if(index < hook->totindex-1) index++;
+               }
+               nr++;
+               bp++;
+       }
+}
+
+static int return_editcurve_indexar(int **indexar, float *cent)
+{
+       extern ListBase editNurb;
+       Nurb *nu;
+       BPoint *bp;
+       BezTriple *bezt;
+       int *index, a, nr, totvert=0;
+       
+       for(nu= editNurb.first; nu; nu= nu->next) {
+               if((nu->type & 7)==CU_BEZIER) {
+                       bezt= nu->bezt;
+                       a= nu->pntsu;
+                       while(a--) {
+                               if(bezt->f1 & SELECT) totvert++;
+                               if(bezt->f2 & SELECT) totvert++;
+                               if(bezt->f3 & SELECT) totvert++;
+                               bezt++;
+                       }
+               }
+               else {
+                       bp= nu->bp;
+                       a= nu->pntsu*nu->pntsv;
+                       while(a--) {
+                               if(bp->f1 & SELECT) totvert++;
+                               bp++;
+                       }
+               }
+       }
+       if(totvert==0) return 0;
+       
+       *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
+       nr= 0;
+       cent[0]= cent[1]= cent[2]= 0.0;
+       
+       for(nu= editNurb.first; nu; nu= nu->next) {
+               if((nu->type & 7)==CU_BEZIER) {
+                       bezt= nu->bezt;
+                       a= nu->pntsu;
+                       while(a--) {
+                               if(bezt->f1 & SELECT) {
+                                       *index= nr; index++;
+                                       VecAddf(cent, cent, bezt->vec[0]);
+                               }
+                               nr++;
+                               if(bezt->f2 & SELECT) {
+                                       *index= nr; index++;
+                                       VecAddf(cent, cent, bezt->vec[1]);
+                               }
+                               nr++;
+                               if(bezt->f3 & SELECT) {
+                                       *index= nr; index++;
+                                       VecAddf(cent, cent, bezt->vec[2]);
+                               }
+                               nr++;
+                               bezt++;
+                       }
+               }
+               else {
+                       bp= nu->bp;
+                       a= nu->pntsu*nu->pntsv;
+                       while(a--) {
+                               if(bp->f1 & SELECT) {
+                                       *index= nr; index++;
+                                       VecAddf(cent, cent, bp->vec);
+                               }
+                               nr++;
+                               bp++;
+                       }
+               }
+       }
+       
+       VecMulf(cent, 1.0/(float)totvert);
+       
+       return totvert;
+}
+
+static void select_editcurve_hook(ObHook *hook)
+{
+       extern ListBase editNurb;
+       Nurb *nu;
+       BPoint *bp;
+       BezTriple *bezt;
+       int index=0, a, nr=0;
+       
+       for(nu= editNurb.first; nu; nu= nu->next) {
+               if((nu->type & 7)==CU_BEZIER) {
+                       bezt= nu->bezt;
+                       a= nu->pntsu;
+                       while(a--) {
+                               if(nr == hook->indexar[index]) {
+                                       bezt->f1 |= SELECT;
+                                       if(index<hook->totindex-1) index++;
+                               }
+                               nr++;
+                               if(nr == hook->indexar[index]) {
+                                       bezt->f2 |= SELECT;
+                                       if(index<hook->totindex-1) index++;
+                               }
+                               nr++;
+                               if(nr == hook->indexar[index]) {
+                                       bezt->f3 |= SELECT;
+                                       if(index<hook->totindex-1) index++;
+                               }
+                               nr++;
+
+                               bezt++;
+                       }
+               }
+               else {
+                       bp= nu->bp;
+                       a= nu->pntsu*nu->pntsv;
+                       while(a--) {
+                               if(nr == hook->indexar[index]) {
+                                       bp->f1 |= SELECT;
+                                       if(index<hook->totindex-1) index++;
+                               }
+                               nr++;
+                               bp++;
+                       }
+               }
+       }
 }
 
+void add_hook(void)
+{
+       Object *ob=NULL;
+       ObHook *hook=NULL;
+       float cent[3];
+       int tot=0, *indexar, mode;
+
+       if(G.obedit==NULL) return;
+       
+       if(G.obedit->hooks.first)
+               mode= pupmenu("Hooks %t|Add Hook, To New Empty %x1|Add Hook, To Selected Object %x2|Remove... %x3|Reassign... %x4|Select... %x5|Clear Offset...%x6");
+       else
+               mode= pupmenu("Hooks %t|Add, New Empty %x1|Add, To Selected Object %x2");
+
+       if(mode<1) return;
+       
+       /* preconditions */
+
+       if(mode==2) { // selected object
+               Base *base= FIRSTBASE;
+               while(base) {
+                       if TESTBASELIB(base) {
+                               if(base!=BASACT) {
+                                       ob= base->object;
+                                       break;
+                               }
+                       }
+                       base= base->next;
+               }
+               if(ob==NULL) {
+                       error("Requires selected Object");
+                       return;
+               }
+       }
+       else if(mode!=1) {
+               int maxlen=0, a, nr;
+               char *cp;
+               
+               // make pupmenu with hooks
+               for(hook= G.obedit->hooks.first; hook; hook= hook->next) maxlen+=32;
+               
+               if(maxlen==0) {
+                       error("Object has no hooks yet");
+                       return;
+               }
+               
+               cp= MEM_callocN(maxlen+32, "temp string");
+               if(mode==3) strcpy(cp, "Remove %t|");
+               else if(mode==4) strcpy(cp, "Reassign %t|");
+               else if(mode==5) strcpy(cp, "Select %t|");
+               else if(mode==6) strcpy(cp, "Clear Offset %t|");
+               
+               for(hook= G.obedit->hooks.first; hook; hook= hook->next) {
+                       strcat(cp, hook->name);
+                       strcat(cp, " |");
+               }
+       
+               nr= pupmenu(cp);
+               MEM_freeN(cp);
+               
+               if(nr<1) return;
+               
+               a= 1;
+               for(hook= G.obedit->hooks.first; hook; hook= hook->next, a++) {
+                       if(a==nr) break;
+               }
+               ob= hook->parent;
+       }
+
+       /* do it, new hooks or reassign */
+       if(mode==1 || mode==2 || mode==4) {
+       
+               switch(G.obedit->type) {
+               case OB_MESH:
+                       tot= return_editmesh_indexar(&indexar, cent);
+                       break;
+               case OB_CURVE:
+               case OB_SURF:
+                       tot= return_editcurve_indexar(&indexar, cent);
+                       break;
+               case OB_LATTICE:
+                       tot= return_editlattice_indexar(&indexar, cent);
+                       break;
+               }
+               
+               if(tot==0) {
+                       error("Requires selected vertices");
+               }
+               else {
+                       
+                       if(mode==1) {
+                               Base *base= BASACT;
+
+                               ob= add_object(OB_EMPTY);
+                               /* transform cent to global coords for loc */
+                               VecMat4MulVecfl(ob->loc, G.obedit->obmat, cent);
+                               
+                               /* restore, add_object sets active */
+                               BASACT= base;
+                       }
+                       /* if mode is 2 or 4, ob has been set */
+                                                                       
+                       /* new hook */
+                       if(mode==1 || mode==2) {
+                               hook= MEM_callocN(sizeof(ObHook), "new hook");
+                               BLI_addtail(&G.obedit->hooks, hook);
+                               strncpy(hook->name, ob->id.name+2, 30);
+                               hook->force= 1.0;
+                       }
+                       else MEM_freeN(hook->indexar); // reassign, hook was set
+
+                       hook->parent= ob;
+                       hook->indexar= indexar;
+                       VECCOPY(hook->cent, cent);
+                       hook->totindex= tot;
+                       
+                       if(mode==1 || mode==2) {
+                               /* matrix calculus */
+                               /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
+                               /*        (parentinv         )                          */
+                               
+                               where_is_object(ob);
+               
+                               Mat4Invert(ob->imat, ob->obmat);
+                               /* apparently this call goes from right to left... */
+                               Mat4MulSerie(hook->parentinv, ob->imat, G.obedit->obmat, NULL, 
+                                                       NULL, NULL, NULL, NULL, NULL);
+                       }
+               }
+       }
+       else if(mode==3) { // remove
+               BLI_remlink(&G.obedit->hooks, hook);
+               MEM_freeN(hook->indexar);
+               MEM_freeN(hook);
+       }
+       else if(mode==5) { // select
+               if(G.obedit->type==OB_MESH) select_editmesh_hook(hook);
+               else if(G.obedit->type==OB_LATTICE) select_editlattice_hook(hook);
+               else if(G.obedit->type==OB_CURVE) select_editcurve_hook(hook);
+               else if(G.obedit->type==OB_SURF) select_editcurve_hook(hook);
+       }
+       else if(mode==6) { // clear offset
+               where_is_object(ob);    // ob is hook->parent
+
+               Mat4Invert(ob->imat, ob->obmat);
+               /* this call goes from right to left... */
+               Mat4MulSerie(hook->parentinv, ob->imat, G.obedit->obmat, NULL, 
+                                       NULL, NULL, NULL, NULL, NULL);
+       }
+
+       allqueue(REDRAWVIEW3D, 0);
+       allqueue(REDRAWBUTSOBJECT, 0);
+       BIF_undo_push("Add hook");
+}
 
 void make_track(void)
 {
@@ -271,7 +691,7 @@ void make_track(void)
        }
        if(BASACT==0) return;
 
-       mode= pupmenu("Make Track %t|Constraint %x1|Old Track %x2");
+       mode= pupmenu("Make Track %t|TrackTo Constraint %x1|LockTrack Constraint %x2|Old Track %x3");
        if (mode == 0){
                return;
        }
@@ -306,6 +726,36 @@ void make_track(void)
                sort_baselist(G.scene);
        }
        else if (mode == 2){
+               bConstraint *con;
+               bLockTrackConstraint *data;
+
+               base= FIRSTBASE;
+               while(base) {
+                       if TESTBASELIB(base) {
+                               if(base!=BASACT) {
+                                       con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
+                                       strcpy (con->name, "AutoTrack");
+
+                                       data = con->data;
+                                       data->tar = BASACT->object;
+
+                                       /* Lamp and Camera track differently by default */
+                                       if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
+                                               data->trackflag = TRACK_nZ;
+                                               data->lockflag = LOCK_Y;
+                                       }
+
+                                       add_constraint_to_object(con, base->object);
+                               }
+                       }
+                       base= base->next;
+               }
+
+               test_scene_constraints();
+               allqueue(REDRAWVIEW3D, 0);
+               sort_baselist(G.scene);
+       }
+       else if (mode == 3){
                base= FIRSTBASE;
                while(base) {
                        if TESTBASELIB(base) {
@@ -322,6 +772,7 @@ void make_track(void)
                allqueue(REDRAWOOPS, 0);
                sort_baselist(G.scene);
        }
+       BIF_undo_push("Make Track");
 }
 
 void apply_obmat(Object *ob)
@@ -362,7 +813,7 @@ void clear_parent(void)
        if(G.obedit) return;
        if(G.scene->id.lib) return;
 
-       mode= pupmenu("OK? %t|Clear Parent %x1| ... and keep transform (clr track) %x2|Clear parent inverse %x3");
+       mode= pupmenu("OK? %t|Clear Parent %x1|Clear and Keep Transformation (Clear Track) %x2|Clear Parent Inverse %x3");
        
        if(mode<1) return;
 
@@ -388,9 +839,7 @@ void clear_parent(void)
                        }
                        
                        if(par) {
-                               if(par->type==OB_LATTICE) makeDispList(base->object);
-                               if(par->type==OB_IKA) makeDispList(base->object);
-                               if(par->type==OB_ARMATURE) makeDispList(base->object);
+                               makeDispList(base->object);     // just always..., checks are not available well (ton)
                        }
                }
                base= base->next;
@@ -399,6 +848,8 @@ void clear_parent(void)
        test_scene_constraints();
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWOOPS, 0);
+       
+       BIF_undo_push("Clear Parent");  
 }
 
 void clear_track(void)
@@ -409,7 +860,7 @@ void clear_track(void)
        if(G.obedit) return;
        if(G.scene->id.lib) return;
 
-       mode= pupmenu("OK? %t|Clear Track %x1| ... and keep transform %x2");
+       mode= pupmenu("OK? %t|Clear Track %x1| Clear Track and Keep Transform %x2");
 
        if(mode<1) return;
 
@@ -427,20 +878,25 @@ void clear_track(void)
        test_scene_constraints();
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWOOPS, 0);
+       
+       BIF_undo_push("Clear Track");   
 }
 
 void clear_object(char mode)
 {
        Base *base;
+       Object *ob;
        float *v1, *v3, mat[3][3];
+       char *str=NULL;
        
        if(G.obedit) return;
        if(G.scene->id.lib) return;
        
-       if(mode=='r' && okee("Clear rotation")==0) return;
-       else if(mode=='g' && okee("Clear location")==0) return;
-       else if(mode=='s' && okee("Clear size")==0) return;
-       else if(mode=='o' && okee("Clear origin")==0) return;
+       if(mode=='r') str= "Clear rotation";
+       else if(mode=='g') str= "Clear location";
+       else if(mode=='s') str= "Clear size";
+       else if(mode=='o') str= "Clear origin";
+       else return;
        
        if (G.obpose){
 
@@ -455,34 +911,37 @@ void clear_object(char mode)
                }
 
                allqueue(REDRAWVIEW3D, 0);
+               BIF_undo_push(str);
                return;
        }
 
        base= FIRSTBASE;
        while(base) {
                if TESTBASELIB(base) {
+                       ob= base->object;
+                       
                        if(mode=='r') {
-                               memset(base->object->rot, 0, 3*sizeof(float));
-                               memset(base->object->drot, 0, 3*sizeof(float));
-                               QuatOne(base->object->quat);
-                               QuatOne(base->object->dquat);
+                               memset(ob->rot, 0, 3*sizeof(float));
+                               memset(ob->drot, 0, 3*sizeof(float));
+                               QuatOne(ob->quat);
+                               QuatOne(ob->dquat);
                        }
                        else if(mode=='g') {
-                               memset(base->object->loc, 0, 3*sizeof(float));
-                               memset(base->object->dloc, 0, 3*sizeof(float));
+                               memset(ob->loc, 0, 3*sizeof(float));
+                               memset(ob->dloc, 0, 3*sizeof(float));
                        }
                        else if(mode=='s') {
-                               memset(base->object->dsize, 0, 3*sizeof(float));
-                               base->object->size[0]= 1.0;
-                               base->object->size[1]= 1.0;
-                               base->object->size[2]= 1.0;
+                               memset(ob->dsize, 0, 3*sizeof(float));
+                               ob->size[0]= 1.0;
+                               ob->size[1]= 1.0;
+                               ob->size[2]= 1.0;
                        }
                        else if(mode=='o') {
-                               if(base->object->parent) {
-                                       v1= base->object->loc;
-                                       v3= base->object->parentinv[3];
+                               if(ob->parent) {
+                                       v1= ob->loc;
+                                       v3= ob->parentinv[3];
                                        
-                                       Mat3CpyMat4(mat, base->object->parentinv);
+                                       Mat3CpyMat4(mat, ob->parentinv);
                                        VECCOPY(v3, v1);
                                        v3[0]= -v3[0];
                                        v3[1]= -v3[1];
@@ -490,11 +949,17 @@ void clear_object(char mode)
                                        Mat3MulVecfl(mat, v3);
                                }
                        }
+                       
+                       if(ob->parent && ob->partype==PARSKEL)
+                               freedisplist(&ob->disp);
+                       else if(ob->hooks.first)
+                               freedisplist(&ob->disp);
                }
                base= base->next;
        }
        
        allqueue(REDRAWVIEW3D, 0);
+       BIF_undo_push(str);
 }
 
 void reset_slowparents(void)
@@ -519,7 +984,7 @@ void set_slowparent(void)
 {
        Base *base;
 
-       if( okee("Set Slow parent")==0 ) return;
+       if( okee("Set slow parent")==0 ) return;
 
        base= FIRSTBASE;
        while(base) {
@@ -528,7 +993,7 @@ void set_slowparent(void)
                }
                base= base->next;
        }
-       
+       BIF_undo_push("Slow parent");
 }
 
 void make_vertex_parent(void)
@@ -542,7 +1007,7 @@ void make_vertex_parent(void)
        Object *par, *ob;
        int a, v1=0, v2=0, v3=0, nr=1;
        
-       /* we need 1 ot 3 selected vertices */
+       /* we need 1 to 3 selected vertices */
        
        if(G.obedit->type==OB_MESH) {
                eve= em->verts.first;
@@ -594,11 +1059,11 @@ void make_vertex_parent(void)
        }
        
        if( !(v1 && v2==0 && v3==0) && !(v1 && v2 && v3) ) {
-               error("select 1 or 3 vertices");
+               error("Select either 1 or 3 vertices to parent to");
                return;
        }
        
-       if(okee("Make vertex-parent")==0) return;
+       if(okee("Make vertex parent")==0) return;
        
        base= FIRSTBASE;
        while(base) {
@@ -643,6 +1108,7 @@ void make_vertex_parent(void)
        }
        allqueue(REDRAWVIEW3D, 0);
        
+       // BIF_undo_push(str); not, conflicts with editmode undo...
 }
 
 int test_parent_loop(Object *par, Object *ob)
@@ -667,8 +1133,7 @@ void make_parent(void)
 {
        Base *base;
        Object *par;
-       Ika *ika;
-       short qual, ok, mode=0, limbnr=0, effchild=0;
+       short qual, mode=0, limbnr=0, effchild=0;
        char *bonestr=NULL;
        Bone    *bone=NULL;
        int     bonenr;
@@ -684,64 +1149,21 @@ void make_parent(void)
        qual= G.qual;
        par= BASACT->object;
 
-       if(par->type==OB_IKA) {
-               
-               if(qual & LR_SHIFTKEY)
-                       mode= pupmenu("Make Parent without inverse%t|Use Vertex %x1|Use Limb %x2|Use Skeleton %x3");
-               else 
-                       mode= pupmenu("Make Parent %t|Use Vertex %x1|Use Limb %x2|Use Skeleton %x3");
-               
-               if(mode==1) {
-                       draw_ika_nrs(par, 0);
-                       if(button(&limbnr, 0, 99, "Vertex: ")==0) {
-                               allqueue(REDRAWVIEW3D, 0);
-                               return;
-                       }
+       if(par->type == OB_CURVE){
+               bConstraint *con;
+               bFollowPathConstraint *data;
+
+               mode= pupmenu("Make Parent %t|Normal Parent %x1|Follow Path %x2|Curve Deform %x3");
+               if(mode<=0){
+                       return;
                }
-               else if(mode==2) {
-                       draw_ika_nrs(par, 1);
-                       if(button(&limbnr, 0, 99, "Limb: ")==0) {
-                               allqueue(REDRAWVIEW3D, 0);
-                               return;
-                       }
+               else if(mode==1) {
+                       mode= PAROBJECT;
                }
                else if(mode==3) {
-                       ika= par->data;
-                       if(ika->def==0) {
-                               error("No skeleton available: use CTRL K");
-                               return;
-                       }
+                       mode= PARSKEL;
                }
-               else return;
-
-               if(mode==1) mode= PARVERT1;
-               else if(mode==2) mode= PARLIMB;
-               else if(mode==3) mode= PARSKEL;
-
-               /* test effchild */
-               base= FIRSTBASE;
-               while(base) {
-                       if TESTBASELIB(base) {
-                               if(base->object->type==OB_IKA && base->object!=par && mode==PARVERT1 ) {
-                                       if(effchild==0) {
-                                               if(okee("Effector as Child")) effchild= 1;
-                                               else effchild= 2;
-                                       }
-                               }
-                       }
-                       if(effchild) break;
-                       base= base->next;
-               }
-       }
-       else if(par->type == OB_CURVE){
-               bConstraint *con;
-               bFollowPathConstraint *data;
-
-               mode= pupmenu("Make Parent %t|Normal Parent %x1|Follow Path %x2");
-               if (mode == 0){
-                       return;
-               }
-               else if (mode == 2){
+               else if(mode==2) {
 
                        base= FIRSTBASE;
                        while(base) {
@@ -757,7 +1179,7 @@ void make_parent(void)
 
                                                add_constraint_to_object(con, base->object);
 
-                                               get_constraint_target(con, TARGET_OBJECT, NULL, cmat, size, G.scene->r.cfra - base->object->sf);
+                                               get_constraint_target_matrix(con, TARGET_OBJECT, NULL, cmat, size, G.scene->r.cfra - base->object->sf);
                                                VecSubf(vec, base->object->obmat[3], cmat[3]);
 
                                                base->object->loc[0] = vec[0];
@@ -771,6 +1193,7 @@ void make_parent(void)
                        test_scene_constraints();
                        allqueue(REDRAWVIEW3D, 0);
                        sort_baselist(G.scene);
+                       BIF_undo_push("make Parent");
                        return;
                }
        }
@@ -781,11 +1204,11 @@ void make_parent(void)
                                if TESTBASELIB(base) {
                                        if(base!=BASACT) {
                                                if(base->object->type==OB_MESH) {
-                                                       mode= pupmenu("Make Parent %t|Use Bone %x1|Use Armature %x2|Use Object %x3");
+                                                       mode= pupmenu("Make Parent To%t|Bone %x1|Armature %x2|Object %x3");
                                                        break;
                                                }
                                                else {
-                                                       mode= pupmenu("Make Parent %t|Use Bone %x1|Use Object %x3");
+                                                       mode= pupmenu("Make Parent To %t|Bone %x1|Object %x3");
                                                        break;
                                                }
                                        }
@@ -829,15 +1252,15 @@ void make_parent(void)
                                return;
                        }
        }
-               else {
+       else {
                if(qual & LR_SHIFTKEY) {
-                       if(okee("Make Parent without inverse")==0) return;
+                       if(okee("Make parent without inverse")==0) return;
                }
                else {
                        if(qual & LR_ALTKEY) {
-                               if(okee("Make VertexParent")==0) return;
+                               if(okee("Make vertex parent")==0) return;
                        }
-                       else if(okee("Make Parent")==0) return;
+                       else if(okee("Make parent")==0) return;
 
                        /* test effchild */
                        base= FIRSTBASE;
@@ -877,86 +1300,67 @@ void make_parent(void)
                if TESTBASELIB(base) {
                        if(base!=BASACT) {
                                
-                               ok= 1;
-                               if(base->object->type==OB_IKA) {
-                               
-                                       if(effchild==1) {
+                               if( test_parent_loop(par, base->object) ) {
+                                       error("Loop in parents");
+                               }
+                               else {
                                        
-                                               if( test_parent_loop(par, base->object)==0 ) {
-                                               
-                                                       Ika *ika= base->object->data;
-                                                       
-                                                       ika->parent= par;
-                                                       ika->par1= limbnr;
-                                                       ika->partype= mode;
-                                                       itterate_ika(base->object);
-                                                       ok= 0;
-                                               }
-                                               else {
-                                                       ok= 0;
-                                                       error("Loop in parents");
-                                               }
+                                       /* the ifs below are horrible code (ton) */
+                                       
+                                       if(par->type==OB_IKA){
+                                               base->object->partype= mode;
+                                               base->object->par1= limbnr;
                                        }
-                               }
-                               
-                               if(ok) {
-                                       if( test_parent_loop(par, base->object) ) {
-                                               error("Loop in parents");
+                                       else if (par->type==OB_ARMATURE){
+                                               base->object->partype= mode;
+                                               if (bone)
+                                                       strcpy (base->object->parsubstr, bone->name);
+                                               else
+                                                       base->object->parsubstr[0]=0;
                                        }
                                        else {
-                                               
-                                               if(par->type==OB_IKA){
-                                                       base->object->partype= mode;
-                                                       base->object->par1= limbnr;
+                                               if(qual & LR_ALTKEY) {
+                                                       base->object->partype= PARVERT1;
                                                }
-                                               else if (par->type==OB_ARMATURE){
+                                               else if(par->type==OB_CURVE) {
                                                        base->object->partype= mode;
-                                                       if (bone)
-                                                               strcpy (base->object->parsubstr, bone->name);
-                                                       else
-                                                               base->object->parsubstr[0]=0;
-                                               }
-                                               
-                                               else if(qual & LR_ALTKEY) {
-                                                       base->object->partype= PARVERT1;
                                                }
                                                else {
                                                        base->object->partype= PAROBJECT;
                                                }
-                                               
-                                               base->object->parent= par;
-                                               
-                                               /* calculate inverse parent matrix? */
-                                               if( (qual & LR_SHIFTKEY) ) {
-                                                       /* not... */
-                                                       Mat4One(base->object->parentinv);
-                                                       memset(base->object->loc, 0, 3*sizeof(float));
-                                               }
-                                               else {
-                                                       if(mode==PARSKEL && par->type == OB_ARMATURE) {
-                                                               /* Prompt the user as to whether he wants to
-                                                                * add some vertex groups based on the bones
-                                                                * in the parent armature.
-                                                                */
-                                                               create_vgroups_from_armature(base->object, 
-                                                                                                                        par);
-
-                                                               base->object->partype= PAROBJECT;
-                                                               what_does_parent(base->object);
-                                                               Mat4One (base->object->parentinv);
-                                                               base->object->partype= mode;
-                                                       }
-                                                       else
-                                                               what_does_parent(base->object);
-                                                       Mat4Invert(base->object->parentinv, workob.obmat);
-                                               }
-                                               
-                                               if(par->type==OB_LATTICE) makeDispList(base->object);
-                                               if(par->type==OB_IKA && mode==PARSKEL) makeDispList(base->object);
-                                               if(par->type==OB_ARMATURE && mode == PARSKEL){
-                                                       verify_defgroups(base->object);
-                                                       makeDispList(base->object);
+                                       }
+                                       base->object->parent= par;
+                                       
+                                       /* calculate inverse parent matrix? */
+                                       if( (qual & LR_SHIFTKEY) ) {
+                                               /* not... */
+                                               Mat4One(base->object->parentinv);
+                                               memset(base->object->loc, 0, 3*sizeof(float));
+                                       }
+                                       else {
+                                               if(mode==PARSKEL && par->type == OB_ARMATURE) {
+                                                       /* Prompt the user as to whether he wants to
+                                                               * add some vertex groups based on the bones
+                                                               * in the parent armature.
+                                                               */
+                                                       create_vgroups_from_armature(base->object, 
+                                                                                                                       par);
+
+                                                       base->object->partype= PAROBJECT;
+                                                       what_does_parent(base->object);
+                                                       Mat4One (base->object->parentinv);
+                                                       base->object->partype= mode;
                                                }
+                                               else
+                                                       what_does_parent(base->object);
+                                               Mat4Invert(base->object->parentinv, workob.obmat);
+                                       }
+                                       
+                                       if(par->type==OB_LATTICE) makeDispList(base->object);
+                                       if(par->type==OB_CURVE && mode==PARSKEL) makeDispList(base->object);
+                                       if(par->type==OB_ARMATURE && mode == PARSKEL){
+                                               verify_defgroups(base->object);
+                                               makeDispList(base->object);
                                        }
                                }
                        }
@@ -968,6 +1372,8 @@ void make_parent(void)
        
        test_scene_constraints();
        sort_baselist(G.scene);
+
+       BIF_undo_push("make Parent");
 }
 
 
@@ -984,14 +1390,14 @@ void enter_editmode(void)
        if(G.scene->id.lib) return;
        base= BASACT;
        if(base==0) return;
-       if((base->lay & G.vd->lay)==0) return;
+       if((G.vd==NULL || (base->lay & G.vd->lay))==0) return;
        
        ob= base->object;
        if(ob->data==0) return;
        
        id= ob->data;
        if(id->lib) {
-               error("Can't edit libdata");
+               error("Can't edit library data");
                return;
        }
        
@@ -999,19 +1405,20 @@ void enter_editmode(void)
                me= get_mesh(ob);
                if( me==0 ) return;
                if(me->id.lib) {
-                       error("Can't edit libdata");
+                       error("Can't edit library data");
                        return;
                }
                ok= 1;
                G.obedit= ob;
                make_editMesh();
                allqueue(REDRAWBUTSLOGIC, 0);
+               if(G.f & G_FACESELECT) allqueue(REDRAWIMAGE, 0);
        }
        if (ob->type==OB_ARMATURE){
                arm=base->object->data;
                if (!arm) return;
                if (arm->id.lib){
-                       error("Can't edit libdata");
+                       error("Can't edit library data");
                        return;
                }
                ok=1;
@@ -1054,12 +1461,13 @@ void enter_editmode(void)
                make_editNurb();
        }
        allqueue(REDRAWBUTSEDIT, 0);
+       allqueue(REDRAWOOPS, 0);
        countall();
        
        if(ok) {
                setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
        
-               allqueue(REDRAWVIEW3D, 0);
+               allqueue(REDRAWVIEW3D, 1);
        }
        else G.obedit= 0;
 
@@ -1076,13 +1484,13 @@ void make_displists_by_parent(Object *ob) {
                        makeDispList(base->object);
 }
 
-void exit_editmode(int freedata)       /* freedata==0 at render */
+void exit_editmode(int freedata)       /* freedata==0 at render, 1= freedata, 2= do undo buffer too */
 {
        Base *base;
        Object *ob;
        Curve *cu;
 
-       if(G.obedit==0) return;
+       if(G.obedit==NULL) return;
 
        if(G.obedit->type==OB_MESH) {
 
@@ -1090,14 +1498,17 @@ void exit_editmode(int freedata)        /* freedata==0 at render */
                countall();
 
                if(G.totvert>MESH_MAX_VERTS) {
-                       error("too many vertices");
+                       error("Too many vertices");
                        return;
                }
                load_editMesh();        /* makes new displist */
 
-               if(freedata) free_editMesh();
-               
-               if(G.f & G_FACESELECT) allqueue(REDRAWIMAGE, 0);
+               if(freedata) free_editMesh(G.editMesh);
+
+               if(G.f & G_FACESELECT) {
+                       set_seamtface();
+                       allqueue(REDRAWIMAGE, 0);
+               }
 
                build_particle_system(G.obedit);
        }
@@ -1109,7 +1520,7 @@ void exit_editmode(int freedata)  /* freedata==0 at render */
                load_editNurb();
                if(freedata) freeNurblist(&editNurb);
        }
-       else if(G.obedit->type==OB_FONT && freedata==1) {
+       else if(G.obedit->type==OB_FONT && freedata) {
                load_editText();
        }
        else if(G.obedit->type==OB_LATTICE) {
@@ -1125,6 +1536,10 @@ void exit_editmode(int freedata) /* freedata==0 at render */
        
        /* displist make is different in editmode */
        if(freedata) G.obedit= NULL;
+
+       /* total remake of softbody data */
+       if(ob->softflag & OB_SB_ENABLE) sbObjectToSoftbody(ob);
+       
        makeDispList(ob);
 
        /* has this influence at other objects? */
@@ -1140,7 +1555,7 @@ void exit_editmode(int freedata)  /* freedata==0 at render */
                                        text_to_curve(base->object, 0);
                                        makeDispList(base->object);
                                }
-                               if(cu->bevobj== ob) {
+                               if(cu->bevobj==ob || cu->taperobj==ob) {
                                        makeDispList(base->object);
                                }
                        }
@@ -1156,12 +1571,15 @@ void exit_editmode(int freedata)        /* freedata==0 at render */
                setcursor_space(SPACE_VIEW3D, CURSOR_STD);
        
                countall();
-               allqueue(REDRAWVIEW3D, 0);
+               allqueue(REDRAWVIEW3D, 1);
                allqueue(REDRAWBUTSEDIT, 0);
                allqueue(REDRAWBUTSLOGIC, 0);
+               allqueue(REDRAWOOPS, 0);
        }
        scrarea_queue_headredraw(curarea);
-
+       
+       if(G.obedit==NULL && freedata==2) 
+               BIF_undo_push("Editmode");
 }
 
 void check_editmode(int type)
@@ -1169,12 +1587,12 @@ void check_editmode(int type)
        
        if (G.obedit==0 || G.obedit->type==type) return;
 
-       exit_editmode(1);
+       exit_editmode(2); // freedata, and undo
 }
 
-static int centremode= 0; /* 0 == do centre, 1 == centre new, 2 == centre cursor */
+/* 0 == do centre, 1 == centre new, 2 == centre cursor */
 
-void docentre(void)
+void docentre(int centremode)
 {
        EditMesh *em = G.editMesh;
        Base *base;
@@ -1186,29 +1604,39 @@ void docentre(void)
        Nurb *nu, *nu1;
        EditVert *eve;
        float cent[3], centn[3], min[3], max[3], omat[3][3];
-       int a;
+       int a, total= 0;
        MVert *mvert;
 
        if(G.scene->id.lib) return;
-
+       
+       cent[0]= cent[1]= cent[2]= 0.0;
+       
        if(G.obedit) {
 
                INIT_MINMAX(min, max);
        
                if(G.obedit->type==OB_MESH) {
-                       eve= em->verts.first;
-                       while(eve) {
-                               DO_MINMAX(eve->co, min, max);
-                               eve= eve->next;
-                       }
-                       cent[0]= (min[0]+max[0])/2.0;
-                       cent[1]= (min[1]+max[1])/2.0;
-                       cent[2]= (min[2]+max[2])/2.0;
+                       for(eve= em->verts.first; eve; eve= eve->next) {
+                               if(G.vd->around==V3D_CENTROID) {
+                                       total++;
+                                       VECADD(cent, cent, eve->co);
+                               }
+                               else {
+                                       DO_MINMAX(eve->co, min, max);
+                               }
+                       }
+                       
+                       if(G.vd->around==V3D_CENTROID) {
+                               VecMulf(cent, 1.0f/(float)total);
+                       }
+                       else {
+                               cent[0]= (min[0]+max[0])/2.0f;
+                               cent[1]= (min[1]+max[1])/2.0f;
+                               cent[2]= (min[2]+max[2])/2.0f;
+                       }
                        
-                       eve= em->verts.first;
-                       while(eve) {
+                       for(eve= em->verts.first; eve; eve= eve->next) {
                                VecSubf(eve->co, eve->co, cent);                        
-                               eve= eve->next;
                        }
                }
        }
@@ -1238,7 +1666,7 @@ void docentre(void)
                                if(G.obedit==0 && (me=get_mesh(base->object)) ) {
                                        
                                        if(me->key) {
-                                               error("Mesh with vertexkey!");
+                                               error("Can't change the center of a mesh with vertex keys");
                                                return;
                                        }
                                        
@@ -1254,9 +1682,9 @@ void docentre(void)
                                                        DO_MINMAX(mvert->co, min, max);
                                                }
                                
-                                               cent[0]= (min[0]+max[0])/2.0;
-                                               cent[1]= (min[1]+max[1])/2.0;
-                                               cent[2]= (min[2]+max[2])/2.0;
+                                               cent[0]= (min[0]+max[0])/2.0f;
+                                               cent[1]= (min[1]+max[1])/2.0f;
+                                               cent[2]= (min[2]+max[2])/2.0f;
                                        }
                                                
                                        mvert= me->mvert;
@@ -1341,9 +1769,9 @@ void docentre(void)
                                                        nu= nu->next;
                                                }
                                                
-                                               cent[0]= (min[0]+max[0])/2.0;
-                                               cent[1]= (min[1]+max[1])/2.0;
-                                               cent[2]= (min[2]+max[2])/2.0;
+                                               cent[0]= (min[0]+max[0])/2.0f;
+                                               cent[1]= (min[1]+max[1])/2.0f;
+                                               cent[2]= (min[2]+max[2])/2.0f;
                                        }
                                        
                                        nu= nu1;
@@ -1386,8 +1814,8 @@ void docentre(void)
                                        cu= base->object->data;
                                        if(cu->bb==0) return;
                                        
-                                       cu->xof= -0.5*( cu->bb->vec[4][0] - cu->bb->vec[0][0]);
-                                       cu->yof= -0.5 -0.5*( cu->bb->vec[0][1] - cu->bb->vec[2][1]);    /* extra 0.5 is the height of above line */
+                                       cu->xof= -0.5f*( cu->bb->vec[4][0] - cu->bb->vec[0][0]);
+                                       cu->yof= -0.5f -0.5f*( cu->bb->vec[0][1] - cu->bb->vec[2][1]);  /* extra 0.5 is the height of above line */
                                        
                                        /* not really ok, do this better once! */
                                        cu->xof /= cu->fsize;
@@ -1404,6 +1832,7 @@ void docentre(void)
        }
 
        allqueue(REDRAWVIEW3D, 0);
+       BIF_undo_push("Do Centre");     
 }
 
 void docentre_new(void)
@@ -1411,12 +1840,10 @@ void docentre_new(void)
        if(G.scene->id.lib) return;
 
        if(G.obedit) {
-               error("Unable to perform function in EditMode");
+               error("Unable to center new in Edit Mode");
        }
        else {
-               centremode= 1;
-               docentre();
-               centremode= 0;
+               docentre(1);
        }
 }
 
@@ -1425,12 +1852,10 @@ void docentre_cursor(void)
        if(G.scene->id.lib) return;
 
        if(G.obedit) {
-               error("Unable to perform function in EditMode");
+               error("Unable to center cursor in Edit Mode");
        }
        else {
-               centremode= 2;
-               docentre();
-               centremode= 0;
+               docentre(2);
        }
 }
 
@@ -1438,7 +1863,8 @@ void movetolayer(void)
 {
        Base *base;
        unsigned int lay= 0, local;
-
+       int islamp= 0;
+       
        if(G.scene->id.lib) return;
 
        base= FIRSTBASE;
@@ -1455,18 +1881,24 @@ void movetolayer(void)
        base= FIRSTBASE;
        while(base) {
                if TESTBASE(base) {
-                       local= base->lay & 0xFF000000;
+                       /* upper byte is used for local view */
+                       local= base->lay & 0xFF000000;  
                        base->lay= lay + local;
-
                        base->object->lay= lay;
+                       if(base->object->type==OB_LAMP) islamp= 1;
                }
                base= base->next;
        }
+       
+       if(islamp && G.vd->drawtype == OB_SHADED) reshadeall_displist();
+
        countall();
        allqueue(REDRAWBUTSEDIT, 0);
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWOOPS, 0);
        allqueue(REDRAWINFO, 0);
+       
+       BIF_undo_push("Move to layer");
 }
 
 
@@ -1517,7 +1949,8 @@ void special_editmenu(void)
                                }
                        }
                        allqueue(REDRAWVIEW3D, 0);
-                       allqueue(REDRAWBUTSLOGIC, 0);
+                       allqueue(REDRAWBUTSEDIT, 0);
+                       BIF_undo_push("Change texture face");
                }
                else if(G.f & G_VERTEXPAINT) {
                        Mesh *me= get_mesh(OBACT);
@@ -1533,6 +1966,7 @@ void special_editmenu(void)
                                do_shared_vertexcol(me);
                                
                                if(me->tface) mcol_to_tface(me, 1);
+                               BIF_undo_push("Shared VertexCol");
                        }
                }
                else {
@@ -1568,8 +2002,9 @@ void special_editmenu(void)
                                                        if (ret==0) {
                                                                error("An internal error occurred -- sorry!");
                                                        } else if(ret==-1) {
-                                                               error("Boolean ops with faceless meshes is not allowed");
+                                                               error("Selected meshes must have faces to perform boolean operations");
                                                        }
+                                                       else BIF_undo_push("Boolean");
 
                                                        waitcursor(0);
                                                } else {
@@ -1586,31 +2021,31 @@ void special_editmenu(void)
        }
        else if(G.obedit->type==OB_MESH) {
 
-               nr= pupmenu("Specials%t|Subdivide%x1|Subdivide Fractal%x2|Subdivide Smooth%x3|Merge%x4|Remove Doubles%x5|Hide%x6|Reveal%x7|Select swap%x8|Flip Normals %x9|Smooth %x10|Bevel %x11");
+               nr= pupmenu("Specials%t|Subdivide%x1|Subdivide Fractal%x2|Subdivide Smooth%x3|Merge%x4|Remove Doubles%x5|Hide%x6|Reveal%x7|Select Swap%x8|Flip Normals %x9|Smooth %x10|Bevel %x11");
                if(nr>0) waitcursor(1);
                
                switch(nr) {
                case 1:
-                       undo_push_mesh("Subdivide");
                        subdivideflag(1, 0.0, editbutflag);
+                       BIF_undo_push("Subdivide");
                        break;
                case 2:
                        randfac= 10;
                        if(button(&randfac, 1, 100, "Rand fac:")==0) return;
                        fac= -( (float)randfac )/100;
-                       undo_push_mesh("Subdivide Fractal");
                        subdivideflag(1, fac, editbutflag);
+                       BIF_undo_push("Subdivide Fractal");
                        break;
                case 3:
-                       undo_push_mesh("Subdivide Smooth");
                        subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
+                       BIF_undo_push("Subdivide Smooth");
                        break;
                case 4:
                        mergemenu();
                        break;
                case 5:
-                       undo_push_mesh("Rem Doubles");
-                       notice("Removed: %d", removedoublesflag(1, doublimit));
+                       notice("Removed %d Vertices", removedoublesflag(1, doublimit));
+                       BIF_undo_push("Remove Doubles");
                        break;
                case 6:
                        hide_mesh(0);
@@ -1622,11 +2057,10 @@ void special_editmenu(void)
                        selectswap_mesh();
                        break;
                case 9:
-                       undo_push_mesh("Flip Normals");
                        flip_editnormals();
+                       BIF_undo_push("Flip Normals");
                        break;
                case 10:
-                       undo_push_mesh("Smooth");
                        vertexsmooth();
                        break;
                case 11:
@@ -1660,7 +2094,7 @@ void special_editmenu(void)
 
 void convertmenu(void)
 {
-       Base *base, *basen, *basact;
+       Base *base, *basen, *basact, *basedel=NULL;
        Object *ob, *ob1;
        Curve *cu;
        MetaBall *mb;
@@ -1681,7 +2115,7 @@ void convertmenu(void)
                if(nr>0) ok= 1;
        }
        else if(ob->type==OB_MBALL) {
-               nr= pupmenu("Convert MetaBall to%t|Mesh (keep original)");
+               nr= pupmenu("Convert Metaball to%t|Mesh (keep original)%x1|Mesh (Delete Original)%x2");
                if(nr>0) ok= 1;
        }
        else if(ob->type==OB_CURVE) {
@@ -1689,11 +2123,11 @@ void convertmenu(void)
                if(nr>0) ok= 1;
        }
        else if(ob->type==OB_SURF) {
-               nr= pupmenu("Convert Nurbs Surf to%t|Mesh");
+               nr= pupmenu("Convert Nurbs Surface to%t|Mesh");
                if(nr>0) ok= 1;
        }
        else if(ob->type==OB_MESH && mesh_uses_displist((Mesh*) ob->data)) {
-               nr= pupmenu("Convert SubSurf to%t|Mesh (keep original)");
+               nr= pupmenu("Convert SubSurf to%t|Mesh (Keep Original)%x1|Mesh (Delete Original)%x2");
                if(nr>0) ok= 1;
        }
        if(ok==0) return;
@@ -1721,6 +2155,9 @@ void convertmenu(void)
                                
                                if (mesh_uses_displist(oldme)) {
                                        DispListMesh *dlm;
+                                       DerivedMesh *dm;
+
+                                       basedel = base;
 
                                        ob->flag |= OB_DONE;
 
@@ -1745,12 +2182,20 @@ void convertmenu(void)
                                                me->mat= MEM_dupallocN(oldme->mat);
                                                for(a=0; a<ob1->totcol; a++) id_us_plus((ID *)me->mat[a]);
                                        }
-                                               
-                                       dlm= subsurf_make_dispListMesh_from_mesh(oldme, NULL, oldme->subdiv, oldme->flag);
+                                       
+                                       dm= subsurf_make_derived_from_mesh(oldme, oldme->subdiv);
+                                       dlm= dm->convertToDispListMesh(dm);
+                                       dm->release(dm);
+
                                        displistmesh_to_mesh(dlm, ob1->data);
                                        displistmesh_free(dlm);
 
-                                       tex_space_mesh(me);
+                                       /* texspace and normals */
+                                       BASACT= basen;
+                                       enter_editmode();
+                                       exit_editmode(1); // freedata, but no undo
+                                       BASACT= basact;
+                                       
                                }
                        }
                        else if(ob->type==OB_FONT) {
@@ -1789,16 +2234,17 @@ void convertmenu(void)
                                        /* texspace and normals */
                                        BASACT= base;
                                        enter_editmode();
-                                       exit_editmode(1);
+                                       exit_editmode(1); // freedata, but no undo
                                        BASACT= basact;
                                }
                        }
                        else if(ob->type==OB_MBALL) {
                        
-                               if(nr==1) {
+                               if(nr==1 || nr == 2) {
                                        ob= find_basis_mball(ob);
                                        
                                        if(ob->disp.first && !(ob->flag&OB_DONE)) {
+                                               basedel = base;
                                        
                                                ob->flag |= OB_DONE;
 
@@ -1831,11 +2277,18 @@ void convertmenu(void)
                        }
                }
                base= base->next;
+               if(basedel != NULL && nr == 2)
+                       free_and_unlink_base(basedel);  
+               basedel = NULL;                         
        }
        
+       test_scene_constraints();       // always call after delete object
+       
+       countall();
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWOOPS, 0);
        allqueue(REDRAWBUTSEDIT, 0);
+       BIF_undo_push("Convert Object");
 }
 
        /* Change subdivision properties of mesh object ob, if
@@ -1855,6 +2308,8 @@ void flip_subdivison(Object *ob, int level)
        allqueue(REDRAWOOPS, 0);
        allqueue(REDRAWBUTSEDIT, 0);
        makeDispList(ob);
+       
+       BIF_undo_push("Switch subsurf on/off");
 }
  
 void copymenu_properties(Object *ob)
@@ -1871,7 +2326,7 @@ void copymenu_properties(Object *ob)
        }
        
        if(tot==0) {
-               error("No properties in Object");
+               error("No properties in the active object to copy");
                return;
        }
        
@@ -1919,6 +2374,8 @@ void copymenu_properties(Object *ob)
        }
        MEM_freeN(str);
        allqueue(REDRAWVIEW3D, 0);
+       
+       BIF_undo_push("Copy properties");
 }
 
 void copymenu_logicbricks(Object *ob)
@@ -1952,6 +2409,7 @@ void copymenu_logicbricks(Object *ob)
                }
                base= base->next;
        }
+       BIF_undo_push("Copy logic");
 }
 
 void copy_attr_menu()
@@ -1982,6 +2440,8 @@ void copy_attr_menu()
 
        if( give_parteff(ob) ) strcat(str, "|Particle Settings%x20");
 
+       if(ob->soft) strcat(str, "|Soft Body Settings%x23");
+       
        event= pupmenu(str);
        if(event<= 0) return;
        
@@ -2107,6 +2567,7 @@ void copy_attr(short event)
                                                cu1= base->object->data;
                                                
                                                cu1->bevobj= cu->bevobj;
+                                               cu1->taperobj= cu->taperobj;
                                                cu1->width= cu->width;
                                                cu1->bevresol= cu->bevresol;
                                                cu1->ext1= cu->ext1;
@@ -2153,7 +2614,7 @@ void copy_attr(short event)
                                                makeDispList(base->object);
                                        }
                                }
-                               else if(event==22){
+                               else if(event==22) {
                                        /* Clear the constraints on the target */
                                        free_constraints(&base->object->constraints);
                                        free_constraint_channels(&base->object->constraintChannels);
@@ -2167,6 +2628,12 @@ void copy_attr(short event)
 
                                        base->object->activecon = NULL;
                                }
+                               else if(event==23) {
+                                       base->object->softflag= ob->softflag;
+                                       if(base->object->soft) sbFree(base->object->soft);
+                                       
+                                       base->object->soft= copy_softbody(ob->soft);
+                               }
                        }
                }
                base= base->next;
@@ -2177,6 +2644,7 @@ void copy_attr(short event)
                allqueue(REDRAWBUTSOBJECT, 0);
        }
        
+       BIF_undo_push("Copy attributes");
 }
 
 void link_to_scene(unsigned short nr)
@@ -2273,7 +2741,7 @@ void make_links(short event)
                                sce= sce->id.next;
                        }
                        if(sce==G.scene) {
-                               error("This is current scene");
+                               error("This is the current scene");
                                return;
                        }
                        if(sce==0 || sce->id.lib) return;
@@ -2391,6 +2859,8 @@ void make_links(short event)
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWOOPS, 0);
        allqueue(REDRAWBUTSHEAD, 0);
+       
+       BIF_undo_push("Create links");
 }
 
 void make_duplilist_real()
@@ -2399,7 +2869,7 @@ void make_duplilist_real()
        Object *ob;
        extern ListBase duplilist;
        
-       if(okee("Make dupli's real")==0) return;
+       if(okee("Make dupli objects real")==0) return;
        
        base= FIRSTBASE;
        while(base) {
@@ -2439,6 +2909,8 @@ void make_duplilist_real()
        
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWOOPS, 0);
+       
+       BIF_undo_push("Make duplicates real");
 }
 
 void apply_object()
@@ -2462,13 +2934,21 @@ void apply_object()
                ob= OBACT;
                if(ob==0) return;
                
-               if(ob->transflag & OB_DUPLI) make_duplilist_real();
-               else if(ob->parent && ob->parent->type==OB_LATTICE) apply_lattice();
-               
+               if(ob->transflag & OB_DUPLI) {
+                       make_duplilist_real();
+               }
+               else {
+                       if(okee("Apply deformation")) {
+                               object_apply_deform(ob);
+                               BIF_undo_push("Apply deformation");
+                       }
+               }
+               allqueue(REDRAWVIEW3D, 0);
+
                return;
        }
 
-       if(okee("Apply size/rot")==0) return;
+       if(okee("Apply size and rotation")==0) return;
 
        base= FIRSTBASE;
        while(base) {
@@ -2480,11 +2960,11 @@ void apply_object()
                                me= ob->data;
                                
                                if(me->id.us>1) {
-                                       error("Can't do multi user mesh");
+                                       error("Can't apply to a multi user mesh");
                                        return;
                                }
                                if(me->key) {
-                                       error("Can't do key && mesh");
+                                       error("Can't apply to a mesh with vertex keys");
                                        return;
                                }
                                
@@ -2501,7 +2981,8 @@ void apply_object()
                                /* texspace and normals */
                                BASACT= base;
                                enter_editmode();
-                               exit_editmode(1);
+                               BIF_undo_push("Applied object");        // editmode undo itself
+                               exit_editmode(1); // freedata, but no undo
                                BASACT= basact;                         
                                
                        }
@@ -2511,7 +2992,7 @@ void apply_object()
                                object_to_mat3(ob, mat);
                                arm= ob->data;
                                if(arm->id.us>1) {
-                                       error("Can't do multi user armature");
+                                       error("Can't apply to a multi user armature");
                                        return;
                                }
 
@@ -2528,11 +3009,11 @@ void apply_object()
                                cu= ob->data;
                                
                                if(cu->id.us>1) {
-                                       error("Can't do multi user curve");
+                                       error("Can't apply to a multi user curve");
                                        return;
                                }
                                if(cu->key) {
-                                       error("Can't do keys");
+                                       error("Can't apply to a curve with vertex keys");
                                        return;
                                }
                                
@@ -2568,7 +3049,8 @@ void apply_object()
                                /* texspace and normals */
                                BASACT= base;
                                enter_editmode();
-                               exit_editmode(1);
+                               BIF_undo_push("Applied object");        // editmode undo itself
+                               exit_editmode(1); // freedata, but no undo
                                BASACT= basact;
                        }
                }
@@ -2576,6 +3058,7 @@ void apply_object()
        }
        
        allqueue(REDRAWVIEW3D, 0);
+       BIF_undo_push("Apply object");
 }
 
 
@@ -2652,7 +3135,8 @@ static void clear_pose_update_flag(Object *ob) {
        }
 }
 
-static int pose_flags_reset_done(Object *ob) {
+/* exposed in transform.c */
+int pose_flags_reset_done(Object *ob) {
        /* Clear the constraint done status for every pose channe;
         * that has been flagged as needing constant updating
         */
@@ -2679,14 +3163,14 @@ static int is_ob_constraint_target(Object *ob, ListBase *conlist) {
 
        for (con=conlist->first; con; con=con->next)
        {
-               if (get_con_target(con) == ob)
+               if (get_constraint_target(con) == ob)
                        return 1;
        }
        return 0;
 
 }
 
-int clear_bone_nocalc(Object *ob, Bone *bone, void *ptr) {
+static int clear_bone_nocalc(Object *ob, Bone *bone, void *ptr) {
        /* When we aren't transform()-ing, we'll want to turn off
         * the no calc flag for bone bone in case the frame changes,
         * or something
@@ -2709,7 +3193,7 @@ static void clear_bone_nocalc_ob(Object *ob) {
 
 }
 
-int set_bone_nocalc(Object *ob, Bone *bone, void *ptr) {
+static int set_bone_nocalc(Object *ob, Bone *bone, void *ptr) {
        /* Calculating bone transformation makes thins slow ...
         * lets set the no calc flag for a bone by default
         */
@@ -2718,7 +3202,7 @@ int set_bone_nocalc(Object *ob, Bone *bone, void *ptr) {
        return 0;
 }
 
-int selected_bone_docalc(Object *ob, Bone *bone, void *ptr) {
+static int selected_bone_docalc(Object *ob, Bone *bone, void *ptr) {
        /* Let's clear the no calc flag for selected bones.
         * This function always returns 1 for non-no calc bones
         * (a.k.a., the 'do calc' bones) so that the bone_looper 
@@ -2869,7 +3353,8 @@ static void figure_bone_nocalc_core(Object *ob, bArmature *arm) {
        }
 }
 
-static void figure_bone_nocalc(Object *ob) {
+/* exposed in transform.c */
+void figure_bone_nocalc(Object *ob) {
        /* Let's figure out which bones need to be recalculated,
         * and which don't. Calculations are based on which bones
         * are selected, and the constraints that love them.
@@ -2889,7 +3374,7 @@ static void figure_bone_nocalc(Object *ob) {
        figure_bone_nocalc_core(ob, arm);
 }
 
-int bone_nocalc2chan_trans_update(Object *ob, Bone *bone, void *ptr) {
+static int bone_nocalc2chan_trans_update(Object *ob, Bone *bone, void *ptr) {
        /* Set PCHAN_TRANS_UPDATE for channels with bones that don't have
         * the no calc flag set ... I hate this.
         */
@@ -2907,31 +3392,31 @@ int bone_nocalc2chan_trans_update(Object *ob, Bone *bone, void *ptr) {
        return 0;
 }
 
-void clear_gonna_move(void) {
+static void clear_gonna_move(void) {
        Base *base;
 
        /* clear the gonna move flag */
        for (base= FIRSTBASE; base; base= base->next) {
-               base->object->flag &= ~GONNA_MOVE;
+               base->object->flag &= ~OB_GONNA_MOVE;
        }
 }
 
-int is_parent_gonna_move(Object *ob) {
+static int is_parent_gonna_move(Object *ob) {
        if ( (ob->parent) &&
-                (ob->parent->flag & GONNA_MOVE) ) {
+                (ob->parent->flag & OB_GONNA_MOVE) ) {
                return 1;
        }
        return 0;
 }
 
-int is_constraint_target_gonna_move(Object *ob) {
+static int is_constraint_target_gonna_move(Object *ob) {
        Object *tarOb;
        bConstraint *con;
        bPoseChannel *chan;
 
        for (con = ob->constraints.first; con; con=con->next) {
-               if ( (tarOb = get_con_target(con)) ) {
-                       if (tarOb->flag & GONNA_MOVE )
+               if ( (tarOb = get_constraint_target(con)) ) {
+                       if (tarOb->flag & OB_GONNA_MOVE )
                                return 1;
                }
        }
@@ -2939,8 +3424,8 @@ int is_constraint_target_gonna_move(Object *ob) {
        if (ob->pose) {
                for (chan = ob->pose->chanbase.first; chan; chan=chan->next){
                        for (con = chan->constraints.first; con; con=con->next) {
-                               if ( (tarOb = get_con_target(con)) ) {
-                                       if (tarOb->flag & GONNA_MOVE )
+                               if ( (tarOb = get_constraint_target(con)) ) {
+                                       if (tarOb->flag & OB_GONNA_MOVE )
                                                return 1;
                                }
                        }
@@ -2950,7 +3435,7 @@ int is_constraint_target_gonna_move(Object *ob) {
        return 0;
 }
 
-void flag_moving_objects(void) {
+static void flag_moving_objects(void) {
        Base *base;
        int numgonnamove = 0, oldnumgonnamove = -1;
 
@@ -2962,19 +3447,19 @@ void flag_moving_objects(void) {
                oldnumgonnamove = numgonnamove;
                numgonnamove = 0;
                for (base= FIRSTBASE; base; base= base->next) {
-                       if (base->object->flag & GONNA_MOVE) {
+                       if (base->object->flag & OB_GONNA_MOVE) {
                                ++numgonnamove;
                        }
                        else if (base->flag & SELECT) {
-                               base->object->flag |= GONNA_MOVE;
+                               base->object->flag |= OB_GONNA_MOVE;
                                ++numgonnamove;
                        }
                        else if (is_parent_gonna_move(base->object)) {
-                               base->object->flag |= GONNA_MOVE;
+                               base->object->flag |= OB_GONNA_MOVE;
                                ++numgonnamove;
                        }
                        else if (is_constraint_target_gonna_move(base->object)) {
-                               base->object->flag |= GONNA_MOVE;
+                               base->object->flag |= OB_GONNA_MOVE;
                                ++numgonnamove;
                        }
                }
@@ -3006,8 +3491,8 @@ static int pose_do_update_flag(Object *ob) {
                                for (base= FIRSTBASE; base; base= base->next) {
                                        if (is_ob_constraint_target(base->object, 
                                                                                                &chan->constraints)) {
-                                               if( (base->object->flag & GONNA_MOVE) || 
-                                                       (ob->flag & GONNA_MOVE)) {
+                                               if( (base->object->flag & OB_GONNA_MOVE) || 
+                                                       (ob->flag & OB_GONNA_MOVE)) {
                                                        Bone *bone;
                                                        /* If this armature is selected, or if the
                                                         * object that is the target of a constraint
@@ -3036,6 +3521,9 @@ static int pose_do_update_flag(Object *ob) {
        return do_update;
 }
 
+/* this is a confusing call, it also does the constraint update flags, but was not used...
+   hopefully transform refactor will take care better of it (ton) */
+/* exposed int transform.c */
 void figure_pose_updating(void)
 {
        Base *base;
@@ -3046,8 +3534,17 @@ void figure_pose_updating(void)
                /* Recalculate the pose if necessary, regardless of
                 * whether the layer is visible or not.
                 */
-               if (pose_do_update_flag(base->object))
+               if (pose_do_update_flag(base->object)) {
                        base->flag |= BA_WHERE_UPDATE;
+               }
+               else if(base->object->flag & OB_GONNA_MOVE) {
+                       /* if position updates, deform info could change too */
+                       if(base->object->hooks.first) base->flag |= BA_DISP_UPDATE;
+                       else if(base->object->parent) {
+                               if(base->object->parent->type==OB_LATTICE || base->object->partype==PARSKEL)
+                                       base->flag |= BA_DISP_UPDATE;
+                       }
+               }
        }
 
 }
@@ -3064,8 +3561,18 @@ static void setbaseflags_for_editing(int mode)   /* 0,'g','r','s' */
                        base->flag= BA_PARSEL
                                
        */
-       GHash *object_to_base_hash= NULL; /* built on demand, see below - zr */
+       GHash *object_to_base_hash= NULL; 
        Base *base;
+
+       /* moved to start of function, it is needed for hooks now too */
+       if (!object_to_base_hash) {
+               Base *b;
+               object_to_base_hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+               
+               for (b= FIRSTBASE; b; b= b->next)
+                       BLI_ghash_insert(object_to_base_hash, b->object, b);
+       }
+       
        
        copy_baseflags();
 
@@ -3097,14 +3604,36 @@ static void setbaseflags_for_editing(int mode)  /* 0,'g','r','s' */
                                if(ika->parent && parsel) base->flag |= BA_WHERE_UPDATE;
                        }
                        
+                       if(ob->hooks.first) {
+                               Base *b;
+                               ObHook *hook= ob->hooks.first;
+                               
+                               while(hook) {
+                                       if(hook->parent) {
+                                               Object *parsel= is_a_parent_selected(hook->parent);
+                                               
+                                               b= BLI_ghash_lookup(object_to_base_hash, hook->parent);
+                                               if(parsel || ((base->flag | b->flag) & (SELECT | BA_PARSEL)) ) {
+                                                       base->flag |= BA_DISP_UPDATE;
+                                               }
+                                       }
+                                       hook= hook->next;
+                               }
+                       }
+                       
+                       if(ob->parent && ob->parent->type==OB_LATTICE)
+                               if(ob->parent->hooks.first) base->flag |= BA_DISP_UPDATE;
+                       
                        if(base->flag & (SELECT | BA_PARSEL)) {
                                
                                base->flag |= BA_WHERE_UPDATE;
                                
                                if(ob->parent) {
                                        if(ob->parent->type==OB_LATTICE) base->flag |= BA_DISP_UPDATE;
-                                       if(ob->parent->type==OB_IKA && ob->partype==PARSKEL) base->flag |= BA_DISP_UPDATE;
-                                       if(ob->parent->type==OB_ARMATURE && ob->partype==PARSKEL) base->flag |= BA_DISP_UPDATE;
+                                       else if(ob->partype==PARSKEL) {
+                                               if ELEM3(ob->parent->type, OB_IKA, OB_CURVE, OB_ARMATURE) 
+                                                       base->flag |= BA_DISP_UPDATE;
+                                       }
                                }
                                if(ob->track) {
                                        ;
@@ -3115,16 +3644,6 @@ static void setbaseflags_for_editing(int mode)   /* 0,'g','r','s' */
                                if(ob->type==OB_MBALL) {
                                        Base *b;
                                        
-                                               /* Only bother building the object to base
-                                                * hash if we are going to be needing it... - zr
-                                                */
-                                       if (!object_to_base_hash) {
-                                               object_to_base_hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
-                                               
-                                               for (b= FIRSTBASE; b; b= b->next)
-                                                       BLI_ghash_insert(object_to_base_hash, b->object, b);
-                                       }
-
                                        b= BLI_ghash_lookup(object_to_base_hash, find_basis_mball(ob));
                                        b->flag |= BA_DISP_UPDATE;
                                }
@@ -3430,44 +3949,94 @@ void make_trans_verts(float *min, float *max, int mode)
        Nurb *nu;
        BezTriple *bezt;
        BPoint *bp;
-       TransVert *tv;
+       TransVert *tv=NULL;
        MetaElem *ml;
        EditVert *eve;
-       int a;
        EditBone        *ebo;
-       tottrans= 0;
+       float total;
+       int a;
+
+       tottrans= 0; // global!
        
        INIT_MINMAX(min, max);
        centroid[0]=centroid[1]=centroid[2]= 0.0;
        
-       countall();
-       if(mode) tottrans= G.totvert;
-       else tottrans= G.totvertsel;
-       
-       if(G.totvertsel==0) {
-               tottrans= 0;
-               return;
+       /* note for transform refactor: dont rely on countall anymore... its ancient */
+       /* I skip it for editmesh now (ton) */
+       if(G.obedit->type!=OB_MESH) {
+               countall();
+               if(mode) tottrans= G.totvert;
+               else tottrans= G.totvertsel;
+
+               if(G.totvertsel==0) {
+                       tottrans= 0;
+                       return;
+               }
+               tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
        }
        
-       tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
-       
-       /* we count again because of hide */
+       /* we count again because of hide (old, not for mesh!) */
        tottrans= 0;
        
        if(G.obedit->type==OB_MESH) {
-               eve= em->verts.first;
-               while(eve) {
-                       if(eve->h==0) {
-                               if(mode==1 || (eve->f & 1)) {
+               int proptrans= 0;
+               
+               // transform now requires awareness for select mode, so we tag the f1 flags in verts
+               tottrans= 0;
+               if(G.scene->selectmode & SCE_SELECT_VERTEX) {
+                       for(eve= em->verts.first; eve; eve= eve->next) {
+                               if(eve->h==0 && (eve->f & SELECT)) {
+                                       eve->f1= SELECT;
+                                       tottrans++;
+                               }
+                               else eve->f1= 0;
+                       }
+               }
+               else if(G.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) {
+                               if(eed->h==0 && (eed->f & SELECT)) eed->v1->f1= eed->v2->f1= SELECT;
+                       }
+                       for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
+               }
+               else {
+                       EditFace *efa;
+                       for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
+                       for(efa= em->faces.first; efa; efa= efa->next) {
+                               if(efa->h==0 && (efa->f & SELECT)) {
+                                       efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
+                                       if(efa->v4) efa->v4->f1= SELECT;
+                               }
+                       }
+                       for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
+               }
+               
+               /* proportional edit exception... */
+               if(mode==1 && tottrans) {
+                       for(eve= em->verts.first; eve; eve= eve->next) {
+                               if(eve->h==0) {
+                                       eve->f1 |= 2;
+                                       proptrans++;
+                               }
+                       }
+                       if(proptrans>tottrans) tottrans= proptrans;
+               }
+               
+               /* and now make transverts */
+               if(tottrans) {
+                       tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
+
+                       for(eve= em->verts.first; eve; eve= eve->next) {
+                               if(eve->f1) {
                                        VECCOPY(tv->oldloc, eve->co);
                                        tv->loc= eve->co;
-                                       tv->nor= eve->no;
-                                       tv->flag= eve->f & 1;
+                                       if(eve->no[0]!=0.0 || eve->no[1]!=0.0 ||eve->no[2]!=0.0)
+                                               tv->nor= eve->no; // note this is a hackish signal (ton)
+                                       tv->flag= eve->f1 & SELECT;
                                        tv++;
-                                       tottrans++;
                                }
                        }
-                       eve= eve->next;
                }
        }
        else if (G.obedit->type==OB_ARMATURE){
@@ -3587,18 +4156,21 @@ void make_trans_verts(float *min, float *max, int mode)
        
        /* cent etc */
        tv= transvmain;
+       total= 0.0;
        for(a=0; a<tottrans; a++, tv++) {
-               if(tv->flag) {
+               if(tv->flag & SELECT) {
                        centroid[0]+= tv->oldloc[0];
                        centroid[1]+= tv->oldloc[1];
                        centroid[2]+= tv->oldloc[2];
-
+                       total+= 1.0;
                        DO_MINMAX(tv->oldloc, min, max);
                }
        }
-       centroid[0]/= G.totvertsel;
-       centroid[1]/= G.totvertsel;
-       centroid[2]/= G.totvertsel;
+       if(total!=0.0) {
+               centroid[0]/= total;
+               centroid[1]/= total;
+               centroid[2]/= total;
+       }
 
        centre[0]= (min[0]+max[0])/2.0;
        centre[1]= (min[1]+max[1])/2.0;
@@ -3606,18 +4178,20 @@ void make_trans_verts(float *min, float *max, int mode)
        
 }
 
+/* now only in use by drawimage.c */
 void draw_prop_circle()
 {
-       float tmat[4][4], imat[4][4];
-       
-       if(G.moving) {
+       if (G.f & G_PROPORTIONAL) {
+               float tmat[4][4], imat[4][4];
 
-               BIF_ThemeColor(TH_GRID);
+               if(G.moving) {
+                       BIF_ThemeColor(TH_GRID);
 
-               mygetmatrix(tmat);
-               Mat4Invert(imat, tmat);
+                       mygetmatrix(tmat);
+                       Mat4Invert(imat, tmat);
 
-               drawcircball(prop_cent, prop_size, imat);
+                       drawcircball(GL_LINE_LOOP, prop_cent, prop_size, imat);
+               }
        }
 }
 
@@ -3655,11 +4229,28 @@ void special_trans_update(int keyflags)
        IpoCurve *icu;
 
        if(G.obedit) {
+               if(G.obedit->type==OB_MESH) {
+                       recalc_editnormals();   // does face centers too
+               }
                if(G.obedit->type==OB_CURVE) {
                        cu= G.obedit->data;
-                       if(cu->flag & CU_3D) makeBevelList(G.obedit);
                        
+                       makeBevelList(G.obedit); // might be needed for deform
                        calc_curvepath(G.obedit);
+                       
+                       base= FIRSTBASE;
+                       while(base) {
+                               if(base->lay & G.vd->lay) {
+                                       if(base->object->parent==G.obedit && base->object->partype==PARSKEL)
+                                               makeDispList(base->object);
+                                       else if(base->object->type==OB_CURVE) {
+                                               Curve *cu= base->object->data;
+                                               if(G.obedit==cu->bevobj || G.obedit==cu->taperobj)
+                                                       makeDispList(base->object);
+                                       }
+                               }
+                               base= base->next;
+                       }
                }
                else if(G.obedit->type==OB_ARMATURE){
                        EditBone *ebo;
@@ -3795,7 +4386,6 @@ void special_aftertrans_update(char mode, int flip, short canceled, int keyflags
        Base *base;
        MetaBall *mb;
        Curve *cu;
-       Ika *ika;
        int doit,redrawipo=0;
 
        
@@ -3876,16 +4466,25 @@ void special_aftertrans_update(char mode, int flip, short canceled, int keyflags
                                
                                where_is_object(ob);
 
-                               if(ob->type==OB_IKA) {
-                                       ika= ob->data;                                  
-                                       VecMat4MulVecfl(ika->effg, ob->obmat, ika->eff);
-                                       itterate_ika(ob);
+                               if(ob->type==OB_ARMATURE && canceled) {
+                                       /* Unfortunately, sometimes when you escape
+                                        * a transform on an object that is the
+                                        * target of an IK constraint on an armature
+                                        * bone, the rotations are not restored
+                                        * correctly on the bones in the IK chain. 
+                                        * There is probably a nice, elegant way to fix 
+                                        * this using transdata, but this system is so 
+                                        * darn confusing that we'll do it this brute
+                                        * force way instead:
+                                        */
+                                       clear_pose_constraint_status(ob);
+                                       make_displists_by_armature(ob);
                                }
                        }
                        if(base->flag & BA_DISP_UPDATE) {
                                if(ob->type==OB_MBALL) {
                                        mb= ob->data;
-                                       if(mb->flag != MB_UPDATE_ALWAYS) makeDispList(ob);
+                                       if(mb->flag != MB_UPDATE_ALWAYS || G.obedit == NULL) makeDispList(ob);
                                }
                                if( give_parteff(ob) ) build_particle_system(ob);
                        }
@@ -3896,6 +4495,7 @@ void special_aftertrans_update(char mode, int flip, short canceled, int keyflags
                                cu= ob->data;
                                
                                if(cu->bevobj && (cu->bevobj->flag & SELECT) ) doit= 1;
+                               else if(cu->taperobj && (cu->taperobj->flag & SELECT) ) doit= 1;
                                else if(cu->textoncurve) {
                                        if(cu->textoncurve->flag & SELECT) doit= 1;
                                        else if(ob->flag & SELECT) doit= 1;
@@ -3912,8 +4512,12 @@ void special_aftertrans_update(char mode, int flip, short canceled, int keyflags
                                
                                if(cu->bevobj && (cu->bevobj->flag & SELECT) ) 
                                        makeDispList(ob);
+                               else if(cu->taperobj && (cu->taperobj->flag & SELECT) ) 
+                                       makeDispList(ob);
                        }
                        
+                       if(ob->softflag & OB_SB_ENABLE) sbObjectReset(ob);
+                       
                        where_is_object(ob);    /* always do, for track etc. */
 
                        /* Set autokey if necessary */
@@ -3973,23 +4577,6 @@ void calc_trans_verts(void)
        }
 }
 
-
-static int test_midtog_proj(short xn, short yn, short *mval)
-{
-       float x,y,z;
-
-       /* which movement is the largest? that'll be the one */
-       xn= (xn-mval[0]);
-       yn= (yn-mval[1]);
-       x = fabs(G.vd->persinv[0][0]*xn + G.vd->persinv[1][0]*yn);
-       y = fabs(G.vd->persinv[0][1]*xn + G.vd->persinv[1][1]*yn);
-       z = fabs(G.vd->persinv[0][2]*xn + G.vd->persinv[1][2]*yn);
-
-       if(x>=y && x>=z) return 0;
-       else if(y>=x && y>=z) return 1;
-       else return 2;
-}
-
 void apply_keyb_grid(float *val, float fac1, float fac2, float fac3, int invert)
 {
        /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */
@@ -4010,10 +4597,9 @@ void apply_keyb_grid(float *val, float fac1, float fac2, float fac3, int invert)
        else {
                if(fac1!= 0.0) *val= fac1*floor(*val/fac1 +.5);
        }
-       
 }
 
-
+/* exported to transform.c */
 void compatible_eul(float *eul, float *oldrot)
 {
        float dx, dy, dz;
@@ -4076,24 +4662,6 @@ void compatible_eul(float *eul, float *oldrot)
 
 }
 
-void headerprint(char *str)
-{
-       if(curarea->headertype) {
-               areawinset(curarea->headwin);
-               
-               headerbox(curarea);
-               cpack(0x0);
-               glRasterPos2i(20+curarea->headbutofs,  6);
-               BMF_DrawString(G.font, str);
-               
-               curarea->head_swap= WIN_BACK_OK;
-               areawinset(curarea->win);
-       }
-       else {
-               // dunno... thats for later (ton)
-       }
-}
-
 void add_ipo_tob_poin(float *poin, float *old, float delta)
 {
        if(poin) {
@@ -4210,1815 +4778,73 @@ int sphere_intersect_test(void)
        oldloc= v1->co;
        
        v1= v1->next;
-       VecSubf(speed, v1->co, oldloc);
-       len= Normalise(speed);
-       if(len==0.0) return 0;
-       
-       VecSubf(rc, oldloc, base);
-       bsq= rc[0]*speed[0] + rc[1]*speed[1] + rc[2]*speed[2]; 
-       u= rc[0]*rc[0] + rc[1]*rc[1] + rc[2]*rc[2] - editbutsize*editbutsize;
-
-       disc= bsq*bsq - u;
-       
-       if(disc>=0.0) {
-               disc= sqrt(disc);
-               labdacor= (-bsq - disc)/len;    /* entry point */
-               labda= (-bsq + disc)/len;
-               
-               printf("var1: %f, var2: %f, var3: %f\n", labdacor, labda, editbutsize);
-       }
-       else return 0;
-
-       /* intersection and normal */
-       rc[0]= oldloc[0] + labdacor*speed[0] - base[0];
-       rc[1]= oldloc[1] + labdacor*speed[1] - base[1];
-       rc[2]= oldloc[2] + labdacor*speed[2] - base[2];
-
-
-       return 1;
-}
-
-#ifndef CLOCKS_PER_SEC
-#define CLOCKS_PER_SEC 1000000
-#endif
-
-int my_clock(void)
-{
-       float ftime;
-       
-       ftime= (float)clock();
-       ftime*= 100.0/CLOCKS_PER_SEC;
-       
-       return (int)ftime;
-}
-
-static void view_editmove(unsigned char event)
-{
-       /* Regular:   Zoom in */
-       /* Shift:     Scroll up */
-       /* Ctrl:      Scroll right */
-       /* Alt-Shift: Rotate up */
-       /* Alt-Ctrl:  Rotate right */
-
-       switch(event) {
-               case WHEELUPMOUSE:
-
-                       if( G.qual & LR_SHIFTKEY ) {
-                               if( G.qual & LR_ALTKEY ) { 
-                                       G.qual &= ~LR_SHIFTKEY;
-                                       persptoetsen(PAD2);
-                                       G.qual |= LR_SHIFTKEY;
-                               } else {
-                                       persptoetsen(PAD2);
-                               }
-                       } else if( G.qual & LR_CTRLKEY ) {
-                               if( G.qual & LR_ALTKEY ) { 
-                                       G.qual &= ~LR_CTRLKEY;
-                                       persptoetsen(PAD4);
-                                       G.qual |= LR_CTRLKEY;
-                               } else {
-                                       persptoetsen(PAD4);
-                               }
-                       } else if(U.uiflag & USER_WHEELZOOMDIR) 
-                               persptoetsen(PADMINUS);
-                       else
-                               persptoetsen(PADPLUSKEY);
-
-                       break;
-               case WHEELDOWNMOUSE:
-                       if( G.qual & LR_SHIFTKEY ) {
-                               if( G.qual & LR_ALTKEY ) { 
-                                       G.qual &= ~LR_SHIFTKEY;
-                                       persptoetsen(PAD8);
-                                       G.qual |= LR_SHIFTKEY;
-                               } else {
-                                       persptoetsen(PAD8);
-                               }
-                       } else if( G.qual & LR_CTRLKEY ) {
-                               if( G.qual & LR_ALTKEY ) { 
-                                       G.qual &= ~LR_CTRLKEY;
-                                       persptoetsen(PAD6);
-                                       G.qual |= LR_CTRLKEY;
-                               } else {
-                                       persptoetsen(PAD6);
-                               }
-                       } else if(U.uiflag & USER_WHEELZOOMDIR) 
-                               persptoetsen(PADPLUSKEY);
-                       else
-                               persptoetsen(PADMINUS);
-                       
-                       break;
-       }
-}
-
-/* *********************** AXIS CONSTRAINT HELPER LINE *************** */
-
-static void constline(float *center, float *dir, char axis, float axismat[][3])
-{
-       extern void make_axis_color(char *col, char *col2, char axis);  // drawview.c
-       float v1[3], v2[3], v3[3];
-       char col[3], col2[3];
-       
-       if(G.obedit) mymultmatrix(G.obedit->obmat);     // sets opengl viewing
-
-       VecCopyf(v3, dir);
-       VecMulf(v3, G.vd->far);
-       
-       VecSubf(v2, center, v3);
-       VecAddf(v1, center, v3);
-
-       BIF_GetThemeColor3ubv(TH_GRID, col);
-       make_axis_color(col, col2, axis);
-       glColor3ubv(col2);
-
-       setlinestyle(0);
-       glBegin(GL_LINE_STRIP); 
-               glVertex3fv(v1); 
-               glVertex3fv(v2); 
-       glEnd();
-       
-       if(axismat) {
-               float mat[4][4];
-               
-               Mat4CpyMat3(mat, axismat);
-               VecAddf(mat[3], mat[3], center);
-               
-               mymultmatrix(mat);
-               BIF_ThemeColor(TH_TEXT);
-               drawaxes(2.0);
-       }
-       
-       myloadmatrix(G.vd->viewmat);
-       
-}
-
-
-#define XTRANS         0x01
-#define YTRANS         0x02
-#define ZTRANS         0x04
-#define TRANSLOCAL     0x80
-#define XTRANSLOCAL    (XTRANS|TRANSLOCAL)
-#define YTRANSLOCAL    (YTRANS|TRANSLOCAL)
-#define ZTRANSLOCAL    (ZTRANS|TRANSLOCAL)
-
-/* temporal storage for callback */
-struct constline_temp {
-       int mode, axismode, midtog;
-       float *centre, *vx, *vy, *vz;
-       float *imat;
-};
-
-static struct constline_temp cnst={0,0}; // init
-
-/* called while transform(), store the relevant values in struct  */
-static void set_constline_callback(int mode, int axismode, int midtog, 
-                                               float *centre, float imat[][3], float *vx, float *vy, float *vz)
-{
-       cnst.mode= mode;
-       cnst.axismode= axismode;
-       cnst.midtog= midtog;
-       cnst.centre= centre;
-       cnst.imat= (float *)imat;
-       cnst.vx= vx;
-       cnst.vy= vy;
-       cnst.vz= vz;
-}
-
-/* is called from drawview.c after drawing objects */
-void constline_callback(void)
-{
-       TransOb *tob;
-       int a;
-       
-       if(cnst.mode==0 || cnst.axismode==0) return;    // uninitialized or no helpline
-       
-       // check further:
-       if( (cnst.mode == 'C') || (cnst.mode == 'w') || (cnst.mode=='N') ) return; 
-       if( ((cnst.mode=='R')||(cnst.mode=='r')) && (cnst.midtog) ) return;
-               
-       if(G.obedit) {  // only one helpline in editmode
-               float matone[3][3];
-               Mat3One(matone);
-               
-               switch (cnst.axismode) {
-               case XTRANSLOCAL: constline(cnst.centre, cnst.vx, 'x', matone); break;
-               case YTRANSLOCAL: constline(cnst.centre, cnst.vy, 'y', matone); break;
-               case ZTRANSLOCAL: constline(cnst.centre, cnst.vz, 'z', matone); break;
-               case XTRANS: constline(cnst.centre, cnst.imat, 'x', NULL); break;
-               case YTRANS: constline(cnst.centre, cnst.imat+3, 'y', NULL); break;
-               case ZTRANS: constline(cnst.centre, cnst.imat+6, 'z', NULL); break;
-               }
-       }
-       else if(cnst.axismode < TRANSLOCAL) {   // for multiple objects one helpline...
-               switch (cnst.axismode) {
-               case XTRANS: constline(cnst.centre, cnst.vx, 'x', NULL); break;
-               case YTRANS: constline(cnst.centre, cnst.vy, 'y', NULL); break;
-               case ZTRANS: constline(cnst.centre, cnst.vz, 'z', NULL); break;
-               }
-       }
-       else {  // unless it's local transform
-               tob= transmain;
-               for(a=0; a<tottrans; a++, tob++) {
-                       switch (cnst.axismode) {
-                       case XTRANSLOCAL: constline(tob->loc, tob->axismat[0], 'x', tob->axismat); break;
-                       case YTRANSLOCAL: constline(tob->loc, tob->axismat[1], 'y', tob->axismat); break;
-                       case ZTRANSLOCAL: constline(tob->loc, tob->axismat[2], 'z', tob->axismat); break;
-                       }
-               }
-       }
-}
-
-/* *********************** END AXIS CONSTRAINT HELPER LINE *************** */
-/* *********************** TRANSFORM()  *************** */
-
-static char *transform_mode_to_string(int mode)
-{
-       switch(mode) {
-               case 'g':       return("Grab"); break;
-               case 's':       return("Scale"); break;
-               case 'r':       return("Rotate"); break;
-               case 'G':       return("Grab proportional"); break;
-               case 'C':       return("Scale proportional"); break;
-               case 'R':       return("Rotate proportional"); break;
-               case 'S':       return("Shear"); break;
-               case 'N':       return("Shrink/Fatten"); break;
-               case 'w':       return("Warp"); break;
-               case 'd':       return("Duplicate"); break;
-               default:        return("Transform");
-       }
-}
-
-/* 
-'g' 'G' -> Grab / Grab with PET
-'r' 'R' -> Rotate / Rotate with PET
-'s' 'C' -> Scale / Scale with PET
-'S'            -> Shear
-'t'            -> Tilt
-'w'            -> Warp
-'N'            -> Shrink/Fatten
-'V'            -> Snap vertice
-*/
-void transform(int mode)
-{
-       short canceled = 0;
-       TransOb *tob;
-       TransVert *tv;
-       float vec[3], min[3], max[3], dvec[3], d_dvec[3], dvecp[3], rot0[3], rot1[3], rot2[3], axis[3];
-       float totmat[3][3], omat[3][3], imat[3][3], mat[3][3], tmat[3][3], phi, dphi;
-
-       float persinv[3][3], persmat[3][3], viewinv[4][4], imat4[4][4];
-       float *curs, dx1, dx2, dy1, dy2, eul[3], quat[4], rot[3], phi0, phi1, deler, rad = 0.0;
-       float sizefac, size[3], sizelo[3], smat[3][3], xref=1.0, yref=1.0, zref= 1.0;
-       float si, co, dist, startomtrekfac = 0.0, omtrekfac, oldval[3];
-       int axismode=0, time, fast=0, a, midtog=0, firsttime=1, fout= 0, cameragrab= 0, gridflag;
-       unsigned short event=0;
-       short mval[2], afbreek=0, doit, xn, yn, xc, yc, xo, yo = 0, val;
-       char str[100];
-       int     keyflags = 0;
-
-       float addvec[3] = {0,0,0}; // for new typing code
-       short ax = 0, del = 0, typemode = 0; // also for new typing thingy
-       short pe[3] = {0,0,0}; // again for the same thing. Determines if the period key has been pressed.
-       short mi[3] = {1,1,1}; // same thing again. Determines whether or not the minus key has been pressed (in order to add or substract new numbers).
-       short numchange[3] = {0,0,0}; // Determines whether or not one axis recieved changes (mainly for scaling)
-
-       float vx[3] = {1,0,0}, vy[3] = {0,1,0}, vz[3] = {0,0,1};
-               
-       if (mode % 'x' == 0)
-               axismode = XTRANSLOCAL;
-       else if (mode % 'X' == 0)
-               axismode = XTRANS;
-       else if (mode % 'y' == 0)
-               axismode = YTRANSLOCAL;
-       else if (mode % 'Y' == 0)
-               axismode = YTRANS;
-       else if (mode % 'z' == 0)
-               axismode = ZTRANSLOCAL;
-       else if (mode % 'Z' == 0)
-               axismode = ZTRANS;
-       
-       if (mode % 'g' == 0)
-               mode = 'g';
-       else if (mode % 'r' == 0)
-               mode = 'r';
-       else if (mode % 's' == 0)
-               mode = 's';
-
-       if(G.obedit && (G.f & G_PROPORTIONAL)) {
-               if(mode=='g') mode= 'G';
-               if(mode=='r') mode= 'R';
-               if(mode=='s') mode= 'C';
-       }
-       /* form duplicate routines */
-       if(mode=='d') mode= 'g';
-
-       /* this can cause floating exception at dec alpha */
-       d_dvec[0]= d_dvec[1]= d_dvec[2]= 0.0;
-       dvec[0]= dvec[1]= dvec[2]= 0.0;
-       
-       if(G.scene->id.lib) return;
-       
-       if(mode=='t') {
-               if(G.obedit==0 || G.obedit->type!=OB_CURVE) return;
-       }
-       if(mode=='w' && G.obedit==0) return;
-       
-       if (G.obedit && G.obedit->type == OB_MESH) {
-               undo_push_mesh(transform_mode_to_string(mode));
-       }
-
-       /* what data will be involved? */
-       if(G.obedit) {
-               if(mode=='N') vertexnormals(0);
-       
-               /* min en max needed for warp */
-               if(mode=='G' || mode=='R' || mode=='C') make_trans_verts(min, max, 1);
-               else make_trans_verts(min, max, 0);
-       }
-       else if (G.obpose){
-
-               switch (G.obpose->type) {
-               case OB_ARMATURE:
-                       /* figure out which bones need calculating */
-                       figure_bone_nocalc(G.obpose);
-                       figure_pose_updating();
-                       make_trans_bones(mode);
-                       break;
-               }
-       }
-       else {
-               int opt= 0;
-               if (mode=='g' || mode=='G') opt= 'g';
-               else if (mode=='r' || mode=='R') opt= 'r';
-               else if (mode=='s' || mode=='S') opt= 's';
-               
-               setbaseflags_for_editing(opt);
-               figure_pose_updating();
-               make_trans_objects();
-       }
-       
-       if(tottrans==0) {
-               if(G.obedit==0) clearbaseflags_for_editing();
-               return;
-       }
-       
-       if(G.obedit==0 && mode=='S') return;
-       
-       if(G.vd->around==V3D_LOCAL) {
-               if(G.obedit) {
-                       centre[0]= centre[1]= centre[2]= 0.0;
-               }
-
-       }
-       if(G.vd->around==V3D_CENTROID) {
-               VECCOPY(centre, centroid);
-       }
-       else if(G.vd->around==V3D_CURSOR) {
-               curs= give_cursor();
-               VECCOPY(centre, curs);
-               
-               if(G.obedit) {
-                       VecSubf(centre, centre, G.obedit->obmat[3]);
-                       Mat3CpyMat4(mat, G.obedit->obmat);
-                       Mat3Inv(imat, mat);
-                       Mat3MulVecfl(imat, centre);
-               }
-
-       }
-       
-       /* Always rotate around object centroid */
-       if (G.obpose){
-               VECCOPY (centre, centroid);
-       }
-
-       /* moving: is shown in drawobject() */
-       if(G.obedit) G.moving= 2;
-       else G.moving= 1;
-       
-       areawinset(curarea->win);
-       
-       /* the persinv is polluted with translation, do not use!! */
-       Mat3CpyMat4(persmat, G.vd->persmat);
-       Mat3Inv(persinv, persmat);
-       
-       VECCOPY(rot0, persinv[0]);
-       Normalise(rot0);
-       VECCOPY(rot1, persinv[1]);
-       Normalise(rot1);
-       VECCOPY(rot2, persinv[2]);
-       Normalise(rot2);
-
-       /* init vars */
-
-       Mat4Invert(viewinv, G.vd->viewmat);
-
-       if(transvmain) {
-               VECCOPY(vec, centre);
-               Mat4MulVecfl(G.obedit->obmat, vec);
-               initgrabz(vec[0], vec[1], vec[2]);
-               project_short_noclip(vec, mval);
-       }
-       else {
-               /* voor panning from cameraview */
-               if( G.vd->camera==OBACT && G.vd->persp>1) {
-                       /* 6.0 = 6 grid units */
-                       centre[0]+= -6.0*rot2[0];
-                       centre[1]+= -6.0*rot2[1];
-                       centre[2]+= -6.0*rot2[2];
-               }
-               
-               initgrabz(centre[0], centre[1], centre[2]);
-               project_short_noclip(centre, mval);
-
-               if( G.vd->camera==OBACT && G.vd->persp>1) {
-                       centre[0]+= 6.0*rot2[0];
-                       centre[1]+= 6.0*rot2[1];
-                       centre[2]+= 6.0*rot2[2];
-               }
-       }
-       
-       VECCOPY(prop_cent, centre);
-
-       xc= mval[0];
-       yc= mval[1];
-
-       if(G.obedit) {
-               Mat3CpyMat4(omat, G.obedit->obmat);
-               Mat3Inv(imat, omat);
-               
-               Mat4Invert(imat4, G.obedit->obmat);
-       }
-
-       else if(G.obpose) {
-               Mat3CpyMat4(omat, G.obpose->obmat);
-               Mat3Inv(imat, omat);
-               
-               Mat4Invert(imat4, G.obpose->obmat);
-       }
-
-       else {
-               if(transmain) {
-                       if(OBACT &&  G.vd->persp>1 && G.vd->camera==OBACT) {
-                               cameragrab= 1;
-                               xc= curarea->winx/2;
-                               yc= curarea->winy/2;
-                       }
-               }
-       }
-       
-       if((mode=='r' || mode=='s' || mode=='S') && xc==32000) {
-               error("centre far out of view");
-               fout= 1;
-       }
-
-       if(mode=='w' && G.obedit) {
-               Mat4MulVecfl(G.obedit->obmat, min);
-               Mat4MulVecfl(G.vd->viewmat, min);
-               Mat4MulVecfl(G.obedit->obmat, max);
-               Mat4MulVecfl(G.vd->viewmat, max);
-               
-               centre[0]= (min[0]+max[0])/2.0;
-               centre[1]= (min[1]+max[1])/2.0;
-               centre[2]= (min[2]+max[2])/2.0;
-
-                       /* cursor is centre */
-               curs= give_cursor();
-               VECCOPY(axis, curs);
-               Mat4MulVecfl(G.vd->viewmat, axis);
-               rad= sqrt( (axis[0]-centre[0])*(axis[0]-centre[0])+(axis[1]-centre[1])*(axis[1]-centre[1]) );
-               dist= max[0]-centre[0];
-               if(dist==0.0) fout= 1;
-               else startomtrekfac= (90*rad*M_PI)/(360.0*dist);
-       }
-
-       getmouseco_areawin(mval);
-       xn=xo= mval[0];
-       yn=xo= mval[1];
-       dx1= xc-xn; 
-       dy1= yc-yn;
-       phi= phi0= phi1= 0.0;
-       
-       sizefac= sqrt( (float)((yc-yn)*(yc-yn)+(xn-xc)*(xn-xc)) );
-       if(sizefac<2.0) sizefac= 2.0;
-
-       gridflag= U.flag;
-       
-       while(fout==0 && afbreek==0) {
-               
-               getmouseco_areawin(mval);
-               if(mval[0]!=xo || mval[1]!=yo || firsttime) {
-                       if(firsttime) {
-                               
-                               /* not really nice, but who cares! */
-                               oldval[0]= oldval[1]= oldval[2]= MAXFLOAT;
-                               
-                               /* proportional precalc */
-                               if(mode=='G' || mode=='R' || mode=='C') {
-                                       if(transvmain) {
-                                               tv= transvmain;
-                                               for(a=0; a<tottrans; a++, tv++) {
-                                                       set_proportional_weight(tv, min, max);
-                                               }
-                                       }
-                               }
-                       }
-                       firsttime= 0;
-                       
-                       if(mode=='g' || mode=='G') {
-                               char gmode[10] = "";
-
-                               keyflags |= KEYFLAG_LOC;
-
-                               if (axismode==XTRANSLOCAL) strcpy(gmode, "Local X: ");
-                               if (axismode==YTRANSLOCAL) strcpy(gmode, "Local Y: ");
-                               if (axismode==ZTRANSLOCAL) strcpy(gmode, "Local Z: ");
-                               if (axismode==XTRANS) strcpy(gmode, "X Axis: ");
-                               if (axismode==YTRANS) strcpy(gmode, "Y Axis: ");
-                               if (axismode==ZTRANS) strcpy(gmode, "Z Axis: ");
-                               
-                               if(axismode) {
-                                       if(cameragrab) {
-                                               dx1= 0.002*(mval[1]-yn)*G.vd->grid;
-                                               dvec[0]-= dx1*G.vd->viewinv[2][0];
-                                               dvec[1]-= dx1*G.vd->viewinv[2][1];
-                                               dvec[2]-= dx1*G.vd->viewinv[2][2];
-                                               firsttime= 1;   /* so it keeps going */
-                                       }
-                                       else {
-                                               window_to_3d(dvec, mval[0]-xn, mval[1]-yn);
-                                               if(axismode & XTRANS) dvec[1]=dvec[2]= 0.0;
-                                               if(axismode & YTRANS) dvec[0]=dvec[2]= 0.0;
-                                               if(axismode & ZTRANS) dvec[0]=dvec[1]= 0.0;
-                                       }
-                               }
-                               else window_to_3d(dvec, mval[0]-xn, mval[1]-yn);
-
-                               if (typemode){
-                                       dvec[0] = addvec[0];
-                                       dvec[1] = addvec[1];
-                                       dvec[2] = addvec[2];
-                                       if(axismode == XTRANS) dvec[1]=dvec[2]= 0.0;
-                                       if(axismode == YTRANS) dvec[0]=dvec[2]= 0.0;
-                                       if(axismode == ZTRANS) dvec[0]=dvec[1]= 0.0;
-                               }
-
-                               /* grids */
-                               if(G.qual & LR_SHIFTKEY) {
-                                       dvec[0]= 0.1*(dvec[0]-d_dvec[0])+d_dvec[0];
-                                       dvec[1]= 0.1*(dvec[1]-d_dvec[1])+d_dvec[1];
-                                       dvec[2]= 0.1*(dvec[2]-d_dvec[2])+d_dvec[2];
-                               }
-                               apply_keyb_grid(dvec, 0.0, G.vd->grid, 0.1*G.vd->grid, gridflag & USER_AUTOGRABGRID);
-                               apply_keyb_grid(dvec+1, 0.0, G.vd->grid, 0.1*G.vd->grid, gridflag & USER_AUTOGRABGRID);
-                               apply_keyb_grid(dvec+2, 0.0, G.vd->grid, 0.1*G.vd->grid, gridflag & USER_AUTOGRABGRID);
-
-                               if(dvec[0]!=oldval[0] ||dvec[1]!=oldval[1] ||dvec[2]!=oldval[2]) {
-                                       VECCOPY(oldval, dvec);
-                                       
-                                       /* speedup for vertices */
-                                       if (G.obedit) {
-                                               VECCOPY(dvecp, dvec);
-                                               if (axismode&TRANSLOCAL && typemode) {
-                                                       if(axismode==XTRANSLOCAL) dvecp[1]=dvecp[2]=0;
-                                                       if(axismode==YTRANSLOCAL) dvecp[0]=dvecp[2]=0;
-                                                       if(axismode==ZTRANSLOCAL) dvecp[0]=dvecp[1]=0;
-                                                       VECCOPY(dvec, dvecp);
-                                               }
-                                               else {
-                                                       Mat3MulVecfl(imat, dvecp);
-                                                       if(axismode==XTRANSLOCAL) dvecp[1]=dvecp[2]=0;
-                                                       if(axismode==YTRANSLOCAL) dvecp[0]=dvecp[2]=0;
-                                                       if(axismode==ZTRANSLOCAL) dvecp[0]=dvecp[1]=0;
-                                                       if(axismode&TRANSLOCAL){
-                                                               VECCOPY(dvec, dvecp);
-                                                               Mat3MulVecfl(omat, dvec);
-                                                       }
-                                               }
-                                       }
-
-                                       
-                                       /* apply */
-                                       tob= transmain;
-                                       tv= transvmain;
-                                       for(a=0; a<tottrans; a++, tob++, tv++) {
-                                               
-                                               if(transmain) {
-                                                       VECCOPY(dvecp, dvec);
-                                                       if(axismode & TRANSLOCAL)
-                                                               Mat3MulVecfl(tob->axismat, dvecp);
-                                                       
-                                                       if(transmode==TRANS_TEX) Mat3MulVecfl(tob->obinv, dvecp);
-
-                                                       if(tob->flag & TOB_IKA) {
-                                                               VecAddf(tob->eff, tob->oldeff, dvecp);
-                                                       }
-                                                       else
-                                                               Mat3MulVecfl(tob->parinv, dvecp);
-                                                       
-                                                       if(tob->flag & TOB_IPO) {
-                                                               add_ipo_tob_poin(tob->locx, tob->oldloc, dvecp[0]);
-                                                               add_ipo_tob_poin(tob->locy, tob->oldloc+1, dvecp[1]);
-                                                               add_ipo_tob_poin(tob->locz, tob->oldloc+2, dvecp[2]);
-                                                       }
-                                                       else if(tob->loc) {
-                                                               VecAddf(tob->loc, tob->oldloc, dvecp);
-                                                       }
-                                               }
-                                               else {
-                                                       if(mode=='G') {
-                                                               tv->loc[0]= tv->oldloc[0]+tv->fac*dvecp[0];
-                                                               tv->loc[1]= tv->oldloc[1]+tv->fac*dvecp[1];
-                                                               tv->loc[2]= tv->oldloc[2]+tv->fac*dvecp[2];
-                                                       }
-                                                       else VecAddf(tv->loc, tv->oldloc, dvecp);
-                                               }
-
-                                       }
-                                       if (typemode){
-                                               switch (ax){
-                                               case 0:
-                                                       sprintf(str, "%sDx: >%.4f<   Dy: %.4f  Dz: %.4f", gmode, dvec[0], dvec[1], dvec[2]);
-                                                       break;
-                                               case 1:
-                                                       sprintf(str, "%sDx: %.4f   Dy: >%.4f<  Dz: %.4f", gmode, dvec[0], dvec[1], dvec[2]);
-                                                       break;
-                                               case 2:
-                                                       sprintf(str, "%sDx: %.4f   Dy: %.4f  Dz: >%.4f<", gmode, dvec[0], dvec[1], dvec[2]);
-                                               }
-                                       }
-                                       else
-                                               sprintf(str, "%sDx: %.4f   Dy: %.4f  Dz: %.4f", gmode, dvec[0], dvec[1], dvec[2]);
-                                       headerprint(str);
-
-                                       time= my_clock();
-
-                                       if(G.obedit) calc_trans_verts();
-                                       special_trans_update(keyflags);
-                                       
-                                       if (cameragrab && midtog)
-                                               set_constline_callback(mode, ZTRANSLOCAL, midtog, centre, imat, vx, vy, vz);
-                                       else
-                                               set_constline_callback(mode, axismode, midtog, centre, imat, vx, vy, vz);
-
-                                       if(fast==0) {
-                                               force_draw();
-                                               time= my_clock()-time;
-                                               if(time>50) fast= 1;
-                                       }
-                                       else {
-                                               scrarea_do_windraw(curarea);
-                                               screen_swapbuffers();
-                                       }
-                               }
-                       }
-                       else if(mode=='r' || mode=='t' || mode=='R') {
-                               int turntable = 0;
-                               doit= 0;
-                               keyflags |= KEYFLAG_ROT;
-                               dx2= xc-mval[0];
-                               dy2= yc-mval[1];
-                               
-                               if(midtog && (mode=='r' || mode=='R')) {
-                                       turntable = 1;
-                                       phi0+= .007*(float)(dy2-dy1);
-                                       phi1+= .007*(float)(dx1-dx2);
-                               
-                                       apply_keyb_grid(&phi0, 0.0, (5.0/180)*M_PI, (1.0/180)*M_PI, gridflag & USER_AUTOROTGRID);
-                                       apply_keyb_grid(&phi1, 0.0, (5.0/180)*M_PI, (1.0/180)*M_PI, gridflag & USER_AUTOROTGRID);
-
-                                       if(typemode){
-                                               VecRotToMat3(rot0, addvec[1]*M_PI/180.0, smat);
-                                               VecRotToMat3(rot1, addvec[2]*M_PI/180.0, totmat);
-
-                                               Mat3MulMat3(mat, smat, totmat);
-                                               doit= 1;
-                                       }
-                                       else if(oldval[0]!=phi0 || oldval[1]!=phi1){
-                                               VecRotToMat3(rot0, phi0, smat);
-                                               VecRotToMat3(rot1, phi1, totmat);
-
-                                               Mat3MulMat3(mat, smat, totmat);
-                                               dx1= dx2;
-                                               dy1= dy2;
-                                               oldval[0]= phi0;
-                                               oldval[1]= phi1;
-                                               doit= 1;
-                                       }
-                               }
-                               else {
-                                       deler= sqrt( (dx1*dx1+dy1*dy1)*(dx2*dx2+dy2*dy2));
-                                       if(deler>1.0) {
-                                       
-                                               dphi= (dx1*dx2+dy1*dy2)/deler;
-                                               dphi= saacos(dphi);
-                                               if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi;
-                                                               
-                                               if(G.qual & LR_SHIFTKEY) phi+= dphi/30.0;
-                                               else phi+= dphi;
-                                               
-                                               apply_keyb_grid(&phi, 0.0, (5.0/180)*M_PI, (1.0/180)*M_PI, gridflag & USER_AUTOROTGRID);
-
-                                               if(axismode) {
-                                                       if(axismode==XTRANS) vec[0]= -1.0; else vec[0]= 0.0;
-                                                       if(axismode==YTRANS) vec[1]= 1.0; else vec[1]= 0.0;
-                                                       if(axismode==ZTRANS) vec[2]= -1.0; else vec[2]= 0.0;
-                                                       if (G.obedit){
-                                                               if (axismode == XTRANSLOCAL) VECCOPY(vec, G.obedit->obmat[0]);
-                                                               if (axismode == YTRANSLOCAL) VECCOPY(vec, G.obedit->obmat[1]);
-                                                               if (axismode == ZTRANSLOCAL) VECCOPY(vec, G.obedit->obmat[2]);
-                                                               if (axismode & TRANSLOCAL) VecMulf(vec, -1.0);
-                                                       }
-                                               }
-                                               
-                                               if(typemode){
-                                                       doit= 1;
-                                                       if(axismode) {
-                                                               VecRotToMat3(vec, addvec[0]*M_PI/180.0, mat);
-                                                       }
-                                                       else VecRotToMat3(rot2, addvec[0]*M_PI/180.0, mat);
-                                               }
-                                               else if(oldval[2]!=phi) {
-                                                       dx1= dx2; 
-                                                       dy1= dy2;
-                                                       oldval[2]= phi;
-                                                       doit= 1;
-                                                       if(axismode) {
-                                                               VecRotToMat3(vec, phi, mat);
-                                                       }
-                                                       else VecRotToMat3(rot2, phi, mat);
-                                               }
-                                       }
-
-                               }
-                               if(doit) {
-                                       /* apply */
-                                       tob= transmain;
-                                       tv= transvmain;
-                                       
-                                       for(a=0; a<tottrans; a++, tob++, tv++) {
-                                               if(transmain) {
-                                                       /* rotation in three steps:
-                                                        * 1. editrot correction for parent
-                                                        * 2. distill from this the euler. Always do this step because MatToEul is pretty weak
-                                                        * 3. multiply with its own rotation, calculate euler.
-                                                        */
-                                               
-                                                       /* Roll around local axis */
-                                                       if (mode=='r' || mode=='R'){
-
-                                                               if (tob && axismode && (turntable == 0)){
-                                                                       if (axismode == XTRANSLOCAL){ 
-                                                                               VECCOPY(vec, tob->axismat[0]);
-                                                                       }
-                                                                       if (axismode == YTRANSLOCAL){
-                                                                               VECCOPY(vec, tob->axismat[1]);
-                                                                       }
-                                                                       if (axismode == ZTRANSLOCAL){
-                                                                               VECCOPY(vec, tob->axismat[2]);
-                                                                       }
-                                                                       /* Correct the vector */
-                                                                       if ((axismode & TRANSLOCAL) && ((G.vd->viewmat[0][2] * vec[0]+G.vd->viewmat[1][2] * vec[1]+G.vd->viewmat[2][2] * vec[2])>0)){
-                                                                               vec[0]*=-1;
-                                                                               vec[1]*=-1;
-                                                                               vec[2]*=-1;
-                                                                       }
-
-                                                                       if (typemode)
-                                                                               VecRotToMat3(vec, addvec[0] * M_PI / 180.0, mat);
-                                                                       else
-                                                                               VecRotToMat3(vec, phi, mat);
-                                                                               
-                                                               }
-                                                       }
-                                                       Mat3MulSerie(smat, tob->parmat, mat, tob->parinv, 0, 0, 0, 0, 0);
-
-                                                       /* 2 */
-                                                       if( (tob->ob->transflag & OB_QUAT) == 0 && tob->rot){
-                                                               Mat3ToEul(smat, eul);
-                                                               EulToMat3(eul, smat);
-                                                       }
-                                               
-                                                       /* 3 */
-                                                       /* we now work with rot+drot */
-                                                               
-                                                       if(tob->ob->transflag & OB_QUAT || !tob->rot) {
-                                                       
-                                                               /* drot+rot TO DO! */
-                                                               Mat3ToQuat(smat, quat); // Original
-                                                               QuatMul(tob->quat, quat, tob->oldquat);
-                                                               
-                                                               if(tob->flag & TOB_IPO) {
-                                                                       
-                                                                       if(tob->flag & TOB_IPODROT) {
-                                                                               /* VecSubf(rot, eul, tob->oldrot); */
-                                                                       }
-                                                                       else {
-                                                                               /* VecSubf(rot, eul, tob->olddrot); */
-                                                                       }
-       
-                                                                       /* VecMulf(rot, 9.0/M_PI_2); */
-                                                                       /* VecSubf(rot, rot, tob->oldrot+3); */
-
-                                                                       /* add_ipo_tob_poin(tob->rotx, tob->oldrot+3, rot[0]); */
-                                                                       /* add_ipo_tob_poin(tob->roty, tob->oldrot+4, rot[1]); */
-                                                                       /* add_ipo_tob_poin(tob->rotz, tob->oldrot+5, rot[2]); */
-       
-                                                               }
-                                                               else {
-                                                                       /* QuatSub(tob->quat, quat, tob->oldquat); */
-                                                               }
-                                                       }
-                                                       else {
-                                                               VecAddf(eul, tob->oldrot, tob->olddrot);
-                                                               EulToMat3(eul, tmat);
-
-                                                               Mat3MulMat3(totmat, smat, tmat);
-
-                                                               Mat3ToEul(totmat, eul);
-
-                                                               /* Eul is not allowed to differ too much from old eul.
-                                                                * This has only been tested for dx && dz
-                                                                */
-                                                               
-                                                               compatible_eul(eul, tob->oldrot);
-                                                       
-                                                               if(tob->flag & TOB_IPO) {
-                                                                       
-                                                                       if(tob->flag & TOB_IPODROT) {
-                                                                               VecSubf(rot, eul, tob->oldrot);
-                                                                       }
-                                                                       else {
-                                                                               VecSubf(rot, eul, tob->olddrot);
-                                                                       }
-       
-                                                                       VecMulf(rot, 9.0/M_PI_2);
-                                                                       VecSubf(rot, rot, tob->oldrot+3);
-
-
-                                                                       add_ipo_tob_poin(tob->rotx, tob->oldrot+3, rot[0]);
-                                                                       add_ipo_tob_poin(tob->roty, tob->oldrot+4, rot[1]);
-                                                                       add_ipo_tob_poin(tob->rotz, tob->oldrot+5, rot[2]);
-       
-                                                               }
-                                                               else {
-                                                                       VecSubf(tob->rot, eul, tob->olddrot);
-                                                               }
-                                                               
-                                                               /* See if we've moved */
-                                                               if (!VecCompare (tob->loc, tob->oldloc, 0.01)){
-                                                                       keyflags |= KEYFLAG_LOC;
-                                                               }
-
-                                                       }
-                                                       
-                                                       if(G.vd->around!=V3D_LOCAL && (!G.obpose))  {
-                                                               float vec[3];   // make local, the other vec stores rot axis
-                                                               
-                                                               /* translation */
-                                                               VecSubf(vec, tob->obvec, centre);
-                                                               Mat3MulVecfl(mat, vec);
-                                                               VecAddf(vec, vec, centre);
-                                                               /* vec now is the location where the object has to be */
-                                                               VecSubf(vec, vec, tob->obvec);
-                                                               Mat3MulVecfl(tob->parinv, vec);
-                                                               
-                                                               if(tob->flag & TOB_IPO) {
-                                                                       add_ipo_tob_poin(tob->locx, tob->oldloc, vec[0]);
-                                                                       add_ipo_tob_poin(tob->locy, tob->oldloc+1, vec[1]);
-                                                                       add_ipo_tob_poin(tob->locz, tob->oldloc+2, vec[2]);
-                                                               }
-                                                               else if(tob->loc) {
-                                                                       VecAddf(tob->loc, tob->oldloc, vec);
-                                                               }
-                                                       }
-                                               }
-                                               else {
-                                                       if(mode=='t') {
-                                                               if(tv->val) *(tv->val)= tv->oldval-phi;
-                                                       }
-                                                       else {
-                                                       
-                                                               if(mode=='R') {
-
-                                                                       if(midtog) {
-                                                                               if (typemode){
-                                                                                       VecRotToMat3(rot0, tv->fac*addvec[1] * M_PI / 180.0, smat);
-                                                                                       VecRotToMat3(rot1, tv->fac*addvec[2] * M_PI / 180.0, totmat);
-                                                                               }
-                                                                               else{
-                                                                                       VecRotToMat3(rot0, tv->fac*phi0, smat);
-                                                                                       VecRotToMat3(rot1, tv->fac*phi1, totmat);
-                                                                               }
-
-                                                                               Mat3MulMat3(mat, smat, totmat);
-                                                                       }
-                                                                       else {
-                                                                               if (typemode)
-                                                                                       VecRotToMat3(rot2, tv->fac*addvec[0] * M_PI / 180.0, mat);
-                                                                               else
-                                                                                       VecRotToMat3(rot2, tv->fac*phi, mat);
-                                                                       }
-                                                                       
-                                                               }
-
-                                                               Mat3MulMat3(totmat, mat, omat);
-                                                               Mat3MulMat3(smat, imat, totmat);
-                                                       
-                                                               VecSubf(vec, tv->oldloc, centre);
-                                                               Mat3MulVecfl(smat, vec);
-                                                               
-                                                               VecAddf(tv->loc, vec, centre);
-                                                       }
-                                               }
-                                       }
-                                       
-                                       
-                                       if(midtog){
-                                               if (typemode){
-                                                       if (ax == 1)
-                                                               sprintf(str, "Rotx: >%.2f<  Roty: %.2f", addvec[1], addvec[2]);
-                                                       if (ax == 2)
-                                                               sprintf(str, "Rotx: %.2f  Roty: >%.2f<", addvec[1], addvec[2]);
-                                               }
-                                               else
-                                                       sprintf(str, "Rotx: %.2f  Roty: %.2f", 180.0*phi0/M_PI, 180.0*phi1/M_PI);
-                                       }
-                                       else if(axismode) {
-                                               if (typemode){
-                                                       if(axismode==XTRANS) sprintf(str, "Rot X: >%.2f<", addvec[0]);
-                                                       else if(axismode==YTRANS) sprintf(str, "Rot Y: >%.2f<", addvec[0]);
-                                                       else if(axismode==ZTRANS) sprintf(str, "Rot Z: >%.2f<", addvec[0]);
-                                                       else if(axismode==XTRANSLOCAL) sprintf(str, "Local Rot X: >%.2f<", addvec[0]);
-                                                       else if(axismode==YTRANSLOCAL) sprintf(str, "Local Rot Y: >%.2f<", addvec[0]);
-                                                       else if(axismode==ZTRANSLOCAL) sprintf(str, "Local Rot Z: >%.2f<", addvec[0]);
-                                               }
-                                               else{
-                                                       if(axismode==XTRANS) sprintf(str, "Rot X: %.2f", 180.0*phi/M_PI);
-                                                       else if(axismode==YTRANS) sprintf(str, "Rot Y: %.2f", 180.0*phi/M_PI);
-                                                       else if(axismode==ZTRANS) sprintf(str, "Rot Z: %.2f", 180.0*phi/M_PI);
-                                                       else if(axismode==XTRANSLOCAL) sprintf(str, "Local Rot X: %.2f", 180.0*phi/M_PI);
-                                                       else if(axismode==YTRANSLOCAL) sprintf(str, "Local Rot Y: %.2f", 180.0*phi/M_PI);
-                                                       else if(axismode==ZTRANSLOCAL) sprintf(str, "Local Rot Z: %.2f", 180.0*phi/M_PI);
-                                               }
-                                       }
-                                       else{
-                                               if (typemode)
-                                                       sprintf(str, "Rot: >%.2f<", addvec[0]);
-                                               else
-                                                       sprintf(str, "Rot: %.2f", 180.0*phi/M_PI);
-                                       }
-                                       headerprint(str);
-                                       
-                                       time= my_clock();
-
-                                       if(G.obedit) calc_trans_verts();
-                                       special_trans_update(keyflags);
-                                       
-                                       set_constline_callback(mode, axismode, midtog, centre, imat, vx, vy, vz);
-                                       
-                                       if(fast==0) {
-                                               force_draw();
-                                               time= my_clock()-time;
-                                               if(time>50) fast= 1;
-                                       }
-                                       else {
-                                               scrarea_do_windraw(curarea);
-                                               screen_swapbuffers();
-                                       }
-                                       if(tottrans>1 || G.vd->around==V3D_CURSOR) helpline(centre);
-                                       else if (G.obpose) helpline (centre);
-                               }
-                       }
-                       else if(mode=='s' || mode=='S' || mode=='C' || mode=='N') {
-                               keyflags |= KEYFLAG_SIZE;
-
-                               if(mode=='S') {
-                                       size[0]= 1.0-(float)(xn-mval[0])*0.005;
-                                       size[1]= 1.0-(float)(yn-mval[1])*0.005;
-                                       size[2]= 1.0;
-                               }
-                               else size[0]=size[1]=size[2]= (sqrt( (float)((yc-mval[1])*(yc-mval[1])+(mval[0]-xc)*(mval[0]-xc)) ))/sizefac;
-                               
-                               if (typemode){
-                                       if (numchange[0]) size[0] = addvec[0]; else size[0] = 1;
-                                       if (numchange[1]) size[1] = addvec[1]; else size[1] = 1;
-                                       if (numchange[2]) size[2] = addvec[2]; else size[2] = 1;
-                               }
-
-                               if(axismode && mode=='s') {
-                                       /* shear has no axismode */
-                                       if (!(G.obedit)){
-                                               if(axismode==XTRANS) axismode = XTRANSLOCAL;
-                                               if(axismode==YTRANS) axismode = YTRANSLOCAL;
-                                               if(axismode==ZTRANS) axismode = ZTRANSLOCAL;
-                                       }
-                                       if(axismode==XTRANS) size[1]=size[2]= 1.0;
-                                       if(axismode==YTRANS) size[0]=size[2]= 1.0;
-                                       if(axismode==ZTRANS) size[1]=size[0]= 1.0;
-                                       if(axismode==XTRANSLOCAL) size[1]=size[2]= 1.0;
-                                       if(axismode==YTRANSLOCAL) size[0]=size[2]= 1.0;
-                                       if(axismode==ZTRANSLOCAL) size[1]=size[0]= 1.0;
-                               }
-
-/* X en Y flip, there are 2 methods: at  |**| removing comments makes flips local
-
-                               if(transvmain) {
-       
-                                               // x flip
-                                       val= test_midtog_proj(mval[0]+10, mval[1], mval);
-                                       size[val]*= xref;
-                                               // y flip
-                                       val= test_midtog_proj(mval[0], mval[1]+10, mval);
-                                       size[val]*= yref;
-                                       
-                               } */
-
-
-                               /* grid */
-                               apply_keyb_grid(size, 0.0, 0.1, 0.01, gridflag & USER_AUTOSIZEGRID);
-                               apply_keyb_grid(size+1, 0.0, 0.1, 0.01, gridflag & USER_AUTOSIZEGRID);
-                               apply_keyb_grid(size+2, 0.0, 0.1, 0.01, gridflag & USER_AUTOSIZEGRID);
-                               
-                               if(transmain) {
-                                       size[0]= MINSIZE(size[0], 0.001);
-                                       size[1]= MINSIZE(size[1], 0.001);
-                                       size[2]= MINSIZE(size[2], 0.001);
-                               }
-                               
-                               if(size[0]!=oldval[0] ||size[1]!=oldval[1] ||size[2]!=oldval[2]) {
-                                       VECCOPY(oldval, size);
-                                       
-                                       SizeToMat3(size, mat);
-
-                                       /* apply */
-                                       tob= transmain;
-                                       tv= transvmain;
-                                       
-                                       for(a=0; a<tottrans; a++, tob++, tv++) {
-                                               if(transmain) {
-                                                       /* size local with respect to parent AND own rotation */
-                                                       /* local wrt parent: */
-                                                       
-                                                       Mat3MulSerie(smat, tob->parmat, mat, tob->parinv, 0, 0,0 ,0, 0);
-                                                       
-                                                       /* local wrt own rotation: */
-                                                       Mat3MulSerie(totmat, tob->obmat, smat, tob->obinv, 0, 0, 0,0 ,0);
-
-                                                       /* XXX this can yield garbage in case of inverted sizes (< 0.0)
-                                                                                                       */
-                                                       if(!midtog) {
-                                                               sizelo[0]= size[0];
-                                                               sizelo[1]= size[1];
-                                                               sizelo[2]= size[2];
-                                                       } else {        
-                                                       /* in this case the previous calculation of the size is wrong */
-                                                               sizelo[0]= totmat[0][0];        
-                                                               sizelo[1]= totmat[1][1];        
-                                                               sizelo[2]= totmat[2][2];
-                                                               apply_keyb_grid(sizelo, 0.0, 0.1, 0.01, gridflag & USER_AUTOSIZEGRID);
-                                                               apply_keyb_grid(sizelo+1, 0.0, 0.1, 0.01, gridflag & USER_AUTOSIZEGRID);
-                                                               apply_keyb_grid(sizelo+2, 0.0, 0.1, 0.01, gridflag & USER_AUTOSIZEGRID);
-                                                       } 
-
-                                                               /* x flip */
-/**/                                           /* sizelo[0]*= xref; */
-                                                               /* y flip */
-/**/                                           /* sizelo[1]*= yref; */
-                                                               /* z flip */
-/**/                                           /* sizelo[2]*= zref; */
-
-
-                                                       /* what you see is what you want; not what you get! */
-                                                       /* correction for delta size */
-                                                       if(tob->flag & TOB_IPO) {
-                                                               /* calculate delta size (equal for size and dsize) */
-                                                               
-                                                               vec[0]= (tob->oldsize[0]+tob->olddsize[0])*(sizelo[0] -1.0);
-                                                               vec[1]= (tob->oldsize[1]+tob->olddsize[1])*(sizelo[1] -1.0);
-                                                               vec[2]= (tob->oldsize[2]+tob->olddsize[2])*(sizelo[2] -1.0);
-
-                                                               add_ipo_tob_poin(tob->sizex, tob->oldsize+3, vec[0]);
-                                                               add_ipo_tob_poin(tob->sizey, tob->oldsize+4, vec[1]);
-                                                               add_ipo_tob_poin(tob->sizez, tob->oldsize+5, vec[2]);
-                                                               
-                                                       }
-                                                       else {
-                                                               tob->size[0]= (tob->oldsize[0]+tob->olddsize[0])*sizelo[0] -tob->olddsize[0];
-                                                               tob->size[1]= (tob->oldsize[1]+tob->olddsize[1])*sizelo[1] -tob->olddsize[1];
-                                                               tob->size[2]= (tob->oldsize[2]+tob->olddsize[2])*sizelo[2] -tob->olddsize[2];
-                                                       }
-                                                       
-                                                       if(G.vd->around!=V3D_LOCAL && !G.obpose) {
-                                                               /* translation */
-                                                               VecSubf(vec, tob->obvec, centre);
-                                                               Mat3MulVecfl(mat, vec);
-                                                               VecAddf(vec, vec, centre);
-                                                               /* vec is the location where the object has to be */
-                                                               VecSubf(vec, vec, tob->obvec);
-                                                               Mat3MulVecfl(tob->parinv, vec);
-
-                                                               if(tob->flag & TOB_IPO) {
-                                                                       add_ipo_tob_poin(tob->locx, tob->oldloc, vec[0]);
-                                                                       add_ipo_tob_poin(tob->locy, tob->oldloc+1, vec[1]);
-                                                                       add_ipo_tob_poin(tob->locz, tob->oldloc+2, vec[2]);
-                                                               }
-                                                               else if(tob->loc) {
-                                                                       if(transmode==TRANS_TEX) ;
-                                                                       else  VecAddf(tob->loc, tob->oldloc, vec);
-                                                               }
-                                                       }
-                                               }
-                                               else {  /* vertices */
-                                               
-                                                       /* for print */
-                                                       VECCOPY(sizelo, size);
-                                                       
-                                                       if(mode=='C') {
-                                                               size[0]= tv->fac*size[0]+ 1.0-tv->fac;;
-                                                               size[1]= tv->fac*size[1]+ 1.0-tv->fac;;
-                                                               size[2]= tv->fac*size[2]+ 1.0-tv->fac;;
-                                                               SizeToMat3(size, mat);
-                                                               VECCOPY(size, oldval);
-                                                       }
-                                                       
-                                                       if(mode=='S') { /* shear */
-                                                               Mat3One(tmat);
-                                                               tmat[0][0]= tmat[2][2]= tmat[1][1]= 1.0;
-                                                               tmat[1][0]= size[0]-1.0;
-                                                               
-                                                               Mat3MulMat3(totmat, persmat, omat);
-                                                               Mat3MulMat3(mat, tmat, totmat);
-                                                               Mat3MulMat3(totmat, persinv, mat);
-                                                               Mat3MulMat3(smat, imat, totmat);
-                                                       }
-                                                       else {
-                                                               if (axismode & TRANSLOCAL)
-                                                                       Mat3CpyMat3(smat, mat);
-                                                               else {
-                                                                       Mat3MulMat3(totmat, imat, mat);
-                                                                       Mat3MulMat3(smat, totmat, omat);
-                                                               }
-                                                       }
-                                                       
-                                                       if(mode=='N' && tv->nor!=NULL) {
-                                                               tv->loc[0]= tv->oldloc[0] + (size[0]-1.0)*tv->nor[0];
-                                                               tv->loc[1]= tv->oldloc[1] + (size[1]-1.0)*tv->nor[1];
-                                                               tv->loc[2]= tv->oldloc[2] + (size[2]-1.0)*tv->nor[2];
-                                                       }
-                                                       else {
-                                                               VecSubf(vec, tv->oldloc, centre);
-                                                               Mat3MulVecfl(smat, vec);
-                                                               VecAddf(tv->loc, vec, centre);
-                                                       
-                                                               if(G.obedit->type==OB_MBALL) *(tv->val)= size[0]*tv->oldval;
-                                                       }
-                                               }
-                                       }
-                                       if(mode=='s') {
-                                               if (typemode){
-                                                       switch (ax){
-                                                       case 0:
-                                                               sprintf(str, "Sizex: >%.3f<   Sizey: >%.3f<  Sizez: >%.3f<", sizelo[0], sizelo[1], sizelo[2]);
-                                                               break;
-                                                       case 1:
-                                                               sprintf(str, "Sizex: >%.3f<   Sizey: %.3f  Sizez: %.3f", sizelo[0], sizelo[1], sizelo[2]);
-                                                               break;
-                                                       case 2:
-                                                               sprintf(str, "Sizex: %.3f   Sizey: >%.3f<  Sizez: %.3f", sizelo[0], sizelo[1], sizelo[2]);
-                                                               break;
-                                                       case 3:
-                                                               sprintf(str, "Sizex: %.3f   Sizey: %.3f  Sizez: >%.3f<", sizelo[0], sizelo[1], sizelo[2]);
-                                                       }
-                                               }
-                                               else
-                                                       sprintf(str, "Sizex: %.3f   Sizey: %.3f  Sizez: %.3f", sizelo[0], sizelo[1], sizelo[2]);
-                                       }
-                                       else if (mode=='S') {
-                                               if (typemode)
-                                                       sprintf(str, "Shear: >%.3f<", sizelo[0]);
-                                               else
-                                                       sprintf(str, "Shear: %.3f", sizelo[0]);
-                                       }
-                                       else if (mode=='C') {
-                                               if (typemode)
-                                                       sprintf(str, "Size: >%.3f<", sizelo[0]);
-                                               else
-                                                       sprintf(str, "Size: %.3f", sizelo[0]);
-                                       }
-                                       else if (mode=='N') {
-                                               if (typemode)
-                                                       sprintf(str, "Shrink/Fatten: >%.3f< ", size[0]);
-                                               else
-                                                       sprintf(str, "Shrink/Fatten: %.3f", size[0]);
-                                       }
-                                       
-                                       headerprint(str);
-                                       
-                                       time= my_clock();
-
-                                       if(G.obedit) calc_trans_verts();
-                                       special_trans_update(keyflags);
-                               
-                                       set_constline_callback(mode, axismode, midtog, centre, imat, vx, vy, vz);
-                               
-                                       if(fast==0) {
-                                               force_draw();
-                                               time= my_clock()-time;
-                                               if(time>50) fast= 1;
-                                       }
-                                       else {
-                                               scrarea_do_windraw(curarea);
-                                               screen_swapbuffers();
-                                       }
-                                       if(tottrans>1 || G.vd->around==V3D_CURSOR) helpline(centre);
-                               }
-                       }
-                       else if(mode=='w') {
-                               float Dist1;
-                               
-                               window_to_3d(dvec, 1, 1);
-                               
-                               omtrekfac= startomtrekfac+ 0.05*( mval[1] - yn)*Normalise(dvec);
+       VecSubf(speed, v1->co, oldloc);
+       len= Normalise(speed);
+       if(len==0.0) return 0;
        
-                               /* calc angle for print */
-                               dist= max[0]-centre[0];
-                               Dist1 = dist;
-                               phi0= 360*omtrekfac*dist/(rad*M_PI);
+       VecSubf(rc, oldloc, base);
+       bsq= rc[0]*speed[0] + rc[1]*speed[1] + rc[2]*speed[2]; 
+       u= rc[0]*rc[0] + rc[1]*rc[1] + rc[2]*rc[2] - editbutsize*editbutsize;
 
-                               if ((typemode) && (addvec[0])){
-                                       phi0 = addvec[0];
-                               }
-                               
-                               if((G.qual & LR_CTRLKEY) && (typemode == 0)){
-                                       phi0= 5.0*floor(phi0/5.0);
-                                       omtrekfac= (phi0*rad*M_PI)/(360.0*dist);
-                               }
-                               
-                               if (typemode && addvec[0])
-                                       sprintf(str, "Warp >%3.3f<", addvec[0]); 
-                               else
-                                       sprintf(str, "Warp %3.3f", phi0); 
-                               headerprint(str);
+       disc= bsq*bsq - u;
        
-                               /* each vertex transform individually */
-                               tob= transmain;
-                               tv= transvmain;
-                                       
-                               for(a=0; a<tottrans; a++, tob++, tv++) {
-                                       if(transvmain) {
-                                               
-                                               /* translate point to centre, rotate in such a way that outline==distance */
-                                               
-                                               VECCOPY(vec, tv->oldloc);
-                                               Mat4MulVecfl(G.obedit->obmat, vec);
-                                               Mat4MulVecfl(G.vd->viewmat, vec);
-                                                               
-                                               dist= vec[0]-centre[0];
-
-                                               if ((typemode) && (addvec[0]))
-                                                       phi0= (Dist1*addvec[0]*M_PI/(360.0*dist)) - 0.5*M_PI;
-                                               else
-                                                       phi0= (omtrekfac*dist/rad) - 0.5*M_PI;
-                                       
-                                               co= cos(phi0);
-                                               si= sin(phi0);
-                                               
-                                               vec[0]= (centre[0]-axis[0]);
-                                               vec[1]= (vec[1]-axis[1]);
-                                               
-                                               tv->loc[0]= si*vec[0]+co*vec[1]+axis[0];
-                                               
-                                               tv->loc[1]= co*vec[0]-si*vec[1]+axis[1];
-                                               tv->loc[2]= vec[2];
-                                               
-                                               Mat4MulVecfl(viewinv, tv->loc);
-                                               Mat4MulVecfl(imat4, tv->loc);
-                                               
-                                       }
-                               }
-                               
-                               if(G.obedit) calc_trans_verts();
-                               special_trans_update(keyflags);
-                               
-                               if(fast==0) {
-                                       time= my_clock();
-                                       force_draw();
-                                       time= my_clock()-time;
-                                       if(time>50) fast= 1;
-                               }
-                               else {
-                                       scrarea_do_windraw(curarea);
-                                       screen_swapbuffers();
-                               }
-                       }
-                       /* Help line drawing starts here */
-
-               }
+       if(disc>=0.0) {
+               disc= sqrt(disc);
+               labdacor= (-bsq - disc)/len;    /* entry point */
+               labda= (-bsq + disc)/len;
                
-               while( qtest() ) {
-                       float add_num = 0; // numerical value to be added
-
-                       event= extern_qread(&val);
-                       
-                       if(val) {
-                               /* no-numpad option likes minus for numeric input better */
-                               if ((U.flag & USER_NONUMPAD) && typemode && event==PADMINUS) event = MINUSKEY;
-                               
-                               switch(event) {
-                               case ESCKEY:
-                               case LEFTMOUSE:
-                               case RIGHTMOUSE:
-                               case SPACEKEY:
-                               case PADENTER:
-                               case RETKEY:
-                                       afbreek= 1;
-                                       break;
-                               case MIDDLEMOUSE:
-                                       midtog= ~midtog;
-                                       if(midtog) {
-                                               int proj;
-
-                                               proj= test_midtog_proj(xn, yn, mval);
-                                               if (proj==0)
-                                                       axismode=XTRANS;
-                                               if (proj==1)
-                                                       axismode=YTRANS;
-                                               if (proj==2)
-                                                       axismode=ZTRANS;
-
-                                               phi0= phi1= 0.0;
-                                               if(cameragrab) {
-                                                       dvec[0]= dvec[1]= dvec[2]= 0.0;
-                                               }
-                                       }
-                                       else
-                                               axismode = 0;
-
-                                       if ((mode == 'r') || (mode == 'R')){
-                                               if (midtog){ax = 1;}
-                                               else{ax = 0;}
-                                       }
-                                       firsttime= 1;
-                                       break;
-                               case GKEY:
-                               case RKEY:
-                               case SKEY:
-                                       /* Resetting the variables */
-                                       addvec[0]=addvec[1]=addvec[2]=0;
-                                       ax = del = typemode = 0;
-                                       pe[0]=pe[1]=pe[2]=0;
-                                       mi[0]=mi[1]=mi[2]=1;
-                                       numchange[0]=numchange[1]=numchange[2]=0;
-
-                                       getmouseco_areawin(mval);
-                                       xn=xo= mval[0];
-                                       yn=xo= mval[1];
-                                       dx1= xc-xn; 
-                                       dy1= yc-yn;
-                                       phi= phi0= phi1= 0.0;
-                                       sizefac= sqrt( (float)((yc-yn)*(yc-yn)+(xn-xc)*(xn-xc)) );
-                                       if(sizefac<2.0) sizefac= 2.0;
-                                       
-                                       if (G.obedit && (G.f & G_PROPORTIONAL)) {
-                                               if(event==GKEY) mode= 'G';
-                                               else if(event==RKEY) mode= 'R';
-                                               else if(event==SKEY) mode= 'C';                                         
-                                       } else {
-                                               if(event==GKEY) mode= 'g';
-                                               else if(event==RKEY) mode= 'r';
-                                               else if(event==SKEY) mode= 's';
-                                       }
+               printf("var1: %f, var2: %f, var3: %f\n", labdacor, labda, editbutsize);
+       }
+       else return 0;
 
-                                       firsttime= 1;
-                                       
-                                       tob= transmain;
-                                       tv= transvmain;
-                                       for(a=0; a<tottrans; a++, tob++, tv++) {
-                                               if(transmain) {
-                                                       restore_tob(tob);
-                                               }
-                                               else {
-                                                       VECCOPY(tv->loc, tv->oldloc);
-                                               }
-                                       }
-                                       break;
-                               
-                               case XKEY:
-                                       if (axismode==XTRANS)
-                                               axismode=XTRANSLOCAL;
-                                       else if (axismode==XTRANSLOCAL)
-                                               axismode=0;
-                                       else{
-                                               axismode= XTRANS;
-                                       }
-                    if (mode == 'g') {
-                            if (axismode & XTRANS)
-                                    ax = 0;
-                    } else if (mode == 's') {
-                            if (axismode & XTRANS)
-                                    ax = 1;
-                    }
-                                       firsttime=1;
-                                       break;
-                                       
-                               case YKEY:
-                                       if (axismode==YTRANS)
-                                               axismode=YTRANSLOCAL;
-                                       else if (axismode==YTRANSLOCAL)
-                                               axismode=0;
-                                       else{
-                                               axismode= YTRANS;
-                                       }
-                    if (mode == 'g') {
-                            if (axismode & YTRANS)
-                                    ax = 1;
-                    } else if (mode == 's') {
-                            if (axismode & YTRANS)
-                                    ax = 2;
-                    }
-                                       firsttime=1;
-                                       break;
-                                       
-                               case ZKEY:
-                                       if (axismode==ZTRANS)
-                                               axismode=ZTRANSLOCAL;
-                                       else if (axismode==ZTRANSLOCAL)
-                                               axismode=0;
-                                       else{
-                                               axismode= ZTRANS;
-                                       }
-                    if (mode == 'g') {
-                            if (axismode & ZTRANS)
-                                    ax = 2;
-                    } else if (mode == 's') {
-                            if (axismode & ZTRANS)
-                                    ax = 3;
-                    }
-                                       firsttime=1;
-                                       break;
-                               case WHEELDOWNMOUSE:
-                               case PADPLUSKEY:
-                                       if(G.f & G_PROPORTIONAL) {
-                                               prop_size*= 1.1;
-                                               firsttime= 1;
-                                       }
-                                       else {
-                                               if(event == WHEELDOWNMOUSE)
-                                                       view_editmove(event);
-                                               else
-                                                       persptoetsen(PADPLUSKEY);
-                                         firsttime= 1;
-                                       }
-                                       break;
+       /* intersection and normal */
+       rc[0]= oldloc[0] + labdacor*speed[0] - base[0];
+       rc[1]= oldloc[1] + labdacor*speed[1] - base[1];
+       rc[2]= oldloc[2] + labdacor*speed[2] - base[2];
 
-                               case WHEELUPMOUSE:
-                               case PADMINUS:
-                                       if(G.f & G_PROPORTIONAL) {
-                                               prop_size*= 0.90909090;
-                                               firsttime= 1;
-                                       }
-                                       else {
-                                               if(event == WHEELUPMOUSE)
-                                                       view_editmove(event);
-                                               else
-                                                 persptoetsen(PADMINUS);
-                                         firsttime= 1;
-                                       }
-                                       break;
 
-                               case LEFTSHIFTKEY:
-                               case RIGHTSHIFTKEY:
-                                       VECCOPY(d_dvec, dvec);
-                               case LEFTCTRLKEY:
-                               case RIGHTCTRLKEY:
-                                       firsttime= 1;
-                                       break;
-                               case NKEY:
-                                       {
-                                               // toggle between typemode = 0 and typemode = 1
-                                               typemode *= -1;
-                                               typemode += 1;
-                                               firsttime = 1;
-                                       }
-                                       break;
-                               case BACKSPACEKEY:
-                                       {
-                                               if (typemode){
-                                                       if (((mode == 's') && (ax == 0)) || (mode == 'N')){
-                                                               addvec[0]=addvec[1]=addvec[2]=0;
-                                                               pe[0]=pe[1]=pe[2]=0;
-                                                               mi[0]=mi[1]=mi[2]=1;
-                                                               numchange[0]=numchange[1]=numchange[2]=0;
-                                                       }
-                                                       else if (del == 1){
-                                                               addvec[0]=addvec[1]=addvec[2]=0;
-                                                               pe[0]=pe[1]=pe[2]=0;
-                                                               mi[0]=mi[1]=mi[2]=1;
-                                                               numchange[0]=numchange[1]=numchange[2]=0;
-                                                               del = 0;
-                                                       }
-                                                       else if (mode == 's'){
-                                                               addvec[ax-1]=0;
-                                                               pe[ax-1]=0;
-                                                               mi[ax-1]=1;
-                                                               numchange[ax-1]=0;
-                                                               del = 1;
-                                                       }
-                                                       else if ((mode == 'r') || (mode == 'R')){
-                                                               phi -= M_PI * addvec[ax] / 180;
-                                                               addvec[ax] = 0;
-                                                               pe[ax]=0;
-                                                               mi[ax]=1;
-                                                               numchange[ax]=0;
-                                                               del = 1;
-                                                       }
-                                                       else{
-                                                               addvec[ax] = 0;
-                                                               pe[ax]=0;
-                                                               mi[ax]=1;
-                                                               numchange[ax]=0;
-                                                               del = 1;
-                                                       }
-                                               }
-                                               else{
-                                                       getmouseco_areawin(mval);
-                                                       xn=xo= mval[0];
-                                                       yn=xo= mval[1];
-                                                       dx1= xc-xn; 
-                                                       dy1= yc-yn;
-                                                       phi= phi0= phi1= 0.0;
-                                                       sizefac= sqrt( (float)((yc-yn)*(yc-yn)+(xn-xc)*(xn-xc)) );
-                                                       if(sizefac<2.0) sizefac= 2.0;
-                                               }
-                                               firsttime = 1;
-                                               break;
-                                       }
-                               case PERIODKEY:
-                               case PADPERIOD:
-                                       {
-                                               typemode = 1;
-                                               del = 0;
-                                               if (((mode == 's') && (ax == 0)) || (mode == 'N')){
-                                                       if (pe[0] == 0){pe[0] = 1;}
-                                                       if (pe[1] == 0){pe[1] = 1;}
-                                                       if (pe[2] == 0){pe[2] = 1;}
-                                               }
-                                               else if (mode == 's'){
-                                                       if (pe[ax-1] == 0){pe[ax-1] = 1;}
-                                               }
-                                               else{
-                                                       if (pe[ax] == 0){pe[ax] = 1;}
-                                               }
-                                               break;
-                                       }
-                               case MINUSKEY:
-                                       {
-                                               del = 0;
-                                               if (((mode == 's') && (ax==0)) || (mode == 'N')){
-                                                       addvec[0]*=-1;
-                                                       mi[0] *= -1;
-                                                       addvec[1]*=-1;
-                                                       mi[1] *= -1;
-                                                       addvec[2]*=-1;
-                                                       mi[2] *= -1;
-                                               }
-                                               else if (mode == 's'){
-                                                       addvec[ax-1]*=-1;
-                                                       mi[ax-1] *= -1;
-                                               }
-                                               else{
-                                                       addvec[ax]*=-1;
-                                                       mi[ax] *= -1;
-                                               }
-                                               firsttime = 1;
-                                               break;
-                                       }
-                               case TABKEY:
-                                       {
-                                               typemode = 1;
-                                               del = 0;
-                                               if ((mode == 'S') || (mode == 'w') || (mode == 'C') || (mode == 'N'))
-                                                       break;
-                                               if ((mode != 'r') && (mode != 'R')){
-                            if (axismode != 0)
-                                    break;
-                                                       ax += 1;
-                                                       if (mode == 's'){
-                                                               if (ax == 4){ax=0;}
-                                                       }
-                                                       else if (ax == 3){ax=0;}
-                                                       firsttime = 1;
-                                               }
-                                               else if (((mode == 'r') || (mode == 'R')) && (midtog)){
-                                                       ax += 1;
-                                                       if (ax == 3){ax = 1;}
-                                                       firsttime = 1;
-                                               }
-                                               break;
-                                       }
-                               case PAD9:
-                               case NINEKEY:
-                                       {add_num += 1;}
-                               case PAD8:
-                               case EIGHTKEY:
-                                       {add_num += 1;}
-                               case PAD7:
-                               case SEVENKEY:
-                                       {add_num += 1;}
-                               case PAD6:
-                               case SIXKEY:
-                                       {add_num += 1;}
-                               case PAD5:
-                               case FIVEKEY:
-                                       {add_num += 1;}
-                               case PAD4:
-                               case FOURKEY:
-                                       {add_num += 1;}
-                               case PAD3:
-                               case THREEKEY:
-                                       {add_num += 1;}
-                               case PAD2:
-                               case TWOKEY:
-                                       {add_num += 1;}
-                               case PAD1:
-                               case ONEKEY:
-                                       {add_num += 1;}
-                               case PAD0:
-                               case ZEROKEY:
-                                       {
-                                               typemode = 1;
-                                               del = 0;
-                                               if (mode == 's'){
-                            if (axismode & XTRANS)
-                                    ax = 1;
-                            if (axismode & YTRANS)
-                                    ax = 2;
-                            if (axismode & ZTRANS)
-                                    ax = 3;
-                                                       if (ax == 0){
-                                                               if (pe[0]){
-                                                                       int div = 1;
-                                                                       int i;
-                                                                       for (i = 0; i < pe[ax]; i++){div*=10;}
-                                                                       addvec[0] += mi[0] * add_num / div;
-                                                                       pe[0]+=1;
-                                                                       addvec[1] += mi[1] * add_num / div;
-                                                                       pe[1]+=1;
-                                                                       addvec[2] += mi[2] * add_num / div;
-                                                                       pe[2]+=1;
-                                                               }
-                                                               else{
-                                                                       addvec[0] *= 10;
-                                                                       addvec[0] += mi[0] * add_num;
-                                                                       addvec[1] *= 10;
-                                                                       addvec[1] += mi[1] * add_num;
-                                                                       addvec[2] *= 10;
-                                                                       addvec[2] += mi[2] * add_num;
-                                                               }
-                                                               numchange[0]=numchange[1]=numchange[2]=1;
-                                                       }
-                                                       else{
-                                                               if (pe[ax-1]){
-                                                                       int div = 1;
-                                                                       int i;
-                                                                       for (i = 0; i < pe[ax-1]; i++){div*=10;}
-                                                                       addvec[ax-1] += mi[ax-1] * add_num / div;
-                                                                       pe[ax-1]+=1;
-                                                               }
-                                                               else{
-                                                                       addvec[ax-1] *= 10;
-                                                                       addvec[ax-1] += mi[ax-1] * add_num;
-                                                               }
-                                                               numchange[ax-1]=1;
-                                                       }
-                                                       
-                                               }
-                                               else if (mode == 'N'){
-                                                       if (pe[0]){
-                                                               int div = 1;
-                                                               int i;
-                                                               for (i = 0; i < pe[ax]; i++){div*=10;}
-                                                               addvec[0] += mi[0] * add_num / div;
-                                                               pe[0]+=1;
-                                                               addvec[1] += mi[1] * add_num / div;
-                                                               pe[1]+=1;
-                                                               addvec[2] += mi[2] * add_num / div;
-                                                               pe[2]+=1;
-                                                       }
-                                                       else{
-                                                               addvec[0] *= 10;
-                                                               addvec[0] += mi[0] * add_num;
-                                                               addvec[1] *= 10;
-                                                               addvec[1] += mi[1] * add_num;
-                                                               addvec[2] *= 10;
-                                                               addvec[2] += mi[2] * add_num;
-                                                       }
-                                                       numchange[0]=numchange[1]=numchange[2]=1;
-                                               }
-                                               else if ((mode == 'r') || (mode == 'R')){
-                                                       if (pe[ax]){
-                                                               int div = 1;
-                                                               int i;
-                                                               for (i = 0; i < pe[ax]; i++){div*=10;}
-                                                               addvec[ax] += mi[ax] * add_num / div;
-                                                               pe[ax]+=1;
-                                                       }
-                                                       else{
-                                                               addvec[ax] *= 10;
-                                                               addvec[ax] += mi[ax] * add_num;
-                                                       }
-                                                       numchange[ax]=1;
-                                               }
-                                               else{
-                            if (axismode & XTRANS)
-                                    ax = 0;
-                            if (axismode & YTRANS)
-                                    ax = 1;
-                            if (axismode & ZTRANS)
-                                    ax = 2;
-                                                       if (pe[ax]){
-                                                               int div = 1;
-                                                               int i;
-                                                               for (i = 0; i < pe[ax]; i++){div*=10;}
-                                                               addvec[ax] += mi[ax] * add_num / div;
-                                                               pe[ax]+=1;
-                                                       }
-                                                       else{
-                                                               addvec[ax] *= 10;
-                                                               addvec[ax] += mi[ax] * add_num;
-                                                       }
-                                                       numchange[ax]=1;
-                                               }
-                                               firsttime=1;
-                                       }
-                                       break;
-                               }
-       
-                               arrows_move_cursor(event);
-                       }
-                       if(event==0 || afbreek) break;
+       return 1;
+}
 
-               }
-               xo= mval[0];
-               yo= mval[1];
-                               
-               if( qtest()==0) PIL_sleep_ms(1);
-               
-       }
-       G.moving= 0;
-       
-       if(event==ESCKEY || event==RIGHTMOUSE) {
-               canceled=1;
-               G.undo_edit_level--;
-               tv= transvmain;
-               tob= transmain;
-               for(a=0; a<tottrans; a++, tob++, tv++) {
-                       if(transmain) {
-                               restore_tob(tob);
-                       }
-                       else {
-                               VECCOPY(tv->loc, tv->oldloc);
-                               if(tv->val) *(tv->val)= tv->oldval;
-                       }
-               }
-               if(G.obedit) calc_trans_verts();
-               special_trans_update(keyflags);
-       }
-       
-       a= 0;
-       if(xref<0) a++;
-       if(yref<0) a++;
-       if(zref<0) a++;
-       special_aftertrans_update(mode, a & 1, canceled, keyflags);
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1000000
+#endif
 
-       allqueue(REDRAWVIEW3D, 0);
-       scrarea_queue_headredraw(curarea);
+int my_clock(void)
+{
+       float ftime;
        
-       clearbaseflags_for_editing();
+       ftime= (float)clock();
+       ftime*= 100.0/CLOCKS_PER_SEC;
        
-       if(transmain) MEM_freeN(transmain);
-       transmain= 0;
-       if(transvmain) MEM_freeN(transvmain);
-       transvmain= 0;
-
-       tottrans= 0;
+       return (int)ftime;
 }
 
-void std_rmouse_transform(void (*xf_func)(int))
+
+void std_rmouse_transform(void (*xf_func)(int, int))
 {
        short mval[2];
        short xo, yo;
        short timer=0;
+       short mousebut;
+       
+       /* check for left mouse select/right mouse select user pref */
+       if (U.flag & USER_LMOUSESELECT) mousebut = L_MOUSE;
+               else mousebut = R_MOUSE;
        
        getmouseco_areawin(mval);
        xo= mval[0]; 
        yo= mval[1];
        
-       while(get_mbut()&R_MOUSE) {
+       while(get_mbut() & mousebut) {
                getmouseco_areawin(mval);
                if(abs(mval[0]-xo)+abs(mval[1]-yo) > 10) {
-                       xf_func('g');
-                       while(get_mbut()&R_MOUSE) BIF_wait_for_statechange();
+                       if(curarea->spacetype==SPACE_VIEW3D)
+                               Transform(TFM_TRANSLATION, CTX_NONE);
+                       else
+                               xf_func('g', 0);
+
+                       while(get_mbut() & mousebut) BIF_wait_for_statechange();
                        return;
                }
                else {
@@ -6029,12 +4855,14 @@ void std_rmouse_transform(void (*xf_func)(int))
                                return;
                        }
                }
-       }       
+       }
+       /* if gets here it's a select */
+       BIF_undo_push("Select");
 }
 
 void rightmouse_transform(void)
 {
-       std_rmouse_transform(transform);
+       std_rmouse_transform(Transform);
 }
 
 
@@ -6042,7 +4870,6 @@ void rightmouse_transform(void)
 
 
 void single_object_users(int flag)     
-       /* after this call clear_id_newpoins() */
 {
        Base *base;
        Object *ob, *obn;
@@ -6076,6 +4903,21 @@ void single_object_users(int flag)
                if(ob->id.lib==0) {
                        if( (base->flag & flag)==flag) {
                                
+                               relink_constraints(&base->object->constraints);
+                               if (base->object->pose){
+                                       bPoseChannel *chan;
+                                       for (chan = base->object->pose->chanbase.first; chan; chan=chan->next){
+                                               relink_constraints(&chan->constraints);
+                                       }
+                               }
+                               if(base->object->hooks.first) {
+                                       ObHook *hook= base->object->hooks.first;
+                                       while(hook) {
+                                               ID_NEW(hook->parent);
+                                               hook= hook->next;
+                                       }
+                               }
+                               
                                ID_NEW(ob->parent);
                                ID_NEW(ob->track);
                                
@@ -6134,7 +4976,7 @@ void single_obdata_users(int flag)
                                case OB_LAMP:
                                        if(id && id->us>1 && id->lib==0) {
                                                ob->data= la= copy_lamp(ob->data);
-                                               for(a=0; a<8; a++) {
+                                               for(a=0; a<MAX_MTEX; a++) {
                                                        if(la->mtex[a]) {
                                                                ID_NEW(la->mtex[a]->object);
                                                        }
@@ -6155,6 +4997,7 @@ void single_obdata_users(int flag)
                                case OB_FONT:
                                        ob->data= cu= copy_curve(ob->data);
                                        ID_NEW(cu->bevobj);
+                                       ID_NEW(cu->taperobj);
                                        makeDispList(ob);
                                        break;
                                case OB_LATTICE:
@@ -6274,7 +5117,7 @@ void single_mat_users(int flag)
                                                        ma->ipo->id.us--;
                                                }
                                                
-                                               for(b=0; b<8; b++) {
+                                               for(b=0; b<MAX_MTEX; b++) {
                                                        if(ma->mtex[b] && ma->mtex[b]->tex) {
                                                                tex= ma->mtex[b]->tex;
                                                                if(tex->id.us>1) {
@@ -6324,7 +5167,7 @@ void single_tex_users_expand()
        ma= G.main->mat.first;
        while(ma) {
                if(ma->id.flag & LIB_NEW) {
-                       for(b=0; b<8; b++) {
+                       for(b=0; b<MAX_MTEX; b++) {
                                if(ma->mtex[b] && ma->mtex[b]->tex) {
                                        do_single_tex_user( &(ma->mtex[b]->tex) );
                                }
@@ -6336,7 +5179,7 @@ void single_tex_users_expand()
        la= G.main->lamp.first;
        while(la) {
                if(la->id.flag & LIB_NEW) {
-                       for(b=0; b<6; b++) {
+                       for(b=0; b<MAX_MTEX; b++) {
                                if(la->mtex[b] && la->mtex[b]->tex) {
                                        do_single_tex_user( &(la->mtex[b]->tex) );
                                }
@@ -6347,7 +5190,7 @@ void single_tex_users_expand()
        wo= G.main->world.first;
        while(wo) {
                if(wo->id.flag & LIB_NEW) {
-                       for(b=0; b<6; b++) {
+                       for(b=0; b<MAX_MTEX; b++) {
                                if(wo->mtex[b] && wo->mtex[b]->tex) {
                                        do_single_tex_user( &(wo->mtex[b]->tex) );
                                }
@@ -6404,7 +5247,7 @@ void single_mat_users_expand(void)
        ma= G.main->mat.first;
        while(ma) {
                if(ma->id.flag & LIB_NEW) {
-                       for(a=0; a<8; a++) {
+                       for(a=0; a<MAX_MTEX; a++) {
                                if(ma->mtex[a]) {
                                        ID_NEW(ma->mtex[a]->object);
                                }
@@ -6420,6 +5263,8 @@ void single_user(void)
        
        if(G.scene->id.lib) return;
 
+       clear_id_newpoins();
+       
        nr= pupmenu("Make Single User%t|Object|Object & ObData|Object & ObData & Materials+Tex|Materials+Tex");
        if(nr>0) {
        
@@ -6443,6 +5288,7 @@ void single_user(void)
 
                countall();
                allqueue(REDRAWALL, 0);
+               BIF_undo_push("Single user");
        }
 }
 
@@ -6560,7 +5406,7 @@ void make_local(void)
                        
                        if(ob->type==OB_LAMP) {
                                la= ob->data;
-                               for(b=0; b<8; b++) {
+                               for(b=0; b<MAX_MTEX; b++) {
                                        if(la->mtex[b] && la->mtex[b]->tex) {
                                                make_local_texture(la->mtex[b]->tex);
                                        }
@@ -6573,7 +5419,7 @@ void make_local(void)
                                        if(ma) {
                                                make_local_material(ma);
                                        
-                                               for(b=0; b<8; b++) {
+                                               for(b=0; b<MAX_MTEX; b++) {
                                                        if(ma->mtex[b] && ma->mtex[b]->tex) {
                                                                make_local_texture(ma->mtex[b]->tex);
                                                        }
@@ -6590,7 +5436,7 @@ void make_local(void)
                                        if(ma) {
                                                make_local_material(ma);
                                        
-                                               for(b=0; b<8; b++) {
+                                               for(b=0; b<MAX_MTEX; b++) {
                                                        if(ma->mtex[b] && ma->mtex[b]->tex) {
                                                                make_local_texture(ma->mtex[b]->tex);
                                                        }
@@ -6606,7 +5452,7 @@ void make_local(void)
 
 
        allqueue(REDRAWALL, 0);
-
+       BIF_undo_push("Make local");
 }
 
 
@@ -6615,8 +5461,6 @@ void adduplicate(float *dtrans)
 {
        Base *base, *basen;
        Object *ob, *obn;
-       Ika *ika;
-       Deform *def;
        Material ***matarar, *ma, *mao;
        ID *id;
        bConstraintChannel *chan;
@@ -6804,30 +5648,23 @@ void adduplicate(float *dtrans)
        while(base) {
                if TESTBASELIB(base) {
                        
-                       {
+                       relink_constraints(&base->object->constraints);
+                       if (base->object->pose){
                                bPoseChannel *chan;
-
-                               relink_constraints(&base->object->constraints);
-                               if (base->object->pose){
-                                       for (chan = base->object->pose->chanbase.first; chan; chan=chan->next){
-                                               relink_constraints(&chan->constraints);
-                                       }
+                               for (chan = base->object->pose->chanbase.first; chan; chan=chan->next){
+                                       relink_constraints(&chan->constraints);
+                               }
+                       }
+                       if(base->object->hooks.first) {
+                               ObHook *hook= base->object->hooks.first;
+                               while(hook) {
+                                       ID_NEW(hook->parent);
+                                       hook= hook->next;
                                }
                        }
                        ID_NEW(base->object->parent);
                        ID_NEW(base->object->track);
                        
-                       if(base->object->type==OB_IKA) {
-                               ika= base->object->data;
-                               ID_NEW(ika->parent);
-                               
-                               a= ika->totdef;
-                               def= ika->def;
-                               while(a--) {
-                                       ID_NEW(def->ob);
-                                       def++;
-                               }
-                       }
                }
                base= base->next;
        }
@@ -6841,7 +5678,7 @@ void adduplicate(float *dtrans)
                                ma= (Material *)mao->id.newid;
                                
                                if(dupflag & USER_DUP_TEX) {
-                                       for(a=0; a<8; a++) {
+                                       for(a=0; a<MAX_MTEX; a++) {
                                                if(ma->mtex[a]) {
                                                        id= (ID *)ma->mtex[a]->tex;
                                                        if(id) {
@@ -6869,7 +5706,7 @@ void adduplicate(float *dtrans)
        clear_id_newpoins();
        
        countall();
-       if(dtrans==0) transform('g');
+       if(dtrans==0) Transform(TFM_TRANSLATION, CTX_NONE);
        
        set_active_base(BASACT);
        
@@ -6953,7 +5790,7 @@ void selectlinks(int nr)
                                                if(mat1==mat) base->flag |= SELECT;
                                        }
                                        else if(mat1 && nr==4) {
-                                               for(b=0; b<8; b++) {
+                                               for(b=0; b<MAX_MTEX; b++) {
                                                        if(mat1->mtex[b]) {
                                                                if(tex==mat1->mtex[b]->tex) base->flag |= SELECT;
                                                        }
@@ -6968,6 +5805,7 @@ void selectlinks(int nr)
        allqueue(REDRAWVIEW3D, 0);
        allqueue(REDRAWDATASELECT, 0);
        allqueue(REDRAWOOPS, 0);
+       BIF_undo_push("Select links");
 }
 
 void image_aspect(void)
@@ -6994,7 +5832,7 @@ void image_aspect(void)
                        for(a=1; a<=ob->totcol; a++) {
                                ma= give_current_material(ob, a);
                                if(ma) {
-                                       for(b=0; b<8; b++) {
+                                       for(b=0; b<MAX_MTEX; b++) {
                                                if(ma->mtex[b] && ma->mtex[b]->tex) {
                                                        tex= ma->mtex[b]->tex;
                                                        if(tex->type==TEX_IMAGE && tex->ima && tex->ima->ibuf) {
@@ -7028,6 +5866,7 @@ void image_aspect(void)
        }
        
        allqueue(REDRAWVIEW3D, 0);
+       BIF_undo_push("Image aspect");
 }
 
 void set_ob_ipoflags(void)
@@ -7078,7 +5917,7 @@ void select_select_keys(void)
        
        if(G.scene->id.lib) return;
 
-       if(okee("show and select all keys")==0) return;
+       if(okee("Show and select all keys")==0) return;
 
        base= FIRSTBASE;
        while(base) {
@@ -7109,6 +5948,8 @@ void select_select_keys(void)
        allspace(REMAKEIPO, 0);
        allqueue(REDRAWIPO, 0);
 
+       BIF_undo_push("Select keys");
+
 }
 
 
@@ -7199,7 +6040,7 @@ void texspace_edit(void)
                return;
        }
        
-       nr= pupmenu("Texture space %t|Grabber%x1|Size%x2");
+       nr= pupmenu("Texture Space %t|Grab/Move%x1|Size%x2");
        if(nr<1) return;
        
        base= FIRSTBASE;
@@ -7211,13 +6052,13 @@ void texspace_edit(void)
        }
        
 
-       transmode= TRANS_TEX;
+       //transmode= TRANS_TEX;
        
-       if(nr==1) transform('g');
-       else if(nr==2) transform('s');
-       else if(nr==3) transform('r');
+       if(nr==1) Transform(TFM_TRANSLATION, CTX_TEXTURE);
+       else if(nr==2) Transform(TFM_RESIZE, CTX_TEXTURE);
+       else if(nr==3) Transform(TFM_ROTATION, CTX_TEXTURE);
        
-       transmode= 0;
+       //transmode= 0;
 }
 
 void first_base(void)
@@ -7225,7 +6066,7 @@ void first_base(void)
        /* inserts selected Bases in beginning of list, sometimes useful for operation order */
        Base *base, *next;
        
-       if(okee("make first base")==0) return;
+       if(okee("Make first base")==0) return;
        
        base= FIRSTBASE;
        while(base) {
@@ -7252,13 +6093,13 @@ void make_displists_by_obdata(void *obdata) {
 /* ******************************************************************** */
 /* Mirror function in Edit Mode */
 
-void mirror(short mode) {
-       short axis, a;
+void mirror_edit(short mode) 
+{
+       int a;
+       short axis;
        float mat[3][3], imat[3][3], min[3], max[3];
        TransVert *tv;
 
-       if(G.obedit->type==OB_MESH) undo_push_mesh("Mirror"); /* If it's a mesh, push it down the undo pipe */
-
        make_trans_verts(min, max, 0);
        Mat3CpyMat4(mat, G.obedit->obmat);
        // Inverting the matrix explicitly, since the inverse is not always correct (then why the heck are we keeping it!)
@@ -7378,19 +6219,89 @@ void mirror(short mode) {
        clearbaseflags_for_editing();
        if(transvmain) MEM_freeN(transvmain);
        transvmain= 0;
+       tottrans= 0;
+       
+       BIF_undo_push("Mirror");
+}
+
+void mirror_object(short mode) 
+{
+       TransOb *tob;
+       int a;
+       short axis;
+       float off[3], imat[3][3];
+
+       setbaseflags_for_editing('s');
+       figure_pose_updating();
+       make_trans_objects();
+
+       tob = transmain;
+
+       // Taking care of all the centre modes
+       if(G.vd->around==V3D_CENTROID) {
+               VecCopyf(centre, centroid);
+       }
+       else if(G.vd->around==V3D_CURSOR) {
+               float *curs;
+               curs= give_cursor();
+               VECCOPY(centre, curs);
+       }
+       else if(G.vd->around==V3D_LOCAL) {
+            &