Initial new transform commit.
authorMartin Poirier <theeth@yahoo.com>
Mon, 14 Feb 2005 02:53:36 +0000 (02:53 +0000)
committerMartin Poirier <theeth@yahoo.com>
Mon, 14 Feb 2005 02:53:36 +0000 (02:53 +0000)
Disabled behind defines. Uncomment //#define NEWTRANSFORM in transform.h to enable.

Use at your own risk

For more info, see Wiki: http://wiki.blender.org/bin/view.pl/Blenderdev/TransformRefactoring
And tuhopuu mailing list: http://projects.blender.org/pipermail/tuhopuu-devel/

Notes for Ton (things that could need bulldozing:
- TransData conversions. Objects is ok, but others could be rechecked. (some still use totsel). Need to add pose mode support.
- Need more icons in the PET mode dropdown (in the 3D view header) for the new modes
- Add new transform calls to Toolbox and Menus and the one right after Extrude.

That's pretty much all I can think of now.

12 files changed:
source/blender/src/SConscript
source/blender/src/drawview.c
source/blender/src/editobject.c
source/blender/src/space.c
source/blender/src/transform.c [new file with mode: 0755]
source/blender/src/transform.h [new file with mode: 0755]
source/blender/src/transform_constraints.c [new file with mode: 0755]
source/blender/src/transform_constraints.h [new file with mode: 0755]
source/blender/src/transform_generics.c [new file with mode: 0755]
source/blender/src/transform_generics.h [new file with mode: 0755]
source/blender/src/transform_numinput.c [new file with mode: 0755]
source/blender/src/transform_numinput.h [new file with mode: 0755]

index 35b992ce7b164061207274a0781592cd51a64352..22192a63e85510cd66f087733b69a1c4e9c714d3 100644 (file)
@@ -85,6 +85,7 @@ source_files = ['B.blend.c',
                 'header_sound.c',
                 'header_text.c',
                 'header_view3d.c',
+                'imagepaint.c',
                 'imasel.c',
                 'interface.c',
                 'interface_panel.c',
@@ -110,6 +111,10 @@ source_files = ['B.blend.c',
                 'swapbuffers.c',
                 'toets.c',
                 'toolbox.c',
+                'transform.c',
+                'transform_generics.c',
+                'transform_numinput.c',
+                'transform_constraints.c',
                 'unwrapper.c',
                 'usiblender.c',
                 'view.c',
index 70464cef034f94314c18f30d9b6ec34e042ae753..51a0c6598431ecd81ed6c48ec1e41eb9ea638205 100644 (file)
 #include "mydevice.h"
 #include "butspace.h"  // event codes
 
+#include "transform_constraints.h"
+
 /* Modules used */
 #include "render.h"            // for ogl render
 #include "radio.h"
@@ -1908,7 +1910,13 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
                base= base->next;
        }
 
-       if(G.moving) constline_callback();
+       if(G.moving) {
+               constline_callback();
+#ifdef NEWTRANSFORM
+               drawConstraint();
+               drawPropCircle();
+#endif
+       }
 
        /* duplis, draw as last to make sure the displists are ok */
        base= G.scene->base.first;
index 65d2a4b38d78c6ebbd27560053a7312c87d376d6..3f89e340d3a2439583b006c0ed6575dd827689f2 100644 (file)
 
 #include "blendef.h"
 
+#include "transform.h"
+
 #include "BIF_poseobject.h"
 
 /*  extern Lattice *copy_lattice(Lattice *lt); */
@@ -760,7 +762,7 @@ void make_track(void)
                allqueue(REDRAWOOPS, 0);
                sort_baselist(G.scene);
        }
-       BIF_undo_push("make Track");
+       BIF_undo_push("Make Track");
 }
 
 void apply_obmat(Object *ob)
@@ -886,8 +888,6 @@ void clear_object(char mode)
        else if(mode=='o') str= "Clear origin";
        else return;
        
-       if(okee(str)==0) return;
-       
        if (G.obpose){
 
                switch (G.obpose->type){
@@ -4142,16 +4142,18 @@ void make_trans_verts(float *min, float *max, int mode)
 
 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];
+
+               if(G.moving) {
 
-               BIF_ThemeColor(TH_GRID);
+                       BIF_ThemeColor(TH_GRID);
 
-               mygetmatrix(tmat);
-               Mat4Invert(imat, tmat);
+                       mygetmatrix(tmat);
+                       Mat4Invert(imat, tmat);
 
-               drawcircball(prop_cent, prop_size, imat);
+                       drawcircball(prop_cent, prop_size, imat);
+               }
        }
 }
 
@@ -6080,7 +6082,7 @@ void transform(int mode)
                                                dist= vec[0]-centre[0];
 
                                                if ((typemode) && (addvec[0]))
-                                                       phi0= (Dist1*addvec[0]*M_PI/(360.0*dist)) - 0.5*M_PI;
+                                                       phi0= (dist*addvec[0]*M_PI/(360.0*Dist1)) - 0.5*M_PI;
                                                else
                                                        phi0= (circumfac*dist/rad) - 0.5*M_PI;
 
@@ -6685,6 +6687,7 @@ void transform(int mode)
        special_aftertrans_update(mode, a & 1, canceled, keyflags);
 
        allqueue(REDRAWVIEW3D, 0);
+       allqueue(REDRAWBUTSOBJECT, 0);
        scrarea_queue_headredraw(curarea);
 
        clearbaseflags_for_editing();
@@ -6722,7 +6725,11 @@ void std_rmouse_transform(void (*xf_func)(int))
        while(get_mbut() & mousebut) {
                getmouseco_areawin(mval);
                if(abs(mval[0]-xo)+abs(mval[1]-yo) > 10) {
+#ifdef NEWTRANSFORM
+                       Transform(TRANSLATION);
+#else
                        xf_func('g');
+#endif
                        while(get_mbut() & mousebut) BIF_wait_for_statechange();
                        return;
                }
@@ -7827,7 +7834,7 @@ void select_select_keys(void)
        allspace(REMAKEIPO, 0);
        allqueue(REDRAWIPO, 0);
 
-       BIF_undo_push("Selet keys");
+       BIF_undo_push("Select keys");
 
 }
 
index 48f03b584d65221c1a960253e78886ff4c1f3bf5..50714cb8af2d730dc57f321b488a227081e5cabd 100644 (file)
 #include "blendef.h"
 #include "datatoc.h"
 
+#include "transform.h"
+
 #include "TPT_DependKludge.h"
 #ifdef NAN_TPT
 #include "BSE_trans_types.h"
@@ -1208,10 +1210,16 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                else if(G.qual & LR_ALTKEY) rem_selected_from_group(); */
                                if((G.qual==LR_SHIFTKEY))
                                        select_group_menu();
-                               else if(G.qual==LR_ALTKEY)
-                                       clear_object('g');
-                               else if((G.qual==0))
+                               else if(G.qual==LR_ALTKEY) {
+                                       if(okee("Clear location")) {
+                                               clear_object('g');
+                                       }
+                               } else if((G.qual==0))
+#ifdef NEWTRANSFORM
+                                       Transform(TRANSLATION);
+#else
                                        transform('g');
