From d2f4ba4549d30e9c10ee8e6b9a051c1bb08d9881 Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Mon, 14 Feb 2005 02:53:36 +0000 Subject: [PATCH] Initial new transform commit. 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. --- source/blender/src/SConscript | 5 + source/blender/src/drawview.c | 10 +- source/blender/src/editobject.c | 31 +- source/blender/src/space.c | 88 +- source/blender/src/transform.c | 1375 ++++++++++++++++++++ source/blender/src/transform.h | 147 +++ source/blender/src/transform_constraints.c | 421 ++++++ source/blender/src/transform_constraints.h | 58 + source/blender/src/transform_generics.c | 499 +++++++ source/blender/src/transform_generics.h | 63 + source/blender/src/transform_numinput.c | 238 ++++ source/blender/src/transform_numinput.h | 62 + 12 files changed, 2963 insertions(+), 34 deletions(-) create mode 100755 source/blender/src/transform.c create mode 100755 source/blender/src/transform.h create mode 100755 source/blender/src/transform_constraints.c create mode 100755 source/blender/src/transform_constraints.h create mode 100755 source/blender/src/transform_generics.c create mode 100755 source/blender/src/transform_generics.h create mode 100755 source/blender/src/transform_numinput.c create mode 100755 source/blender/src/transform_numinput.h diff --git a/source/blender/src/SConscript b/source/blender/src/SConscript index 35b992ce7b1..22192a63e85 100644 --- a/source/blender/src/SConscript +++ b/source/blender/src/SConscript @@ -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', diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 70464cef034..51a0c659843 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -126,6 +126,8 @@ #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; diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 65d2a4b38d7..3f89e340d3a 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -160,6 +160,8 @@ #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]; - BIF_ThemeColor(TH_GRID); + if(G.moving) { - mygetmatrix(tmat); - Mat4Invert(imat, tmat); + BIF_ThemeColor(TH_GRID); - drawcircball(prop_cent, prop_size, imat); + mygetmatrix(tmat); + Mat4Invert(imat, tmat); + + 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"); } diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 48f03b584d6..50714cb8af2 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -145,6 +145,8 @@ #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 index 00000000000..995a52a4985 --- /dev/null +++ b/source/blender/src/transform.c @@ -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 +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifndef WIN32 +#include +#else +#include +#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 index 00000000000..9854471dcd9 --- /dev/null +++ b/source/blender/src/transform.h @@ -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 index 00000000000..96dac6c6bae --- /dev/null +++ b/source/blender/src/transform_constraints.c @@ -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 +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifndef WIN32 +#include +#else +#include +#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 index 00000000000..6577aa25b66 --- /dev/null +++ b/source/blender/src/transform_constraints.h @@ -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 index 00000000000..b020f5f8728 --- /dev/null +++ b/source/blender/src/transform_generics.c @@ -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 +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifndef WIN32 +#include +#else +#include +#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 index 00000000000..44a03ad0a0a --- /dev/null +++ b/source/blender/src/transform_generics.h @@ -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 index 00000000000..7293d935bb5 --- /dev/null +++ b/source/blender/src/transform_numinput.c @@ -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 +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifndef WIN32 +#include +#else +#include +#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 index 00000000000..61e99dd3ac2 --- /dev/null +++ b/source/blender/src/transform_numinput.h @@ -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 +