+#endif
                                break;
                        case HKEY:
                                if(G.obedit) {
@@ -1402,24 +1410,29 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                break;
                        case OKEY:
                                ob= OBACT;
-                               if(G.obedit) {
+                               if (G.qual==LR_SHIFTKEY) {
                                        extern int prop_mode;
-
-                                       if (G.qual==LR_SHIFTKEY) {
-                                               prop_mode= !prop_mode;
-                                               allqueue(REDRAWHEADERS, 0);
-                                       }
-                                       else if((G.qual==0)) {
-                                               G.f ^= G_PROPORTIONAL;
-                                               allqueue(REDRAWHEADERS, 0);
-                                       }
+#ifdef NEWTRANSFORM
+                                       prop_mode = (prop_mode+1)%5;
+#else
+                                       prop_mode= !prop_mode;
+#endif
+                                       allqueue(REDRAWHEADERS, 0);
                                }
-                               else if((G.qual==LR_SHIFTKEY)) {
+                               else if((G.qual==0)) {
+                                       G.f ^= G_PROPORTIONAL;
+                                       allqueue(REDRAWHEADERS, 0);
+                               }
+                               else if((G.qual==LR_CTRLKEY)) {
                                        if(ob && ob->type == OB_MESH) {
                                                flip_subdivison(ob, -1);
                                        }
                                }
-                               else if(G.qual==LR_ALTKEY) clear_object('o');
+                               else if(G.qual==LR_ALTKEY) {
+                                       if(okee("Clear origin")) {
+                                               clear_object('o');
+                                       }
+                               }
                                break;
 
                        case PKEY:
@@ -1443,9 +1456,11 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                        case RKEY:
                                if((G.obedit==0) && (G.f & G_FACESELECT) && (G.qual==0))
                                        rotate_uv_tface();
-                               else if(G.qual==LR_ALTKEY)
-                                       clear_object('r');
-                               else if (G.obedit) {
+                               else if(G.qual==LR_ALTKEY) {
+                                       if(okee("Clear rotation")) {
+                                               clear_object('r');
+                                       }
+                               } else if (G.obedit) {
                                        if((G.qual==LR_SHIFTKEY)) {
                                                if ELEM(G.obedit->type,  OB_CURVE, OB_SURF)                                     
                                                        selectrow_nurb();
@@ -1457,29 +1472,60 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                                        loopoperations(LOOP_CUT);
                                        }
                                        else if((G.qual==0))
+#ifdef NEWTRANSFORM
+                                               Transform(ROTATION);
+#else
                                                transform('r');
+#endif
                                }
                                else if((G.qual==0))
+#ifdef NEWTRANSFORM
+                                       Transform(ROTATION);
+#else
                                        transform('r');
+#endif
                                break;
                        case SKEY:
                                if(G.obedit) {
                                        if(G.qual==LR_ALTKEY)
                                                transform('N'); /* scale along normal */
                                        else if(G.qual==LR_CTRLKEY)
+#ifdef NEWTRANSFORM
+                                               Transform(SHEAR);
+                                       else if(G.qual==(LR_CTRLKEY|LR_ALTKEY))
+                                               Transform(SHEAR);
+#else
                                                transform('S');
+#endif
                                        else if(G.qual==LR_SHIFTKEY)
                                                snapmenu();
-                                       else if((G.qual==0))
+                                       else if(G.qual==0)
+#ifdef NEWTRANSFORM
+                                               Transform(RESIZE);
+                                       else if(G.qual==(LR_SHIFTKEY|LR_CTRLKEY))
+                                               Transform(TOSPHERE);
+#else
                                                transform('s');
+#endif
                                }
                                else if(G.qual==LR_ALTKEY) {
-                                       clear_object('s');
+                                       if(okee("Clear size")) {
+                                               clear_object('s');
+                                       }
                                }
-                               else if((G.qual==LR_SHIFTKEY))
+                               else if(G.qual==LR_SHIFTKEY) {
                                        snapmenu();
+                               }
                                else if((G.qual==0))
+#ifdef NEWTRANSFORM
+                                       Transform(RESIZE);
+                               else if(G.qual==(LR_SHIFTKEY|LR_CTRLKEY))
+                                       Transform(TOSPHERE);
+                               else if(G.qual==(LR_CTRLKEY|LR_ALTKEY))
+                                       Transform(SHEAR);
+#else
                                        transform('s');
+#endif
                                break;
                        case TKEY:
                                if(G.obedit){
diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c
new file mode 100755 (executable)
index 0000000..995a52a
--- /dev/null
@@ -0,0 +1,1375 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_image_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_property_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_constraint_types.h"
+
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_editview.h"
+#include "BIF_resources.h"
+#include "BIF_mywindow.h"
+#include "BIF_gl.h"
+#include "BIF_editlattice.h"
+#include "BIF_editarmature.h"
+#include "BIF_editmesh.h"
+
+#include "BKE_global.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_lattice.h"
+#include "BKE_armature.h"
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+
+#include "BSE_view.h"
+#include "BSE_edit.h"
+
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "blendef.h"
+
+#include "mydevice.h"
+
+extern ListBase editNurb;
+extern ListBase editelems;
+
+#include "transform.h"
+#include "transform_generics.h"
+#include "transform_constraints.h"
+#include "transform_numinput.h"
+
+/* GLOBAL VARIABLE THAT SHOULD MOVED TO SCREEN MEMBER OR SOMETHING  */
+TransInfo trans;
+int    LastMode = TRANSLATION;
+
+/* ************************** Functions *************************** */
+
+/* ************************** CONVERSIONS ************************* */
+
+int allocTransData()
+{
+    int count, mode=0;
+    countall();
+       
+       if(mode) count= G.totvert;
+       else count= G.totvertsel;
+       printf("count: %d\n", count);
+       if(G.totvertsel==0) {
+               count= 0;
+               return count;
+       }
+       
+       trans.total = count;
+       trans.data= MEM_mallocN(trans.total*sizeof(TransData), "TransObData(EditMode)");
+       return count;
+}
+
+void createTransArmatureVerts()
+{
+       EditBone *ebo;
+       TransData *tv;
+       float mtx[3][3], smtx[3][3];
+
+       trans.total = 0;
+       for (ebo=G.edbo.first;ebo;ebo=ebo->next){
+               if (ebo->flag & BONE_TIPSEL){
+                       trans.total++;
+               }
+               if (ebo->flag & BONE_ROOTSEL){
+                       trans.total++;
+               }
+       }
+
+    if (!trans.total) return;
+       
+       Mat3CpyMat4(mtx, G.obedit->obmat);
+       Mat3Inv(smtx, mtx);
+
+    tv = trans.data = MEM_mallocN(trans.total*sizeof(TransData), "TransEditBone");
+       
+       Mat3CpyMat4(mtx, G.obedit->obmat);
+       Mat3Inv(smtx, mtx);
+    
+       for (ebo=G.edbo.first;ebo;ebo=ebo->next){
+               if (ebo->flag & BONE_TIPSEL){
+                       VECCOPY (tv->iloc, ebo->tail);
+                       tv->loc= ebo->tail;
+                       tv->flag= TD_SELECTED;
+
+                       Mat3CpyMat3(tv->smtx, smtx);
+                       Mat3CpyMat3(tv->mtx, mtx);
+
+                       tv->size = NULL;
+                       tv->rot = NULL;
+
+                       tv->dist = 0.0f;
+            
+                       tv++;
+               }
+               if (ebo->flag & BONE_ROOTSEL){
+                       VECCOPY (tv->iloc, ebo->head);
+                       tv->loc= ebo->head;
+                       tv->flag= TD_SELECTED;
+
+                       Mat3CpyMat3(tv->smtx, smtx);
+                       Mat3CpyMat3(tv->mtx, mtx);
+
+                       tv->size = NULL;
+                       tv->rot = NULL;
+
+                       tv->dist = 0.0f;
+        
+                       tv++;
+               }
+                       
+       }
+}
+
+void createTransMBallVerts()
+{
+       MetaElem *ml;
+    TransData *tv;
+    int count;
+       float mtx[3][3], smtx[3][3];
+
+    count = allocTransData();
+    if (!count) return;
+
+       Mat3CpyMat4(mtx, G.obedit->obmat);
+       Mat3Inv(smtx, mtx);
+    
+       tv = trans.data;
+    ml= editelems.first;
+       while(ml) {
+               if(ml->flag & SELECT) {
+                       tv->loc= &ml->x;
+                       VECCOPY(tv->iloc, tv->loc);
+                       VECCOPY(tv->center, tv->loc);
+                       tv->flag= TD_SELECTED;
+
+                       Mat3CpyMat3(tv->smtx, smtx);
+                       Mat3CpyMat3(tv->mtx, mtx);
+
+                       tv->size = &ml->expx;
+                       tv->isize[0] = ml->expx;
+                       tv->isize[1] = ml->expy;
+                       tv->isize[2] = ml->expz;
+
+                       tv->rot = NULL;
+
+                       tv->dist = 0.0f;
+
+                       tv++;
+               }
+               ml= ml->next;
+       }
+} 
+
+void createTransCurveVerts()
+{
+    TransData *tv = NULL;
+       int count=0;
+    int mode = 0; /*This used for. . .what?*/
+       Nurb *nu;
+       BezTriple *bezt;
+       BPoint *bp;
+       int a;
+    int proptrans= 0;
+       float mtx[3][3], smtx[3][3];
+
+    count = allocTransData();
+       if (!count) return;
+
+       Mat3CpyMat4(mtx, G.obedit->obmat);
+       Mat3Inv(smtx, mtx);
+
+    tv = trans.data;
+       nu= editNurb.first;
+       while(nu) {
+               if((nu->type & 7)==CU_BEZIER) {
+                       a= nu->pntsu;
+                       bezt= nu->bezt;
+                       while(a--) {
+                               if(bezt->hide==0) {
+                                       if(mode==1 || (bezt->f1 & 1)) {
+                                               VECCOPY(tv->iloc, bezt->vec[0]);
+                                               tv->loc= bezt->vec[0];
+                                               VECCOPY(tv->center, tv->loc);
+                                               tv->flag= TD_SELECTED;
+                                               tv->rot = NULL;
+                                               tv->size = NULL;
+
+                                               Mat3CpyMat3(tv->smtx, smtx);
+                                               Mat3CpyMat3(tv->mtx, mtx);
+
+                                               tv->dist = 0.0f;
+            
+                                               tv++;
+                                               count++;
+                                       }
+                                       if(mode==1 || (bezt->f2 & 1)) {
+                                               VECCOPY(tv->iloc, bezt->vec[1]);
+                                               tv->loc= bezt->vec[1];
+                                               VECCOPY(tv->center, tv->loc);
+                                               tv->flag= TD_SELECTED;
+                                               tv->rot = NULL;
+                                               tv->size = NULL;
+
+                                               Mat3CpyMat3(tv->smtx, smtx);
+                                               Mat3CpyMat3(tv->mtx, mtx);
+
+                                               tv->dist = 0.0f;
+            
+                                               tv++;
+                                               count++;
+                                       }
+                                       if(mode==1 || (bezt->f3 & 1)) {
+                                               VECCOPY(tv->iloc, bezt->vec[2]);
+                                               tv->loc= bezt->vec[2];
+                                               VECCOPY(tv->center, tv->loc);
+                                               tv->flag= TD_SELECTED;
+                                               tv->rot = NULL;
+                                               tv->size = NULL;
+
+                                               Mat3CpyMat3(tv->smtx, smtx);
+                                               Mat3CpyMat3(tv->mtx, mtx);
+
+                                               tv->dist = 0.0f;
+            
+                                               tv++;
+                                               count++;
+                                       }
+                               }
+                               bezt++;
+                       }
+               }
+               else {
+                       a= nu->pntsu*nu->pntsv;
+                       bp= nu->bp;
+                       while(a--) {
+                               if(bp->hide==0) {
+                                       if(mode==1 || (bp->f1 & 1)) {
+                                               VECCOPY(tv->iloc, bp->vec);
+                                               tv->loc= bp->vec;
+                                               VECCOPY(tv->center, tv->loc);
+                                               tv->flag= TD_SELECTED;
+                                               tv->rot = NULL;
+                                               tv->size = NULL;
+
+                                               Mat3CpyMat3(tv->smtx, smtx);
+                                               Mat3CpyMat3(tv->mtx, mtx);
+
+                                               tv->dist = 0.0f;
+            
+                                               tv++;
+                                               count++;
+                                       }
+                               }
+                               bp++;
+                       }
+               }
+               nu= nu->next;
+       }
+}
+
+void createTransLatticeVerts()
+{
+    TransData *tv = NULL;
+    int count = 0;
+       BPoint *bp;
+       float mtx[3][3], smtx[3][3];
+
+    int mode = 0; /*This used for proportional editing*/
+    /*should find a function that does this. . . what else is this used for? I DONT KNOW!*/
+    int a;
+    int proptrans= 0;
+    bp= editLatt->def;
+    
+       
+       count = allocTransData();
+       
+       if (!count) return;
+       
+       Mat3CpyMat4(mtx, G.obedit->obmat);
+       Mat3Inv(smtx, mtx);
+
+       tv = trans.data;
+       bp= editLatt->def;
+       a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+       while(a--) {
+               if(mode==1 || (bp->f1 & 1)) {
+                       if(bp->hide==0) {
+                               VECCOPY(tv->iloc, bp->vec);
+                               tv->loc= bp->vec;
+                               VECCOPY(tv->center, tv->loc);
+                               tv->flag= TD_SELECTED;
+
+                               Mat3CpyMat3(tv->smtx, smtx);
+                               Mat3CpyMat3(tv->mtx, mtx);
+
+                               tv->size = NULL;
+                               tv->rot = NULL;
+
+                               tv->dist = 0.0f;
+
+                               tv++;
+                               count++;
+                       }
+               }
+               bp++;
+       }
+} 
+
+void VertsToTransData(TransData *tob, EditVert *eve)
+{
+       tob->flag = 0;
+    tob->loc = eve->co;
+       VECCOPY(tob->center, tob->loc);
+       VECCOPY(tob->iloc, tob->loc);
+       tob->rot = NULL; 
+    tob->size = NULL;
+    tob->quat = NULL;
+}
+
+void createTransEditVerts()
+{
+    TransData *tob = NULL;
+    int totsel = 0;
+    EditMesh *em = G.editMesh;
+    EditVert *eve;
+       float mtx[3][3], smtx[3][3];
+
+    /*should find a function that does this. . .*/
+    int proptrans= 0;
+               
+       // transform now requires awareness for select mode, so we tag the f1 flags in verts
+       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;
+                               trans.total++;
+                       }
+                       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)
+                               trans.total++;
+       }
+       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)
+                               trans.total++;
+       }
+       
+       totsel = trans.total;
+       /* proportional edit exception... */
+       if((G.f & G_PROPORTIONAL) && trans.total) {
+               for(eve= em->verts.first; eve; eve= eve->next) {
+                       if(eve->h==0 && (!(eve->f1 & SELECT))) {
+                               eve->f1 = 2;
+                               trans.total++;
+                       }
+               }
+       }
+       
+       /* and now make transverts */
+    
+    if (!trans.total) return;
+       
+       Mat3CpyMat4(mtx, G.obedit->obmat);
+       Mat3Inv(smtx, mtx);
+
+    tob = trans.data = MEM_mallocN(trans.total*sizeof(TransData), "TransEditVert");
+
+    for (eve=em->verts.first; eve; eve=eve->next)
+    {
+        if (eve->f1 == SELECT) {
+                       VertsToTransData(tob, eve);
+
+               tob->flag |= TD_SELECTED;
+
+                       Mat3CpyMat3(tob->smtx, smtx);
+                       Mat3CpyMat3(tob->mtx, mtx);
+
+                       tob->dist = 0.0f;
+
+                       tob++;
+           }    
+    }    
+
+       /* PROPORTIONAL*/
+       if (G.f & G_PROPORTIONAL) {
+               for (eve=em->verts.first; eve; eve=eve->next)
+               {
+                       TransData *td;
+                       int i;
+                       float dist, vec[3];
+                       if (eve->f1 == 2) {
+
+                               VertsToTransData(tob, eve);
+
+                               Mat3CpyMat3(tob->smtx, smtx);
+                               Mat3CpyMat3(tob->mtx, mtx);
+            
+                               tob->dist = -1;
+
+                               td = trans.data;
+                               for (i = 0; i < totsel; i++, td++) {
+                                       VecSubf(vec, tob->center, td->center);
+                                       Mat3MulVecfl(mtx, vec);
+                                       dist = Normalise(vec);
+                                       if (tob->dist == -1) {
+                                               tob->dist = dist;
+                                       }
+                                       else if (dist < tob->dist) {
+                                               tob->dist = dist;
+                                       }
+                               }
+
+                               tob++;
+                       }    
+               }    
+       }
+}
+
+void ObjectToTransData(TransData *tob, Object *ob) {
+       float totmat[3][3], obinv[3][3], obmtx[3][3];
+       Object *tr;
+       void *cfirst, *clast;
+
+       cfirst = ob->constraints.first;
+       clast = ob->constraints.last;
+       ob->constraints.first=ob->constraints.last=NULL;
+
+       tr= ob->track;
+       ob->track= NULL;
+
+       where_is_object(ob);
+
+       ob->track= tr;
+
+       ob->constraints.first = cfirst;
+       ob->constraints.last = clast;
+
+       tob->ob = ob;
+
+       tob->loc = ob->loc;
+       VECCOPY(tob->iloc, tob->loc);
+       
+       tob->rot = ob->rot;
+       VECCOPY(tob->irot, ob->rot);
+       
+       tob->size = ob->size;
+       VECCOPY(tob->isize, ob->size);
+
+       VECCOPY(tob->center, ob->obmat[3]);
+
+       Mat3CpyMat4(tob->mtx, ob->obmat);
+
+       object_to_mat3(ob, obmtx);
+
+       Mat3CpyMat4(totmat, ob->obmat);
+       Mat3Inv(obinv, totmat);
+       Mat3MulMat3(tob->smtx, obmtx, obinv);
+}
+
+void createTransObject()
+{
+       TransData *tob = NULL;
+       Object *ob;
+       Base *base;
+       int totsel = 0, i;
+
+       /* count */     
+       base= FIRSTBASE;
+       while(base) {
+               if TESTBASELIB(base) {
+                       trans.total++;
+                       totsel++;
+               }
+               else if (G.f & G_PROPORTIONAL) {
+                       ob= base->object;
+                       if (G.vd->lay & ob->lay) {
+                               trans.total++;
+                       }
+               }
+               base= base->next;
+       }
+
+       if(!trans.total)
+               return;
+
+       tob = trans.data = MEM_mallocN(trans.total*sizeof(TransData), "TransOb");
+
+       base= FIRSTBASE;
+       while(base) {
+               if TESTBASELIB(base) {
+                       ob= base->object;
+                       
+                       tob->flag= TD_SELECTED;
+
+                       ObjectToTransData(tob, ob);
+
+                       tob->dist = 0.0f;
+
+                       tob++;
+               }
+               base= base->next;
+       }
+
+
+       /* PROPORTIONAL*/
+       if (G.f & G_PROPORTIONAL) {
+               base= FIRSTBASE;
+               while(base) {
+                       if (!TESTBASELIB(base)) {
+                               TransData *td;
+                               int i;
+                               float dist;
+
+                               ob= base->object;
+                               
+                               if (G.vd->lay & ob->lay) {
+                                       tob->flag = 0;
+
+                                       tob->ob = ob;
+                               
+                                       ObjectToTransData(tob, ob);
+
+                                       tob->dist = -1;
+
+                                       td = trans.data;
+                                       for (i = 0; i < totsel; i++, td++) {
+                                               dist = VecLenf(tob->center, td->center);
+                                               if (tob->dist == -1) {
+                                                       tob->dist = dist;
+                                               }
+                                               else if (dist < tob->dist) {
+                                                       tob->dist = dist;
+                                               }
+                                       }
+
+                                       tob++;
+                               }
+                       }
+                       base= base->next;
+               }
+       }
+
+/*
+       KICK OUT CHILDS OF OBJECTS THAT ARE BEING TRANSFORMED
+       SINCE TRANSFORMATION IS ALREADY APPLIED ON PARENT
+
+       THERE MUST BE A BETTER WAY TO DO THIS
+*/
+
+       tob = trans.data;
+       for (i = 0; i < trans.total; i++, tob++) {
+               ob = tob->ob->parent;
+               while (ob) {
+                       TransData *td;
+                       int j, found = 0;
+                       td = trans.data;
+                       for (j = 0; j < trans.total; j++, td++) {
+                               if (ob == td->ob) {
+                                       found = 1;
+                                       tob->flag |= TD_NOACTION;
+                                       break;
+                               }
+                       }
+
+                       if (found) {
+                               break;
+                       }
+
+                       ob = ob->parent;
+               }
+       }
+
+}
+
+void createTransData() {
+       if (G.obedit) {
+               if (G.obedit->type == OB_MESH) {
+                       createTransEditVerts(); 
+               }
+               else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
+               createTransCurveVerts();
+       }
+               else if (G.obedit->type==OB_LATTICE) {
+           createTransLatticeVerts();
+               }
+               else if (G.obedit->type==OB_MBALL) {
+                   createTransMBallVerts();
+               }
+               else if (G.obedit->type==OB_ARMATURE) {
+                   createTransArmatureVerts();
+               }                                       
+               else {
+                       printf("not done yet! only have mesh surface curve\n");
+               }
+       }
+       else {
+               createTransObject();
+       }
+}
+
+#define TRANS_CANCEL   2
+#define TRANS_CONFIRM  1
+
+/* ************************** TRANSFORMATIONS **************************** */
+
+void Transform(int mode) {
+       int ret_val = 0;
+       short pmval[2] = {0, 0}, mval[2], val;
+       float MatI[3][3];
+       unsigned short event;
+
+       Mat3One(MatI);
+
+       /* stupid PET initialisation code */
+       /* START */
+       if (trans.propsize == 0.0f) {
+               trans.propsize = 1.0;
+       }
+       /* END */
+
+       if (mode == REPEAT) {
+               mode = LastMode;
+       }
+       else {
+               LastMode = mode;
+       }
+       
+       initTransModeFlags(&trans, mode);
+
+       initTrans(&trans);
+
+       createTransData();
+
+       if (trans.total == 0)
+               return;
+
+       calculatePropRatio(&trans);
+       calculateCenter(&trans);
+
+       switch (mode) {
+       case TRANSLATION:
+               initTranslation(&trans);
+               break;
+       case ROTATION:
+               initRotation(&trans);
+               break;
+       case RESIZE:
+               initResize(&trans);
+               break;
+       case TOSPHERE:
+               initToSphere(&trans);
+               break;
+       case SHEAR:
+               initShear(&trans);
+               break;
+       }
+
+       // Emptying event queue
+       while( qtest() ) {
+               event= extern_qread(&val);
+       }
+
+       /*joeedh -> hopefully may be what makes the old transform() constant*/  
+       areawinset(curarea->win);
+
+       trans.redraw = 1;
+
+       while (ret_val == 0) {
+               getmouseco_areawin(mval);
+               if (mval[0] != pmval[0] || mval[1] != pmval[1]) {
+                       trans.redraw = 1;
+               }
+               if (trans.redraw) {
+                       pmval[0] = mval[0];
+                       pmval[1] = mval[1];
+
+                       if (trans.transform) {
+                               trans.transform(&trans, mval);
+                       }
+                       trans.redraw = 0;
+               }
+               while( qtest() ) {
+                       event= extern_qread(&val);
+
+                       if(val) {
+                               switch (event){
+                               case MIDDLEMOUSE:
+                                       selectConstraint(&trans);
+                                       trans.redraw = 1;
+                                       break;
+                               case ESCKEY:
+                               case RIGHTMOUSE:
+                                       ret_val = TRANS_CANCEL;
+                                       break;
+                               case LEFTMOUSE:
+                               case SPACEKEY:
+                               case PADENTER:
+                               case RETKEY:
+                                       ret_val = TRANS_CONFIRM;
+                                       break;
+                               case GKEY:
+                               case SKEY:
+                               case RKEY:
+                                       if (G.qual == LR_CTRLKEY)
+                                               applyTransObjects(&trans);
+                                       else
+                                               restoreTransObjects(&trans);
+                                       break;
+                               case XKEY:
+                                       if (G.qual == 0)
+                                               setConstraint(&trans, MatI, (APPLYCON|CONAXIS0));
+                                       else if (G.qual == LR_CTRLKEY)
+                                               setConstraint(&trans, MatI, (APPLYCON|CONAXIS1|CONAXIS2));
+                                       break;
+                               case YKEY:
+                                       if (G.qual == 0)
+                                               setConstraint(&trans, MatI, (APPLYCON|CONAXIS1));
+                                       else if (G.qual == LR_CTRLKEY)
+                                               setConstraint(&trans, MatI, (APPLYCON|CONAXIS0|CONAXIS2));
+                                       break;
+                               case ZKEY:
+                                       if (G.qual == 0)
+                                               setConstraint(&trans, MatI, (APPLYCON|CONAXIS2));
+                                       else if (G.qual == LR_CTRLKEY)
+                                               setConstraint(&trans, MatI, (APPLYCON|CONAXIS0|CONAXIS1));
+                                       break;
+                               case OKEY:
+                                       if (G.qual==LR_SHIFTKEY) {
+                                               extern int prop_mode;
+                                               prop_mode = (prop_mode+1)%5;
+                                               calculatePropRatio(&trans);
+                                               trans.redraw= 1;
+                                       }
+                                       break;
+                               case WHEELDOWNMOUSE:
+                               case PADPLUSKEY:
+                                       if(G.f & G_PROPORTIONAL) {
+                                               trans.propsize*= 1.1f;
+                                               calculatePropRatio(&trans);
+                                               trans.redraw= 1;
+                                       }
+                                       break;
+                               case WHEELUPMOUSE:
+                               case PADMINUS:
+                                       if(G.f & G_PROPORTIONAL) {
+                                               trans.propsize*= 0.90909090f;
+                                               calculatePropRatio(&trans);
+                                               trans.redraw= 1;
+                                       }
+                                       break;
+                               }
+                               trans.redraw |= handleNumInput(&(trans.num), event);
+                               arrows_move_cursor(event);
+                       }
+                       else {
+                               switch (event){
+                               case MIDDLEMOUSE:
+                                       chooseConstraint(&trans);
+                                       trans.redraw = 1;
+                                       break;
+                               case LEFTMOUSE:
+                               case RIGHTMOUSE:
+                                       ret_val = TRANS_CONFIRM;
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if(ret_val == TRANS_CANCEL) {
+               restoreTransObjects(&trans);
+       }
+       else {
+               BIF_undo_push("Transform");
+       }
+
+       postTrans(&trans);
+}
+
+/* ************************** WRAP *************************** */
+
+void initWrap(TransInfo *t) {
+       float min[3], max[3], loc[3];
+       int i;
+       calculateCenterCursor(t);
+       t->num.idx_max = 0;
+       t->transform = Wrap;
+
+       for(i = 0; i < t->total; i++) {
+               VECCOPY(loc, t->data[i].iloc);
+               if (G.obedit) {
+                       Mat4MulVecfl(G.obedit->obmat, loc);
+               }
+               Mat4MulVecfl(G.vd->viewmat, loc);
+               if (i) {
+                       MinMax3(min, max, loc);
+               }
+               else {
+                       VECCOPY(max, loc);
+                       VECCOPY(min, loc);
+               }
+       }
+
+
+       t->fac = (float)(t->center2d[0] - t->imval[0]);
+}
+
+
+int Wrap(TransInfo *t, short mval[2]) {
+       return 1;
+}
+
+/* ************************** SHEAR *************************** */
+
+void initShear(TransInfo *t) {
+       t->num.idx_max = 0;
+       t->transform = Shear;
+       t->fac = (float)(t->center2d[0] - t->imval[0]);
+}
+
+int Shear(TransInfo *t, short mval[2]) {
+       float vec[3];
+       float smat[3][3], tmat[3][3], totmat[3][3], omat[3][3], persmat[3][3], persinv[3][3];
+       float value;
+       int i;
+       char str[50];
+       TransData *td = t->data;
+
+       Mat3CpyMat4(persmat, G.vd->viewmat);
+       Mat3Inv(persinv, persmat);
+
+       if (G.obedit) {
+               Mat3CpyMat4(omat, G.obedit->obmat);
+       }
+
+       value = -0.005f * ((float)(t->center2d[0] - mval[0]) - t->fac);
+
+       apply_grid1(&value, t->num.idx_max, 0.1f);
+
+       applyNumInput(&t->num, &value);
+
+       /* header print for NumInput */
+       if (hasNumInput(&t->num)) {
+               char c[20];
+
+               outputNumInput(&(t->num), c);
+
+               sprintf(str, "Shear: %s %s", c, t->proptext);
+       }
+       else {
+               /* default header print */
+               sprintf(str, "Shear: %.3f %s", value, t->proptext);
+       }
+       
+       Mat3One(smat);
+       smat[1][0] = value;
+       Mat3MulMat3(tmat, smat, persmat);
+       Mat3MulMat3(totmat, persinv, tmat);
+       
+       for(i = 0 ; i < t->total; i++, td++) {
+               if (td->flag & TD_NOACTION)
+                       continue;
+               if (G.obedit) {
+                       Mat3MulMat3(totmat, tmat, omat);
+                       Mat3MulMat3(tmat, td->smtx, totmat);
+               }
+               else {
+                       Mat3CpyMat3(tmat, totmat);
+               }
+               VecSubf(vec, td->iloc, t->center);
+
+               Mat3MulVecfl(tmat, vec);
+
+               VecAddf(vec, vec, t->center);
+               VecSubf(vec, vec, td->iloc);
+
+               VecMulf(vec, td->factor);
+
+               VecAddf(td->loc, td->iloc, vec);
+       }
+
+       recalcData(t);
+
+       headerprint(str);
+
+       force_draw(0);
+
+       helpline (t->center);
+
+       return 1;
+}
+
+/* ************************** RESIZE *************************** */
+
+void initResize(TransInfo *t) {
+       trans.fac = (float)sqrt( (float)
+               (
+                       (trans.center2d[1] - trans.imval[1])*(trans.center2d[1] - trans.imval[1])
+               +
+                       (trans.center2d[0] - trans.imval[0])*(trans.center2d[0] - trans.imval[0])
+               ) );
+
+       t->num.idx_max = 2;
+       t->transform = Resize;
+}
+
+int Resize(TransInfo *t, short mval[2]) {
+       float vec[3];
+       float size[3], tsize[3], mat[3][3], tmat[3][3], omat[3][3];
+       float ratio;
+       int i;
+       char str[50];
+       TransData *td = t->data;
+
+       if (G.obedit) {
+               Mat3CpyMat4(omat, G.obedit->obmat);
+       }
+
+       ratio = (float)sqrt( (float)
+               (
+                       (t->center2d[1] - mval[1])*(t->center2d[1] - mval[1])
+               +
+                       (t->center2d[0] - mval[0])*(t->center2d[0] - mval[0])
+               ) ) / t->fac;
+
+       size[0] = size[1] = size[2] = ratio;
+
+       apply_grid1(size, t->num.idx_max, 0.1f);
+
+       if (t->con.applyVec) {
+               t->con.applyVec(t, NULL, size, tsize);
+               VECCOPY(size, tsize);
+       }
+
+       applyNumInput(&t->num, size);
+
+       /* header print for NumInput */
+       if (hasNumInput(&t->num)) {
+               char c[60];
+
+               outputNumInput(&(t->num), c);
+
+               sprintf(str, "Size X: %s Y: %s Z: %s %s", &c[0], &c[20], &c[40], t->proptext);
+       }
+       else {
+               /* default header print */
+               sprintf(str, "Size X: %.3f Y: %.3f Z: %.3f %s", size[0], size[1], size[2], t->proptext);
+       }
+       
+       SizeToMat3(size, mat);
+       for(i = 0 ; i < t->total; i++, td++) {
+               if (td->flag & TD_NOACTION)
+                       continue;
+
+               if (G.obedit) {
+                       float smat[3][3];
+                       Mat3MulMat3(smat, td->smtx, mat);
+                       Mat3MulMat3(tmat, smat, omat);
+               }
+               else {
+                       Mat3CpyMat3(tmat, mat);
+               }
+
+               if (td->size) {
+                       // TEMPORARY NAIVE CODE
+                       td->size[0] = td->isize[0] + td->isize[0] * (size[0] - 1.0f) * td->factor;
+                       td->size[1] = td->isize[1] + td->isize[1] * (size[1] - 1.0f) * td->factor;
+                       td->size[2] = td->isize[2] + td->isize[2] * (size[2] - 1.0f) * td->factor;
+               }
+               VecSubf(vec, td->iloc, t->center);
+
+               Mat3MulVecfl(tmat, vec);
+
+               VecAddf(vec, vec, t->center);
+               VecSubf(vec, vec, td->iloc);
+
+               VecMulf(vec, td->factor);
+
+               VecAddf(td->loc, td->iloc, vec);
+       }
+
+       recalcData(t);
+
+       headerprint(str);
+
+       force_draw(0);
+
+       helpline (t->center);
+
+       return 1;
+}
+
+/* ************************** TOSPHERE *************************** */
+
+void initToSphere(TransInfo *t) {
+       TransData *td = t->data;
+       int i;
+
+       // Calculate average radius
+       for(i = 0 ; i < t->total; i++, td++) {
+               t->val += VecLenf(t->center, td->iloc);
+       }
+
+       t->val /= (float)t->total;
+
+       trans.fac = (float)sqrt( (float)
+               (
+                       (trans.center2d[1] - trans.imval[1])*(trans.center2d[1] - trans.imval[1])
+               +
+                       (trans.center2d[0] - trans.imval[0])*(trans.center2d[0] - trans.imval[0])
+               ) );
+
+       t->num.idx_max = 0;
+       t->transform = ToSphere;
+}
+
+
+
+int ToSphere(TransInfo *t, short mval[2]) {
+       float vec[3];
+       float ratio, radius;
+       int i;
+       char str[50];
+       TransData *td = t->data;
+
+       ratio = (float)sqrt( (float)
+               (
+                       (t->center2d[1] - mval[1])*(t->center2d[1] - mval[1])
+               +
+                       (t->center2d[0] - mval[0])*(t->center2d[0] - mval[0])
+               ) ) / t->fac;
+
+       apply_grid1(&ratio, t->num.idx_max, 0.1f);
+
+       applyNumInput(&t->num, &ratio);
+
+       if (ratio > 1.0f)
+               ratio = 1.0f;
+
+       /* header print for NumInput */
+       if (hasNumInput(&t->num)) {
+               char c[20];
+
+               outputNumInput(&(t->num), c);
+
+               sprintf(str, "To Sphere: %s %s", c, t->proptext);
+       }
+       else {
+               /* default header print */
+               sprintf(str, "To Sphere: %.4f %s", ratio, t->proptext);
+       }
+       
+       
+       for(i = 0 ; i < t->total; i++, td++) {
+               float tratio;
+               if (td->flag & TD_NOACTION)
+                       continue;
+               VecSubf(vec, td->iloc, t->center);
+
+               radius = Normalise(vec);
+
+               tratio = 1.0f - ((1.0f - ratio) * td->factor);
+
+               VecMulf(vec, radius * tratio + t->val * (1.0f - tratio));
+
+               VecAddf(td->loc, t->center, vec);
+       }
+
+       recalcData(t);
+
+       headerprint(str);
+
+       force_draw(0);
+
+       helpline (t->center);
+
+       return 1;
+}
+
+/* ************************** ROTATION *************************** */
+
+void initRotation(TransInfo *t) {
+       t->num.idx_max = 0;
+       t->fac = 0;
+       t->transform = Rotation;
+}
+
+int Rotation(TransInfo *t, short mval[2]) {
+       TransData *td = t->data;
+       int i;
+       char str[50];
+
+       float final;
+
+       int dx2 = t->center2d[0] - mval[0];
+       int dy2 = t->center2d[1] - mval[1];
+       float B = (float)sqrt(dx2*dx2+dy2*dy2);
+
+       int dx1 = t->center2d[0] - t->imval[0];
+       int dy1 = t->center2d[1] - t->imval[1];
+       float A = (float)sqrt(dx1*dx1+dy1*dy1);
+
+       int dx3 = mval[0] - t->imval[0];
+       int dy3 = mval[1] - t->imval[1];
+
+       float deler= ((dx1*dx1+dy1*dy1)+(dx2*dx2+dy2*dy2)-(dx3*dx3+dy3*dy3))
+               / (2 * A * B);
+
+       float dphi;
+
+       float vec[3], axis[3];
+       float mat[3][3], totmat[3][3], omat[3][3], smat[3][3];
+
+       if (G.obedit) {
+               Mat3CpyMat4(omat, G.obedit->obmat);
+       }
+
+       VECCOPY(axis, G.vd->persinv[2]);
+       Normalise(axis);
+
+       dphi = saacos(deler);
+       if( (dx1*dy2-dx2*dy1)>0.0 ) dphi= -dphi;
+
+       if(G.qual & LR_SHIFTKEY) t->fac += dphi/30.0f;
+       else t->fac += dphi;
+
+       final = t->fac;
+
+       apply_grid2(&final, t->num.idx_max, (float)((5.0/180)*M_PI), 0.2f);
+
+       t->imval[0] = mval[0];
+       t->imval[1] = mval[1];
+
+       if (t->con.applyRot) {
+               t->con.applyRot(t, NULL, axis);
+       }
+
+       if (hasNumInput(&t->num)) {
+               char c[20];
+
+               applyNumInput(&t->num, &final);
+
+               outputNumInput(&(t->num), c);
+
+               sprintf(str, "Rot: %s %s", &c[0], t->proptext);
+
+               final *= (float)(M_PI / 180.0);
+       }
+       else {
+               sprintf(str, "Rot: %.2f %s", 180.0*final/M_PI, t->proptext);
+       }
+
+       VecRotToMat3(axis, final * td->factor, mat);
+
+       for(i = 0 ; i < t->total; i++, td++) {
+               if (td->flag & TD_NOACTION)
+                       continue;
+
+               if (t->con.applyRot) {
+                       t->con.applyRot(t, td, axis);
+                       VecRotToMat3(axis, final * td->factor, mat);
+               }
+               else if (G.f & G_PROPORTIONAL) {
+                       VecRotToMat3(axis, final * td->factor, mat);
+               }
+
+               if (G.obedit) {
+                       Mat3MulMat3(totmat, mat, omat);
+                       Mat3MulMat3(smat, td->smtx, totmat);
+
+                       VecSubf(vec, td->iloc, t->center);
+                       Mat3MulVecfl(smat, vec);
+
+                       VecAddf(td->loc, vec, t->center);
+               }
+               else {
+                       float eul[3], fmat[3][3];
+
+                       /* translation */
+                       VecSubf(vec, td->center, t->center);
+                       Mat3MulVecfl(mat, vec);
+                       VecAddf(vec, vec, t->center);
+                       /* vec now is the location where the object has to be */
+                       VecSubf(vec, vec, td->center);
+                       Mat3MulVecfl(td->smtx, vec);
+
+                       VecAddf(td->loc, td->iloc, vec);
+
+                       Mat3MulMat3(totmat, mat, td->mtx);
+                       Mat3MulMat3(fmat, td->smtx, totmat);
+                       Mat3ToEul(fmat, eul);
+                       VECCOPY(td->rot, eul);
+
+               }
+       }
+
+       recalcData(t);
+
+       headerprint(str);
+
+       force_draw(0);
+
+       helpline (t->center);
+
+       return 1;
+}
+
+/* ************************** TRANSLATION *************************** */
+       
+void initTranslation(TransInfo *t) {
+       t->num.idx_max = 2;
+       t->transform = Translation;
+}
+
+int Translation(TransInfo *t, short mval[2]) {
+       float vec[3], tvec[3], *smtx = NULL;
+       int i;
+       char str[70];
+       TransData *td = t->data;
+
+       window_to_3d(vec, (short)(mval[0] - t->imval[0]), (short)(mval[1] - t->imval[1]));
+
+       if (t->con.applyVec) {
+               t->con.applyVec(t, NULL, vec, tvec);
+               VECCOPY(vec, tvec);
+       }
+
+       apply_grid1(vec, t->num.idx_max, 1.0f);
+
+       applyNumInput(&t->num, vec);
+
+       /* header print for NumInput */
+       if (hasNumInput(&t->num)) {
+               char c[60];
+
+               outputNumInput(&(t->num), c);
+
+               sprintf(str, "Dx: %s   Dy: %s  Dz: %s %s", &c[0], &c[20], &c[40], t->proptext);
+       }
+       else {
+               /* default header print */
+               sprintf(str, "Dx: %.4f   Dy: %.4f  Dz: %.4f %s", vec[0], vec[1], vec[2], t->proptext);
+       }
+
+
+       for(i = 0 ; i < t->total; i++, td++) {
+               if (td->flag & TD_NOACTION)
+                       continue;
+
+               if (t->con.applyVec) {
+                       t->con.applyVec(t, td, vec, tvec);
+               }
+               else {
+                       VECCOPY(tvec, vec);
+               }
+
+               Mat3MulVecfl(td->smtx, tvec);
+
+               VecMulf(tvec, td->factor);
+
+               VecAddf(td->loc, td->iloc, tvec);
+       }
+
+
+       recalcData(t);
+
+       headerprint(str);
+
+       force_draw(0);
+
+       return 1;
+}
\ No newline at end of file
diff --git a/source/blender/src/transform.h b/source/blender/src/transform.h
new file mode 100755 (executable)
index 0000000..9854471
--- /dev/null
@@ -0,0 +1,147 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef TRANSFORM_H
+#define TRANSFORM_H
+
+#include "transform_numinput.h"
+
+/* ************************** Types ***************************** */
+
+typedef struct TransCon {
+    char  text[50];      /* Description of the Constraint for header_print                            */
+    float mtx[3][3];     /* Matrix of the Constraint space                                            */
+    float imtx[3][3];    /* Inverse Matrix of the Constraint space                                    */
+    float center[3];     /* transformation centre to define where to draw the view widget             
+                            ALWAYS in global space. Unlike the transformation center                  */
+    int   mode;          /* Mode flags of the Constraint                                              */
+    void  (*applyVec)(struct TransInfo *, struct TransData *, float *, float *);
+                         /* Apply function pointer for linear vectorial transformation                */
+                         /* The last two parameters are pointers to the in/out vectors                */
+    void  (*applyRot)(struct TransInfo *, struct TransData *, float [3]);
+                         /* Apply function pointer for rotation transformation (prototype will change */
+} TransCon;
+
+typedef struct TransData {
+       float  dist;         /* Distance to the nearest element (for Proportionnal Editing)                    */
+       float  factor;       /* Factor of the transformation (for Proportionnal Editing)                       */
+    float *loc;          /* Location of the data to transform                                              */
+    float  iloc[3];      /* Initial location                                                               */
+    float *rot;          /* Rotation of the data to transform (Faculative)                                 */
+    float  irot[3];      /* Initial rotation                                                               */
+    float *quat;         /* Rotation quaternion of the data to transform (Faculative)                      */
+    float  iquat[4];    /* Initial rotation quaternion                                                    */
+    float *size;         /* Size of the data to transform (Faculative)                                     */
+    float  isize[3];    /* Initial size                                                                   */
+    float  center[3];
+    float  mtx[3][3];    /* Matrix of the data to transform                                                */
+    float  smtx[3][3];   /* Matrix needed to apply the changes (in most case, the inverse of the parent)   */
+       struct Object *ob;
+    int    flag;         /* Various flags                                                                  */
+} TransData;
+
+typedef struct TransInfo {
+    int         mode;           /* current mode                         */
+    int       (*transform)(struct TransInfo *, short *);
+                                /* transform function pointer           */
+    char        redraw;         /* redraw flag                          */
+    int                flags;          /* generic flags for special behaviors  */
+    int         total;          /* total number of transformed data     */
+       float           propsize;               /* proportional circle radius           */
+       char            proptext[20];   /* proportional falloff text                    */
+    float       center[3];      /* center of transformation             */
+    short       center2d[2];    /* center in screen coordinates         */
+    short       imval[2];       /* initial mouse position               */
+    TransData  *data;           /* transformed data (array)             */
+    TransCon    con;            /* transformed constraint               */
+    NumInput    num;            /* numerical input                      */
+    float       val;            /* init value for some transformations  */
+    float       fac;            /* factor for distance based transform  */
+} TransInfo;
+
+
+/* ******************** Macros & Prototypes *********************** */
+
+//#define NEWTRANSFORM
+
+/* MODE AND NUMINPUT FLAGS */
+#define NOCONSTRAINT   1
+#define NULLONE                        2
+#define NONEGATIVE             4
+#define        NOZERO                  8
+#define NOFRACTION             16
+
+
+#define REPEAT                 0
+#define TRANSLATION            1
+#define ROTATION               2
+#define RESIZE                 3
+#define TOSPHERE               4
+#define SHEAR                  5
+
+#define APPLYCON               1
+#define CONAXIS0               2
+#define CONAXIS1               4
+#define CONAXIS2               8
+
+#define PROP_SHARP             0
+#define PROP_SMOOTH            1
+#define PROP_ROOT              2
+#define PROP_LIN               3
+#define PROP_CONST             4
+
+/* TRANSDATA FLAGS */
+#define TD_SELECTED            1
+#define        TD_NOACTION             2
+
+void Transform(int mode);
+
+void initWrap(TransInfo *t);
+int Wrap(TransInfo *t, short mval[2]);
+
+void initShear(TransInfo *t);
+int Shear(TransInfo *t, short mval[2]);
+
+void initResize(TransInfo *t);
+int Resize(TransInfo *t, short mval[2]);
+
+void initTranslation(TransInfo *t);
+int Translation(TransInfo *t, short mval[2]);
+
+void initToSphere(TransInfo *t);
+int ToSphere(TransInfo *t, short mval[2]);
+
+void initRotation(TransInfo *t);
+int Rotation(TransInfo *t, short mval[2]);
+
+#endif
+
diff --git a/source/blender/src/transform_constraints.c b/source/blender/src/transform_constraints.c
new file mode 100755 (executable)
index 0000000..96dac6c
--- /dev/null
@@ -0,0 +1,421 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_image_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_property_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_constraint_types.h"
+
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_editview.h"
+#include "BIF_resources.h"
+#include "BIF_mywindow.h"
+#include "BIF_gl.h"
+#include "BIF_editlattice.h"
+#include "BIF_editarmature.h"
+#include "BIF_editmesh.h"
+
+#include "BKE_global.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_lattice.h"
+#include "BKE_armature.h"
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+
+#include "BSE_view.h"
+#include "BSE_edit.h"
+
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "BDR_drawobject.h"
+
+#include "blendef.h"
+
+#include "mydevice.h"
+
+#include "transform.h"
+#include "transform_constraints.h"
+#include "transform_generics.h"
+
+extern ListBase editNurb;
+extern ListBase editelems;
+
+void recalcData();
+
+extern TransInfo trans;
+
+/* ************************** CONSTRAINTS ************************* */
+void getConstraintMatrix(TransInfo *t);
+
+void applyAxisConstraintVec(TransInfo *t, TransData *td, float in[3], float out[3])
+{
+       VECCOPY(out, in);
+       if (!td && t->con.mode & APPLYCON) {
+               Mat3MulVecfl(t->con.imtx, out);
+               if (!(out[0] == out[1] == out[2] == 0.0f)) {
+                       if (getConstraintSpaceDimension(t) == 2) {
+                               float vec[3], factor, angle;
+
+                               VecSubf(vec, out, in);
+                               factor = Normalise(vec);
+                               angle = Inpf(vec, G.vd->viewinv[2]);
+
+                               if (angle * angle >= 0.000001f) {
+                                       factor /= angle;
+
+                                       VECCOPY(vec, G.vd->viewinv[2]);
+                                       VecMulf(vec, factor);
+
+                                       VecAddf(out, in, vec);
+                               }
+                       }
+                       else if (getConstraintSpaceDimension(t) == 1) {
+                               float c[3], n[3], vec[3], factor;
+
+                               if (t->con.mode & CONAXIS0) {
+                                       VECCOPY(c, t->con.mtx[0]);
+                               }
+                               else if (t->con.mode & CONAXIS1) {
+                                       VECCOPY(c, t->con.mtx[1]);
+                               }
+                               else if (t->con.mode & CONAXIS2) {
+                                       VECCOPY(c, t->con.mtx[2]);
+                               }
+                               Normalise(c);
+
+                               VECCOPY(n, c);
+                               Mat4MulVecfl(G.vd->viewmat, n);
+                               n[2] = G.vd->viewmat[3][2];
+                               Mat4MulVecfl(G.vd->viewinv, n);
+
+                               if (Inpf(c, G.vd->viewinv[2]) != 1.0f) {
+                                       Projf(vec, in, n);
+                                       factor = Normalise(vec);
+                                       factor /= Inpf(c, vec);
+
+                                       VecMulf(c, factor);
+                                       VECCOPY(out, c);
+
+                               }
+                               else {
+                                       out[0] = out[1] = out[2] = 0.0f;
+                               }
+
+                       }
+               }
+
+               if (t->num.flags & NULLONE && !(t->con.mode & CONAXIS0))
+                       out[0] = 1.0f;
+
+               if (t->num.flags & NULLONE && !(t->con.mode & CONAXIS1))
+                       out[1] = 1.0f;
+
+               if (t->num.flags & NULLONE && !(t->con.mode & CONAXIS2))
+                       out[2] = 1.0f;
+       }
+}
+
+/*
+ * Generic callback for constant spacial constraints applied to rotations
+ * 
+ * The rotation axis is copied into VEC.
+ *
+ * In the case of single axis constraints, the rotation axis is directly the one constrained to.
+ * For planar constraints (2 axis), the rotation axis is the normal of the plane.
+ *
+ * The vector is then modified to always point away from the screen (in global space)
+ * This insures that the rotation is always logically following the mouse.
+ * (ie: not doing counterclockwise rotations when the mouse moves clockwise).
+ */
+void applyAxisConstraintRot(TransInfo *t, TransData *td, float vec[3])
+{
+       if (!td && t->con.mode & APPLYCON) {
+               int mode = t->con.mode & (CONAXIS0|CONAXIS1|CONAXIS2);
+
+               switch(mode) {
+               case CONAXIS0:
+               case (CONAXIS1|CONAXIS2):
+                       VECCOPY(vec, t->con.mtx[0]);
+                       break;
+               case CONAXIS1:
+               case (CONAXIS0|CONAXIS2):
+                       VECCOPY(vec, t->con.mtx[1]);
+                       break;
+               case CONAXIS2:
+               case (CONAXIS0|CONAXIS1):
+                       VECCOPY(vec, t->con.mtx[2]);
+                       break;
+               }
+               if (Inpf(vec, G.vd->viewinv[2]) > 0.0f) {
+                       VecMulf(vec, -1.0f);
+               }
+       }
+}
+
+/*
+ * Returns the dimension of the constraint space.
+ * 
+ * For that reason, the flags always needs to be set to properly evaluate here,
+ * even if they aren't actually used in the callback function. (Which could happen
+ * for weird constraints not yet designed. Along a path for example.)
+ */
+int getConstraintSpaceDimension(TransInfo *t)
+{
+       int n = 0;
+
+       if (t->con.mode & CONAXIS0)
+               n++;
+
+       if (t->con.mode & CONAXIS1)
+               n++;
+
+       if (t->con.mode & CONAXIS2)
+               n++;
+
+       return n;
+}
+
+void setConstraint(TransInfo *t, float space[3][3], int mode) {
+       Mat3CpyMat3(t->con.mtx, space);
+       t->con.mode = mode;
+       getConstraintMatrix(t);
+
+       VECCOPY(t->con.center, t->center);
+       if (G.obedit) {
+               Mat4MulVecfl(G.obedit->obmat, t->con.center);
+       }
+
+       t->con.applyVec = applyAxisConstraintVec;
+       t->con.applyRot = applyAxisConstraintRot;
+       t->redraw = 1;
+}
+
+//void drawConstraint(TransCon *t) {
+void drawConstraint() {
+       int i = -1;
+       TransCon *t = &(trans.con);
+
+       if (t->mode == 0)
+               return;
+
+       if (!(t->mode & APPLYCON)) {
+               i = nearestAxisIndex(&trans);
+       }
+
+       if (t->mode & CONAXIS0) {
+               if (i == 0)
+                       drawLine(t->center, t->mtx[0], 255 - 'x');
+               else
+                       drawLine(t->center, t->mtx[0], 'x');
+       }
+       if (t->mode & CONAXIS1) {
+               if (i == 1)
+                       drawLine(t->center, t->mtx[1], 255 - 'y');
+               else
+                       drawLine(t->center, t->mtx[1], 'y');
+       }
+       if (t->mode & CONAXIS2) {
+               if (i == 2)
+                       drawLine(t->center, t->mtx[2], 255 - 'z');
+               else
+                       drawLine(t->center, t->mtx[2], 'z');
+       }
+
+}
+
+void drawPropCircle()
+//void drawPropCircle(TransInfo *t)
+{
+       TransInfo *t = &trans;
+
+       if (G.f & G_PROPORTIONAL) {
+               float tmat[4][4], imat[4][4];
+
+               BIF_ThemeColor(TH_GRID);
+
+               mygetmatrix(tmat);
+               Mat4Invert(imat, tmat);
+
+               drawcircball(t->center, t->propsize, imat);
+       }
+}
+
+void getConstraintMatrix(TransInfo *t)
+{
+       Mat3Inv(t->con.imtx, t->con.mtx);
+
+       if (!(t->con.mode & CONAXIS0)) {
+               t->con.imtx[0][0]               =
+                       t->con.imtx[0][1]       =
+                       t->con.imtx[0][2]       = 0.0f;
+       }
+
+       if (!(t->con.mode & CONAXIS1)) {
+               t->con.imtx[1][0]               =
+                       t->con.imtx[1][1]       =
+                       t->con.imtx[1][2]       = 0.0f;
+       }
+
+       if (!(t->con.mode & CONAXIS2)) {
+               t->con.imtx[2][0]               =
+                       t->con.imtx[2][1]       =
+                       t->con.imtx[2][2]       = 0.0f;
+       }
+}
+
+void selectConstraint(TransInfo *t)
+{
+       Mat3One(t->con.mtx);
+       Mat3One(t->con.imtx);
+       t->con.mode |= CONAXIS0;
+       t->con.mode |= CONAXIS1;
+       t->con.mode |= CONAXIS2;
+       t->con.mode &= ~APPLYCON;
+       VECCOPY(t->con.center, t->center);
+       if (G.obedit) {
+               Mat4MulVecfl(G.obedit->obmat, t->con.center);
+       }
+}
+
+int nearestAxisIndex(TransInfo *t)
+{
+       short coord[2];
+       float mvec[3], axis[3], center[3], proj[3];
+       float len[3];
+       int i;
+
+       VECCOPY(center, t->center);
+       if (G.obedit) {
+               Mat4MulVecfl(G.obedit->obmat, center);
+       }
+
+       getmouseco_areawin(coord);
+       mvec[0] = (float)(coord[0] - t->center2d[0]);
+       mvec[1] = (float)(coord[1] - t->center2d[1]);
+       mvec[2] = 0.0f;
+
+       for (i = 0; i<3; i++) {
+               VECCOPY(axis, t->con.mtx[i]);
+               VecAddf(axis, axis, center);
+               project_short_noclip(axis, coord);
+               axis[0] = (float)(coord[0] - t->center2d[0]);
+               axis[1] = (float)(coord[1] - t->center2d[1]);
+               axis[2] = 0.0f;
+
+               if (Normalise(axis) != 0.0f) {
+                       Projf(proj, mvec, axis);
+                       VecSubf(axis, mvec, proj);
+                       len[i] = Normalise(axis);
+               }
+               else {
+                       len[i] = 10000000000.0f;
+               }
+       }
+
+       if (len[0] < len[1] && len[0] < len[2]) {
+               return 0;
+       }
+       else if (len[1] < len[0] && len[1] < len[2]) {
+               return 1;
+       }
+       else if (len[2] < len[1] && len[2] < len[0]) {
+               return 2;
+       }
+       return -1;
+}
+
+void chooseConstraint(TransInfo *t)
+{
+       t->con.mode &= ~CONAXIS0;
+       t->con.mode &= ~CONAXIS1;
+       t->con.mode &= ~CONAXIS2;
+
+       switch(nearestAxisIndex(t)) {
+       case 0:
+               t->con.mode |= CONAXIS0;
+               break;
+       case 1:
+               t->con.mode |= CONAXIS1;
+               break;
+       case 2:
+               t->con.mode |= CONAXIS2;
+               break;
+       }
+
+       t->con.mode |= APPLYCON;
+       VECCOPY(t->con.center, t->center);
+
+       getConstraintMatrix(t);
+       t->con.applyVec = applyAxisConstraintVec;
+       t->con.applyRot = applyAxisConstraintRot;
+       t->redraw = 1;
+}
diff --git a/source/blender/src/transform_constraints.h b/source/blender/src/transform_constraints.h
new file mode 100755 (executable)
index 0000000..6577aa2
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef TRANSFORM_CONSTRAINTS_H
+#define TRANSFORM_CONSTRAINTS_H
+
+#include "transform.h"
+
+void getConstraintMatrix(TransInfo *t);
+void setConstraint(TransInfo *t, float space[3][3], int mode);
+
+//void drawConstraint(TransCon *t);
+void drawConstraint();
+
+//void drawPropCircle(TransInfo *t);
+void drawPropCircle();
+
+void getConstraintMatrix(TransInfo *t);
+
+void selectConstraint(TransInfo *t);
+
+void chooseConstraint(TransInfo *t);
+
+int getConstraintSpaceDimension(TransInfo *t);
+
+int nearestAxisIndex(TransInfo *t);
+
+#endif
+
diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c
new file mode 100755 (executable)
index 0000000..b020f5f
--- /dev/null
@@ -0,0 +1,499 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_effect_types.h"
+#include "DNA_ika_types.h"
+#include "DNA_image_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_property_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_constraint_types.h"
+
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "BIF_editview.h"
+#include "BIF_resources.h"
+#include "BIF_mywindow.h"
+#include "BIF_gl.h"
+#include "BIF_editlattice.h"
+#include "BIF_editarmature.h"
+#include "BIF_editmesh.h"
+
+#include "BKE_global.h"
+#include "BKE_object.h"
+#include "BKE_utildefines.h"
+#include "BKE_lattice.h"
+#include "BKE_armature.h"
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+
+#include "BSE_view.h"
+#include "BSE_edit.h"
+
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "blendef.h"
+
+#include "mydevice.h"
+
+#include "transform.h"
+#include "transform_generics.h"
+
+extern ListBase editNurb;
+extern ListBase editelems;
+
+/* GLOBAL VARIABLE THAT SHOULD MOVED TO SCREEN MEMBER OR SOMETHING  */
+extern TransInfo trans;
+
+/* ************************** Functions *************************** */
+
+/* ************************** GENERICS **************************** */
+
+void recalcData(TransInfo *t)
+{
+       if (G.obedit) {
+               if (G.obedit->type == OB_MESH) {
+                       recalc_editnormals();
+                       makeDispList(G.obedit);
+               }
+               else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
+                       Nurb *nu= editNurb.first;
+                       while(nu) {
+                               test2DNurb(nu);
+                               testhandlesNurb(nu); /* test for bezier too */
+                               nu= nu->next;
+                       }
+                       makeDispList(G.obedit);
+
+                       makeBevelList(G.obedit); // might be needed for deform
+                       calc_curvepath(G.obedit);
+               }
+               else if (G.obedit->type == OB_MBALL) {
+               makeDispList(G.obedit); 
+               }       
+       }
+       else {
+               TransData *tob;
+               int i;
+               tob = t->data;
+               for (i = 0; i < t->total; i++, tob++) {
+                       if (tob->ob->type == OB_MBALL) {
+                       makeDispList(tob->ob);  
+                       }       
+               }
+       }
+}
+
+void initTransModeFlags(TransInfo *t, int mode) {
+       t->flags = 0;
+       t->num.flags = 0;
+       switch (mode) {
+       case TRANSLATION:
+               break;
+       case ROTATION:
+               break;
+       case RESIZE:
+               t->num.flags |= NULLONE;
+               if (!G.obedit) {
+                       t->flags |= NOZERO;
+                       t->num.flags |= NOZERO;
+               }
+               break;
+       case TOSPHERE:
+               t->num.flags |= NULLONE;
+               t->num.flags |= NONEGATIVE;
+               t->flags |= NOCONSTRAINT;
+               break;
+       case SHEAR:
+               t->flags |= NOCONSTRAINT;
+               break;
+       }
+}
+
+void drawLine(float *center, float *dir, char axis)
+{
+       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);
+
+       if (axis > 127) {
+               axis = -1 * (axis - 255);
+               col[0] = col[1] = col[2] = 200;
+       }
+       else {
+               BIF_GetThemeColor3ubv(TH_GRID, col);
+       }
+       make_axis_color(col, col2, axis);
+       glColor3ubv(col2);
+
+       setlinestyle(0);
+       glBegin(GL_LINE_STRIP); 
+               glVertex3fv(v1); 
+               glVertex3fv(v2); 
+       glEnd();
+       
+       myloadmatrix(G.vd->viewmat);
+}
+
+void postTrans (TransInfo *t) {
+       MEM_freeN(t->data);
+       t->data = NULL;
+
+       G.moving = 0; // Set moving flag off (display as usual)
+
+       scrarea_do_windraw(curarea);
+       screen_swapbuffers();
+
+}
+
+void apply_grid3(float *val, int max_index, float fac1, float fac2, float fac3)
+{
+       /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */
+       int invert = U.flag & USER_AUTOGRABGRID;
+       int ctrl;
+       int i;
+
+       for (i=0; i<=max_index; i++) {
+
+               if(invert) {
+                       if(G.qual & LR_CTRLKEY) ctrl= 0;
+                       else ctrl= 1;
+               }
+               else ctrl= (G.qual & LR_CTRLKEY);
+
+               if(ctrl && (G.qual & LR_SHIFTKEY)) {
+                       if(fac3!= 0.0) {
+                               for (i=0; i<=max_index; i++) {
+                                       val[i]= fac3*(float)floor(val[i]/fac3 +.5);
+                               }
+                       }
+               }
+               else if(ctrl) {
+                       if(fac2!= 0.0) {
+                               for (i=0; i<=max_index; i++) {
+                                       val[i]= fac2*(float)floor(val[i]/fac2 +.5);
+                               }
+                       }
+               }
+               else {
+                       if(fac1!= 0.0) {
+                               for (i=0; i<=max_index; i++) {
+                                       val[i]= fac1*(float)floor(val[i]/fac1 +.5);
+                               }
+                       }
+               }
+       }
+}
+
+void apply_grid1(float *val, int max_index, float factor)
+{
+       /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */
+       float fac1 = 0.0;
+       float fac2 = G.vd->grid * factor;
+       float fac3 = 0.1f * fac2;
+       apply_grid3(val, max_index, fac1, fac2, fac3);
+}
+
+void apply_grid2(float *val, int max_index, float factor, float factor2)
+{
+       /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */
+       float fac1 = 0.0;
+       float fac2 = G.vd->grid * factor;
+       float fac3 = factor2 * fac2;
+       apply_grid3(val, max_index, fac1, fac2, fac3);
+}
+
+void applyTransObjects(TransInfo *t)
+{
+    TransData *tob;
+       for (tob = t->data; tob < t->data + t->total; tob++) {
+        VECCOPY(tob->iloc, tob->loc);
+               if (tob->rot) {
+                       VECCOPY(tob->irot, tob->rot);
+               }
+               if (tob->size) {
+                       VECCOPY(tob->isize, tob->size);
+               }
+    }    
+       recalcData(t);
+} 
+
+void restoreTransObjects(TransInfo *t)
+{
+    TransData *tob;
+       for (tob = t->data; tob < t->data + t->total; tob++) {
+        VECCOPY(tob->loc, tob->iloc);
+               if (tob->rot) {
+                       VECCOPY(tob->rot, tob->irot);
+               }
+               if (tob->size) {
+                       VECCOPY(tob->size, tob->isize);
+               }
+    }    
+       recalcData(t);
+} 
+
+void initTrans (TransInfo *t)
+{
+
+       G.moving = 1; // Set moving flag on (display object in white)
+
+       t->data = NULL;
+
+       getmouseco_areawin(t->imval);
+
+       t->transform            = NULL;
+       t->con.applyVec         = NULL;
+       t->con.applyRot = NULL;
+       t->mode                         =
+               t->con.mode             =
+               t->total                        =
+               t->num.idx              =
+               t->num.idx_max  =
+               t->num.ctrl[0]  = 
+               t->num.ctrl[1]  = 
+               t->num.ctrl[2]  = 0;
+
+       t->val = 0.0f;
+
+       t->num.val[0]           = 
+               t->num.val[1]   = 
+               t->num.val[2]   = 0.0f;
+}
+
+void calculateCenterCursor(TransInfo *t)
+{
+       float *cursor;
+
+       cursor = give_cursor();
+       VECCOPY(t->center, cursor);
+
+       if(G.obedit) {
+               float mat[3][3], imat[3][3];
+               VecSubf(t->center, t->center, G.obedit->obmat[3]);
+               Mat3CpyMat4(mat, G.obedit->obmat);
+               Mat3Inv(imat, mat);
+               Mat3MulVecfl(imat, t->center);
+       }
+
+       if (G.obedit) {
+               float vec[3];
+               VECCOPY(vec, t->center);
+               Mat4MulVecfl(G.obedit->obmat, vec);
+               project_short_noclip(vec, t->center2d);
+       }
+       else {
+               project_short_noclip(t->center, t->center2d);
+       }
+}
+
+void calculateCenterMedian(TransInfo *t)
+{
+       float partial[3] = {0.0f, 0.0f, 0.0f};
+       int i;
+       for(i = 0; i < t->total; i++) {
+               if (t->data[i].flag & TD_SELECTED) {
+                       VecAddf(partial, partial, t->data[i].center);
+               }
+       }
+       VecMulf(partial, 1.0f / t->total);
+       VECCOPY(t->center, partial);
+
+       if (G.obedit) {
+               float vec[3];
+               VECCOPY(vec, t->center);
+               Mat4MulVecfl(G.obedit->obmat, vec);
+               project_short_noclip(vec, t->center2d);
+       }
+       else {
+               project_short_noclip(t->center, t->center2d);
+       }
+}
+
+void calculateCenterBound(TransInfo *t)
+{
+       float max[3];
+       float min[3];
+       int i;
+       for(i = 0; i < t->total; i++) {
+               if (i) {
+                       if (t->data[i].flag & TD_SELECTED) {
+                               MinMax3(min, max, t->data[i].center);
+                       }
+               }
+               else {
+                       VECCOPY(max, t->data[i].center);
+                       VECCOPY(min, t->data[i].center);
+               }
+       }
+       VecAddf(t->center, min, max);
+       VecMulf(t->center, 0.5);
+
+       if (G.obedit) {
+               float vec[3];
+               VECCOPY(vec, t->center);
+               Mat4MulVecfl(G.obedit->obmat, vec);
+               project_short_noclip(vec, t->center2d);
+       }
+       else {
+               project_short_noclip(t->center, t->center2d);
+       }
+}
+
+void calculateCenter(TransInfo *t) {
+       switch(G.vd->around) {
+       case V3D_CENTRE:
+               calculateCenterBound(t);
+               break;
+       case V3D_CENTROID:
+               calculateCenterMedian(t);
+               break;
+       case V3D_CURSOR:
+               calculateCenterCursor(t);
+               break;
+       case V3D_LOCAL:
+               // NEED TO REPLACE THIS
+               calculateCenterMedian(t);
+               printf("local\n");
+               break;
+       }
+       initgrabz(t->center[0], t->center[1], t->center[2]);
+}
+
+void calculatePropRatio(TransInfo *t)
+{
+       TransData *td = t->data;
+       int i;
+       float dist;
+       extern int prop_mode;
+
+       if (G.f & G_PROPORTIONAL) {
+               for(i = 0 ; i < t->total; i++, td++) {
+                       if (td->dist == 0.0f) {
+                               td->factor = 1.0f;
+                       }
+                       else if (td->dist > t->propsize) {
+                               td->factor = 0.0f;
+                       }
+                       else {
+                               dist= (t->propsize-td->dist)/t->propsize;
+                               switch(prop_mode) {
+                               case PROP_SHARP:
+                                       td->factor= dist*dist;
+                                       break;
+                               case PROP_SMOOTH:
+                                       td->factor= 3.0f*dist*dist - 2.0f*dist*dist*dist;
+                                       break;
+                               case PROP_ROOT:
+                                       td->factor = (float)sqrt(dist);
+                                       break;
+                               case PROP_LIN:
+                                       td->factor = dist;
+                                       break;
+                               case PROP_CONST:
+                                       td->factor = 1;
+                                       break;
+                               default:
+                                       td->factor = 1;
+                               }
+                       }
+               }
+               switch(prop_mode) {
+               case PROP_SHARP:
+                       strcpy(t->proptext, "(Quad)");
+                       break;
+               case PROP_SMOOTH:
+                       strcpy(t->proptext, "(Smooth)");
+                       break;
+               case PROP_ROOT:
+                       strcpy(t->proptext, "(Root)");
+                       break;
+               case PROP_LIN:
+                       strcpy(t->proptext, "(Linear)");
+                       break;
+               case PROP_CONST:
+                       strcpy(t->proptext, "(Constant)");
+                       break;
+               default:
+                       strcpy(t->proptext, "");
+               }
+       }
+       else {
+               for(i = 0 ; i < t->total; i++, td++) {
+                       td->factor = 1.0;
+               }
+               strcpy(t->proptext, "");
+       }
+}
\ No newline at end of file
diff --git a/source/blender/src/transform_generics.h b/source/blender/src/transform_generics.h
new file mode 100755 (executable)
index 0000000..44a03ad
--- /dev/null
@@ -0,0 +1,63 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef TRANSFORM_GENERICS_H
+#define TRANSFORM_GENERICS_H
+
+void recalcData(TransInfo *t);
+
+void initTransModeFlags(TransInfo *t, int mode);
+
+void drawLine(float *center, float *dir, char axis);
+
+void postTrans (TransInfo *t);
+
+void apply_grid1(float *val, int max_index, float factor);
+void apply_grid2(float *val, int max_index, float factor, float factor2);
+void apply_grid3(float *val, int max_index, float fac1, float fac2, float fac3);
+
+void applyTransObjects(TransInfo *t);
+void restoreTransObjects(TransInfo *t);
+
+void initTrans(TransInfo *t);
+
+void calculateCenterBound(TransInfo *t);
+void calculateCenterMedian(TransInfo *t);
+void calculateCenterCursor(TransInfo *t);
+
+void calculateCenter(TransInfo *t);
+
+void calculatePropRatio(TransInfo *t);
+
+
+#endif
+
diff --git a/source/blender/src/transform_numinput.c b/source/blender/src/transform_numinput.c
new file mode 100755 (executable)
index 0000000..7293d93
--- /dev/null
@@ -0,0 +1,238 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "blendef.h"
+
+#include "mydevice.h"
+
+#include "BLI_arithb.h"
+
+#include "transform_numinput.h"
+#include "transform.h"
+
+/* ************************** Functions *************************** */
+
+/* ************************** NUMINPUT **************************** */
+
+void outputNumInput(NumInput *n, char *str)
+{
+       char Cur;
+       short i;
+
+       for (i=0; i<=n->idx_max; i++) {
+
+               if (n->idx != i)
+                       Cur = ' ';
+               else
+                       Cur = '|';
+
+               switch (n->ctrl[i]) {
+               case 0:
+                       sprintf(&str[i*20], "NONE%c", Cur);
+                       break;
+               case 1:
+               case -1:
+                       sprintf(&str[i*20], "%.0f%c", n->val[i], Cur);
+                       break;
+               case 10:
+               case -10:
+                       sprintf(&str[i*20], "%.f.%c", n->val[i], Cur);
+                       break;
+               case 100:
+               case -100:
+                       sprintf(&str[i*20], "%.1f%c", n->val[i], Cur);
+                       break;
+               case 1000:
+               case -1000:
+                       sprintf(&str[i*20], "%.2f%c", n->val[i], Cur);
+               case 10000:
+               case -10000:
+                       sprintf(&str[i*20], "%.3f%c", n->val[i], Cur);
+                       break;
+               default:
+                       sprintf(&str[i*20], "%.4f%c", n->val[i], Cur);
+               }
+       }
+}
+
+short hasNumInput(NumInput *n)
+{
+       short doit = 0;
+       short i;
+
+       for (i=0; i<=n->idx_max; i++) {
+               if (n->ctrl[i])
+                       doit = 1;
+       }
+
+       return doit;
+}
+
+void applyNumInput(NumInput *n, float *vec)
+{
+       short i;
+
+       if (hasNumInput(n)) {
+               for (i=0; i<=n->idx_max; i++) {
+                       if (n->ctrl[i] == 0 && n->flags & NULLONE) {
+                               vec[i] = 1.0f;
+                       }
+                       else if (n->val[i] == 0.0f && n->flags & NOZERO) {
+                               vec[i] = 0.0001f;
+                       }
+                       else {
+                               vec[i] = n->val[i];
+                       }
+               }
+       }
+}
+
+char handleNumInput(NumInput *n, unsigned short event)
+{
+       float Val = 0;
+       short idx = n->idx, idx_max = n->idx_max;
+
+       switch (event) {
+       case BACKSPACEKEY:
+               if (n->ctrl[idx] == 0) {
+                       n->val[0]               = 
+                               n->val[1]       = 
+                               n->val[2]       = 0.0f;
+                       n->ctrl[0]              = 
+                               n->ctrl[1]      = 
+                               n->ctrl[2]      = 0;
+               }
+               else {
+                       n->val[idx] = 0.0f;
+                       n->ctrl[idx] = 0;
+               }
+               break;
+       case PERIODKEY:
+       case PADPERIOD:
+               if (n->flags & NOFRACTION)
+                       break;
+
+               switch (n->ctrl[idx])
+               {
+               case 0:
+               case 1:
+                       n->ctrl[idx] = 10;
+                       break;
+               case -1:
+                       n->ctrl[idx] = -10;
+               }
+               break;
+       case MINUSKEY:
+               if (n->flags & NONEGATIVE)
+                       break;
+
+               if (n->ctrl[idx]) {
+                       n->ctrl[idx] *= -1;
+                       n->val[idx] *= -1;
+               }
+               else
+                       n->ctrl[idx] = -1;
+               break;
+       case TABKEY:
+               idx++;
+               if (idx > idx_max)
+                       idx = 0;
+               n->idx = idx;
+               break;
+       case PAD9:
+       case NINEKEY:
+               Val += 1.0f;
+       case PAD8:
+       case EIGHTKEY:
+               Val += 1.0f;
+       case PAD7:
+       case SEVENKEY:
+               Val += 1.0f;
+       case PAD6:
+       case SIXKEY:
+               Val += 1.0f;
+       case PAD5:
+       case FIVEKEY:
+               Val += 1.0f;
+       case PAD4:
+       case FOURKEY:
+               Val += 1.0f;
+       case PAD3:
+       case THREEKEY:
+               Val += 1.0f;
+       case PAD2:
+       case TWOKEY:
+               Val += 1.0f;
+       case PAD1:
+       case ONEKEY:
+               Val += 1.0f;
+       case PAD0:
+       case ZEROKEY:
+               if (!n->ctrl[idx])
+                       n->ctrl[idx] = 1;
+
+               if (n->ctrl[idx] == 1) {
+                       n->val[idx] *= 10;
+                       n->val[idx] += Val;
+               }
+               else if (n->ctrl[idx] == -1) {
+                       n->val[idx] *= 10;
+                       n->val[idx] -= Val;
+               }
+               else {
+                       n->val[idx] += Val / (float)n->ctrl[idx];
+                       n->ctrl[idx] *= 10;
+               }
+               break;
+       default:
+               return 0;
+       }
+       /* REDRAW SINCE NUMBERS HAVE CHANGED */
+       return 1;
+}
diff --git a/source/blender/src/transform_numinput.h b/source/blender/src/transform_numinput.h
new file mode 100755 (executable)
index 0000000..61e99dd
--- /dev/null
@@ -0,0 +1,62 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef TRANSFORM_NUMINPUT_H
+#define TRANSFORM_NUMINPUT_H
+
+typedef struct NumInput {
+    short  idx;
+    short  idx_max;
+    short  flags;        /* Different flags to indicate different behaviors                                */
+    float  val[3];       /* Direct value of the input                                                      */
+    short  ctrl[3];      /* Control to indicate what to do with the numbers that are typed                 */
+} NumInput ;
+
+/*
+       The ctrl value has different meaning:
+               0                       : No value has been typed
+               
+               otherwise, |value| - 1 is where the cursor is located after the period
+               Positive        : number is positive
+               Negative        : number is negative
+*/
+
+void outputNumInput(NumInput *n, char *str);
+
+short hasNumInput(NumInput *n);
+
+void applyNumInput(NumInput *n, float *vec);
+
+char handleNumInput(NumInput *n, unsigned short event);
+
+#endif
+