Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/src/edit.c')
-rw-r--r--source/blender/src/edit.c830
1 files changed, 830 insertions, 0 deletions
diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c
new file mode 100644
index 00000000000..a811f7fd7c3
--- /dev/null
+++ b/source/blender/src/edit.c
@@ -0,0 +1,830 @@
+/**
+ * $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 <math.h>
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#include "BLI_winstuff.h"
+#endif
+#include "MEM_guardedalloc.h"
+
+#include "BMF_Api.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_editVert.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_anim.h"
+#include "BKE_object.h"
+#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_lattice.h"
+#include "BKE_mesh.h"
+
+#include "BIF_gl.h"
+#include "BIF_mywindow.h"
+#include "BIF_screen.h"
+#include "BIF_interface.h"
+#include "BIF_space.h"
+#include "BIF_editview.h"
+#include "BIF_glutil.h"
+
+#include "BSE_view.h"
+#include "BSE_edit.h"
+#include "BSE_trans_types.h"
+#include "BSE_drawipo.h"
+
+#include "BDR_editobject.h"
+
+/* old stuff */
+#include "blendertimer.h"
+#include "blendef.h"
+#include "interface.h"
+#include "mydevice.h"
+/*#include "armature.h"*/
+/* #include "edit.h" */
+#include "nla.h"
+
+#ifdef __NLA
+#include "BIF_editarmature.h"
+#endif
+
+/* editmball.c */
+extern ListBase editelems; /* go away ! */
+
+
+/* from editobject */
+extern void make_trans_verts(float *min, float *max, int mode);
+
+/* circle selection callback */
+typedef void (*select_CBfunc)(short selecting, Object *editobj, short *mval, float rad);
+
+extern void obedit_selectionCB(short selecting, Object *editobj,
+ short *mval, float rad);
+extern void uvedit_selectionCB(short selecting, Object *editobj,
+ short *mval, float rad);
+
+void circle_selectCB(select_CBfunc func);
+
+int get_border(rcti *rect, short col)
+{
+ float dvec[4], fac1, fac2;
+ int retval=1;
+ unsigned short event;
+ short mval[2], mvalo[4], val, x1, y1;
+ char str[64];
+
+ mywinset(G.curscreen->mainwin);
+
+ /* pietsje groter, 1 pixel aan de rand */
+ glReadBuffer(GL_FRONT);
+ glDrawBuffer(GL_FRONT);
+
+ /* removed my_get_frontbuffer, this crashes when it gets a part outside the screen */
+ /* solved it with just a redraw! */
+
+ mywinset(curarea->win);
+
+ glDrawBuffer(GL_FRONT);
+ persp(0);
+ initgrabz(0.0, 0.0, 0.0);
+
+ getmouseco_areawin(mvalo);
+
+ /* draws the selection initial cross */
+ sdrawXORline4(0, 0, mvalo[1], curarea->winx, mvalo[1]);
+ sdrawXORline4(1, mvalo[0], 0, mvalo[0], curarea->winy);
+
+ while(TRUE) {
+
+ /* als een renderwindow open is en de muis gaat erin */
+ persp(1);
+ mywinset(curarea->win);
+ persp(0);
+
+ /* selection loop while mouse pressed */
+ getmouseco_areawin(mval);
+
+ if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
+
+ /* aiming cross */
+ sdrawXORline4(0, 0, mval[1], curarea->winx, mval[1]);
+ sdrawXORline4(1, mval[0], 0, mval[0], curarea->winy);
+ glFlush();
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+ }
+ event= extern_qread(&val);
+
+ if(event && val) {
+ if(event==ESCKEY) {
+ retval= 0;
+ break;
+ }
+ else if(event==BKEY) {
+ /* b has been pressed twice: proceed with circle select */
+ retval= 0;
+ break;
+ }
+ else if(event==LEFTMOUSE) break;
+ else if(event==MIDDLEMOUSE) break;
+ else if(event==RIGHTMOUSE) break;
+ }
+ } /* end while (TRUE) */
+
+ /* erase XORed lines */
+ sdrawXORline4(-1, 0, 0, 0, 0);
+
+ if(retval) {
+ /* box select */
+ x1= mval[0];
+ y1= mval[1];
+
+ getmouseco_areawin(mvalo);
+
+ sdrawXORline4(0, x1, y1, x1, mvalo[1]);
+ sdrawXORline4(1, x1, mvalo[1], mvalo[0], mvalo[1]);
+ sdrawXORline4(2, mvalo[0], mvalo[1], mvalo[0], y1);
+ sdrawXORline4(3, mvalo[0], y1, x1, y1);
+ glFlush();
+
+ while(TRUE) {
+ getmouseco_areawin(mval);
+ if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
+
+ sdrawXORline4(0, x1, y1, x1, mval[1]);
+ sdrawXORline4(1, x1, mval[1], mval[0], mval[1]);
+ sdrawXORline4(2, mval[0], mval[1], mval[0], y1);
+ sdrawXORline4(3, mval[0], y1, x1, y1);
+ glFlush();
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+ }
+
+ event= extern_qread(&val);
+
+ /* still because of the renderwindow... */
+ persp(1);
+ mywinset(curarea->win);
+ persp(0);
+
+ if(val==0) {
+ if(event==ESCKEY) {
+ retval= 0;
+ break;
+ }
+ else if(event==LEFTMOUSE) break;
+ else if(event==MIDDLEMOUSE) break;
+ else if(event==RIGHTMOUSE) break;
+ }
+
+ if(curarea->spacetype==SPACE_VIEW3D) {
+ glColor3f(0.4375, 0.4375, 0.4375);
+ glRecti(0, 10, 250, 20);
+ glColor3f(0.0, 0.0, 0.0);
+
+ if(G.vd->persp==0) {
+ window_to_3d(dvec, mvalo[0]-x1, mvalo[1]-y1);
+
+ glRasterPos2i(10, 10);
+ sprintf(str, "X %.4f Y %.4f Z %.4f Dia %.4f", dvec[0], dvec[1], dvec[2], sqrt(dvec[0]*dvec[0]+dvec[1]*dvec[1]+dvec[2]*dvec[2]));
+ BMF_DrawString(G.fonts, str);
+ }
+ else if(G.vd->persp==2) {
+ rcti vb;
+
+ calc_viewborder(G.vd, &vb);
+
+ fac1= (mvalo[0]-x1)/( (float) (vb.xmax-vb.xmin) );
+ fac1*= 0.01*G.scene->r.size*G.scene->r.xsch;
+
+ fac2= (mvalo[1]-y1)/( (float) (vb.ymax-vb.ymin) );
+ fac2*= 0.01*G.scene->r.size*G.scene->r.ysch;
+
+ glRasterPos2i(10, 10);
+ sprintf(str, "X %.1f Y %.1f Dia %.1f", fabs(fac1), fabs(fac2), sqrt(fac1*fac1 + fac2*fac2) );
+ BMF_DrawString(G.fonts, str);
+ }
+ }
+ else if(curarea->spacetype==SPACE_IPO) {
+ SpaceIpo *sipo= curarea->spacedata.first;
+
+ glColor3f(.40625, .40625, .40625);
+ glRecti(20, 30, 170, 40);
+ glColor3f(0.0, 0.0, 0.0);
+
+ mvalo[2]= x1;
+ mvalo[3]= y1;
+ areamouseco_to_ipoco(&sipo->v2d, mval, dvec, dvec+1);
+ areamouseco_to_ipoco(&sipo->v2d, mvalo+2, dvec+2, dvec+3);
+
+ glRasterPos2i(30, 30);
+ sprintf(str, "Time: %.4f Y %.4f", dvec[0]-dvec[2], dvec[1]-dvec[3]);
+ BMF_DrawString(G.fonts, str);
+ }
+ } /* end while (TRUE) */
+ sdrawXORline4(-1, 0, 0, 0, 0);
+
+ if(retval) {
+ rect->xmin= x1;
+ rect->ymin= y1;
+ rect->xmax= mval[0];
+ rect->ymax= mval[1];
+ retval= event;
+
+ /* normaliseren */
+ if(rect->xmin>rect->xmax) SWAP(int, rect->xmin, rect->xmax);
+ if(rect->ymin>rect->ymax) SWAP(int, rect->ymin, rect->ymax);
+
+ if(rect->xmin==rect->xmax) retval= 0;
+ if(rect->ymin==rect->ymax) retval= 0;
+ }
+ }
+
+
+ /* wissen */
+ if(event!=BKEY) {
+ if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_IPO) {
+ scrarea_queue_winredraw(curarea);
+ }
+ }
+
+ glFlush();
+ glReadBuffer(GL_BACK);
+ glDrawBuffer(GL_BACK);
+
+ persp(1);
+
+ /* pressed B again ? -> brush select */
+ if(event==BKEY) {
+ switch (curarea->spacetype) {
+ case SPACE_VIEW3D:
+ if (G.obedit)
+ circle_selectCB(&obedit_selectionCB);
+ return 0;
+ case SPACE_IMAGE: // brush select in UV editor
+ circle_selectCB(&uvedit_selectionCB);
+ // this is a hack; we return 0 that the caller from get_border
+ // doesn't execute the selection code for border select..
+ return 0;
+ }
+ }
+ return retval;
+}
+
+void draw_sel_circle(short *mval, short *mvalo, float rad, float rado, int selecting)
+{
+ static short no_mvalo=0;
+
+ if(mval==0 && mvalo==0) { /* signal */
+ no_mvalo= 1;
+ return;
+ }
+
+ persp(0);
+ glDrawBuffer(GL_FRONT);
+
+ /* cirkel tekenen */
+
+ if(mvalo && no_mvalo==0) {
+ sdrawXORcirc(mvalo[0], mvalo[1], rado);
+ }
+
+ if(mval) {
+ sdrawXORcirc(mval[0], mval[1], rad);
+ }
+
+ glFlush();
+ persp(1);
+ glDrawBuffer(GL_BACK);
+
+ no_mvalo= 0;
+}
+
+/** This function does the same as editview.c:circle_select(),
+ * but the selection actions are defined by a callback, making
+ * it (hopefully) reusable for other windows than the 3D view.
+ */
+
+void circle_selectCB(select_CBfunc callback)
+{
+ static float rad= 40.0;
+ float rado;
+ int firsttime=1;
+ unsigned short event;
+ short mvalo[2], mval[2], val;
+ short selecting=0;
+ Object *obj;
+
+ if(G.obedit) obj = G.obedit;
+ else obj = OBACT;
+
+
+ getmouseco_areawin(mvalo);
+ draw_sel_circle(mvalo, 0, rad, 0.0, selecting);
+
+ rado= rad;
+
+ while(TRUE) {
+
+ /* als een renderwindow open is en de muis gaat erin */
+
+ mywinset(curarea->win);
+
+ getmouseco_areawin(mval);
+
+ if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || rado!=rad || firsttime) {
+ firsttime= 0;
+
+ draw_sel_circle(mval, mvalo, rad, rado, selecting);
+
+ mvalo[0]= mval[0];
+ mvalo[1]= mval[1];
+ rado= rad;
+
+ if(selecting) {
+ callback(selecting, obj, mval, rad);
+ }
+ }
+ event= extern_qread(&val);
+ if (event) {
+ int afbreek= 0;
+
+ switch(event) {
+ case LEFTMOUSE:
+ case MIDDLEMOUSE:
+ if(val) selecting= event;
+ else selecting= 0;
+ firsttime= 1;
+
+ break;
+ case PADPLUSKEY:
+ if(val) if(rad<200.0) rad*= 1.2;
+ break;
+ case PADMINUS:
+ if(val) if(rad>5.0) rad/= 1.2;
+ break;
+
+ case ESCKEY: case SPACEKEY: case RIGHTMOUSE:
+ case GKEY: case SKEY: case RKEY: case XKEY: case EKEY: case TABKEY:
+ afbreek= 1;
+ break;
+
+ }
+
+ if(afbreek) break;
+ }
+ }
+
+ /* cirkel wissen */
+ draw_sel_circle(0, mvalo, 0, rad, 1);
+
+ countall();
+ allqueue(REDRAWINFO, 0);
+}
+
+void count_object(Object *ob, int sel)
+{
+ Mesh *me;
+ Curve *cu;
+ int tot=0, totf=0;
+
+ switch(ob->type) {
+ case OB_MESH:
+ G.totmesh++;
+ me= get_mesh(ob);
+ if(me) {
+ G.totvert+= me->totvert;
+ G.totface+= me->totface;
+ if(sel) {
+ G.totvertsel+= me->totvert;
+ G.totfacesel+= me->totface;
+ }
+ }
+ break;
+
+ case OB_LAMP:
+ G.totlamp++;
+ break;
+ case OB_SURF:
+ case OB_CURVE:
+ case OB_FONT:
+ G.totcurve++;
+ tot=totf= 0;
+ cu= ob->data;
+ if(cu->disp.first==0) makeDispList(ob);
+ count_displist( &cu->disp, &tot, &totf);
+ G.totvert+= tot;
+ G.totface+= totf;
+ if(sel) {
+ G.totvertsel+= tot;
+ G.totfacesel+= totf;
+ }
+ break;
+ case OB_MBALL:
+ count_displist( &ob->disp, &tot, &totf);
+ G.totvert+= tot;
+ G.totface+= totf;
+ if(sel) {
+ G.totvertsel+= tot;
+ G.totfacesel+= totf;
+ }
+
+ break;
+ }
+
+}
+
+void countall()
+{
+/* extern Lattice *editLatt; in BKE_lattice.h*/
+ extern ListBase editNurb;
+ /* extern ListBase bpbase; */
+ Base *base;
+ Object *ob;
+ Mesh *me;
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ MetaElem *ml;
+ /* struct BodyPoint *bop; */
+ struct EditVert *eve;
+ struct EditVlak *evl;
+#ifdef __NLA
+ struct EditBone *ebo;
+#endif
+ int a;
+
+ G.totvert= G.totvertsel= G.totfacesel= G.totface= G.totobj=
+ G.totmesh= G.totlamp= G.totcurve= G.totobjsel= 0;
+
+ if(G.obedit) {
+
+ if(G.obedit->type==OB_MESH) {
+ eve= G.edve.first;
+ while(eve) {
+ G.totvert++;
+ if(eve->f & 1) G.totvertsel++;
+ eve= eve->next;
+ }
+ evl= G.edvl.first;
+ while(evl) {
+ G.totface++;
+ if(evl->v1->f & 1) {
+ if(evl->v2->f & 1) {
+ if(evl->v3->f & 1) {
+ if(evl->v4) {
+ if(evl->v4->f & 1) G.totfacesel++;
+ }
+ else {
+ G.totfacesel++;
+ }
+ }
+ }
+ }
+ evl= evl->next;
+ }
+ }
+#ifdef __NLA
+ else if (G.obedit->type==OB_ARMATURE){
+ for (ebo=G.edbo.first;ebo;ebo=ebo->next){
+
+ /* Synch selection to parent for ik children */
+ if ((ebo->flag & BONE_IK_TOPARENT) && ebo->parent){
+ G.totvert--;
+ if (ebo->parent->flag & BONE_TIPSEL)
+ ebo->flag |= BONE_ROOTSEL;
+ else
+ ebo->flag &= ~BONE_ROOTSEL;
+ }
+
+ if (ebo->flag & BONE_TIPSEL)
+ G.totvertsel++;
+ if (ebo->flag & BONE_ROOTSEL)
+ G.totvertsel++;
+
+ if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL))
+ ebo->flag |= BONE_SELECTED;
+ else
+ ebo->flag &= ~BONE_SELECTED;
+
+ // If this is an IK child and it's parent is being moved, remove our root
+ if ((ebo->flag & BONE_IK_TOPARENT)&& (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL)){
+ G.totvertsel--;
+ }
+
+ G.totvert+=2;
+ G.totface++;
+
+
+ }
+ }
+#endif
+ else if ELEM3(G.obedit->type, OB_CURVE, OB_SURF, OB_FONT) {
+ nu= editNurb.first;
+ while(nu) {
+ if((nu->type & 7)==CU_BEZIER) {
+ bezt= nu->bezt;
+ a= nu->pntsu;
+ while(a--) {
+ G.totvert+=3;
+ if(bezt->f1) G.totvertsel++;
+ if(bezt->f2) G.totvertsel++;
+ if(bezt->f3) G.totvertsel++;
+ bezt++;
+ }
+ }
+ else {
+ bp= nu->bp;
+ a= nu->pntsu*nu->pntsv;
+ while(a--) {
+ G.totvert++;
+ if(bp->f1 & 1) G.totvertsel++;
+ bp++;
+ }
+ }
+ nu= nu->next;
+ }
+ }
+ else if(G.obedit->type==OB_MBALL) {
+ ml= editelems.first;
+ while(ml) {
+ G.totvert++;
+ if(ml->flag & SELECT) G.totvertsel++;
+ ml= ml->next;
+ }
+ }
+ else if(G.obedit->type==OB_LATTICE) {
+ bp= editLatt->def;
+
+ a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
+ while(a--) {
+ G.totvert++;
+ if(bp->f1 & 1) G.totvertsel++;
+ bp++;
+ }
+ }
+
+ allqueue(REDRAWINFO, 1); /* 1, want header->win==0! */
+ return;
+ }
+ else if(G.f & (G_FACESELECT + G_VERTEXPAINT + G_TEXTUREPAINT +G_WEIGHTPAINT)) {
+ me= get_mesh((G.scene->basact) ? (G.scene->basact->object) : 0);
+ if(me) {
+ G.totface= me->totface;
+ G.totvert= me->totvert;
+ }
+ allqueue(REDRAWINFO, 1); /* 1, want header->win==0! */
+ return;
+ }
+
+ if(G.vd==0) return;
+ if(G.scene==0) return;
+
+ base= (G.scene->base.first);
+ while(base) {
+ if(G.vd->lay & base->lay) {
+
+ G.totobj++;
+ if(base->flag & SELECT) G.totobjsel++;
+
+ count_object(base->object, base->flag & SELECT);
+
+ if(base->object->transflag & OB_DUPLI) {
+ extern ListBase duplilist;
+
+ make_duplilist(G.scene, base->object);
+ ob= duplilist.first;
+ while(ob) {
+ G.totobj++;
+ count_object(ob, base->flag & SELECT);
+ ob= ob->id.next;
+ }
+ free_duplilist();
+ }
+ }
+ base= base->next;
+ }
+ allqueue(REDRAWINFO, 1); /* 1, want header->win==0! */
+}
+
+void snapmenu()
+{
+ extern TransVert *transvmain;
+ extern int tottrans;
+ extern float originmat[3][3]; /* object.c */
+ TransVert *tv;
+ Base *base;
+ Object *ob;
+ float gridf, *curs, imat[3][3], bmat[3][3], vec[3], min[3], max[3], centroid[3];
+ int count, a;
+ short event;
+
+ event= pupmenu("SNAP %t|Sel -> Grid%x1|Sel -> Curs%x2|Curs-> Grid%x3|Curs-> Sel%x4");
+
+ gridf= G.vd->grid;
+ curs= give_cursor();
+
+ if(event== 1 || event==2) { /* sel->grid sel->curs */
+
+ if(G.obedit) {
+#ifdef __NLA
+ if ELEM5(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE) make_trans_verts(bmat[0], bmat[1], 0);
+#else
+ if ELEM4(G.obedit->type, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE) make_trans_verts(bmat[0], bmat[1], 0);
+#endif
+ if(tottrans==0) return;
+
+ Mat3CpyMat4(bmat, G.obedit->obmat);
+ Mat3Inv(imat, bmat);
+
+ tv= transvmain;
+ for(a=0; a<tottrans; a++, tv++) {
+
+ if(event==2) {
+
+ vec[0]= curs[0]-G.obedit->obmat[3][0];
+ vec[1]= curs[1]-G.obedit->obmat[3][1];
+ vec[2]= curs[2]-G.obedit->obmat[3][2];
+ }
+ else {
+ VECCOPY(vec, tv->loc);
+ Mat3MulVecfl(bmat, vec);
+ VecAddf(vec, vec, G.obedit->obmat[3]);
+ vec[0]= G.vd->grid*floor(.5+ vec[0]/gridf);
+ vec[1]= G.vd->grid*floor(.5+ vec[1]/gridf);
+ vec[2]= G.vd->grid*floor(.5+ vec[2]/gridf);
+ VecSubf(vec, vec, G.obedit->obmat[3]);
+ }
+ Mat3MulVecfl(imat, vec);
+ VECCOPY(tv->loc, vec);
+
+ }
+ MEM_freeN(transvmain);
+ transvmain= 0;
+
+ if ELEM(G.obedit->type, OB_SURF, OB_CURVE) makeDispList(G.obedit);
+
+ if (G.obedit->type == OB_ARMATURE)
+ special_trans_update(0);
+
+ allqueue(REDRAWVIEW3D, 0);
+ return;
+ }
+#ifdef __NLA
+ if (G.obpose){
+ allqueue(REDRAWVIEW3D, 0);
+ return;
+ }
+#endif
+ base= (G.scene->base.first);
+ while(base) {
+ if( ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) && ((base)->object->id.lib==0))) {
+ ob= base->object;
+
+ if(event==2) {
+ vec[0]= -ob->obmat[3][0] + curs[0];
+ vec[1]= -ob->obmat[3][1] + curs[1];
+ vec[2]= -ob->obmat[3][2] + curs[2];
+ }
+ else {
+ vec[0]= -ob->obmat[3][0]+G.vd->grid*floor(.5+ ob->obmat[3][0]/gridf);
+ vec[1]= -ob->obmat[3][1]+G.vd->grid*floor(.5+ ob->obmat[3][1]/gridf);
+ vec[2]= -ob->obmat[3][2]+G.vd->grid*floor(.5+ ob->obmat[3][2]/gridf);
+ }
+ if(ob->parent) {
+ where_is_object(ob);
+
+ Mat3Inv(imat, originmat);
+ Mat3MulVecfl(imat, vec);
+ ob->loc[0]+= vec[0];
+ ob->loc[1]+= vec[1];
+ ob->loc[2]+= vec[2];
+ }
+ else {
+ ob->loc[0]+= vec[0];
+ ob->loc[1]+= vec[1];
+ ob->loc[2]+= vec[2];
+ }
+ }
+
+ base= base->next;
+ }
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if(event==3) { /* curs to grid */
+ curs[0]= G.vd->grid*floor(.5+curs[0]/gridf);
+ curs[1]= G.vd->grid*floor(.5+curs[1]/gridf);
+ curs[2]= G.vd->grid*floor(.5+curs[2]/gridf);
+
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ else if(event==4) { /* curs to sel */
+ count= 0;
+ INIT_MINMAX(min, max);
+ centroid[0]= centroid[1]= centroid[2]= 0.0;
+
+ if(G.obedit) {
+ tottrans=0;
+#ifdef __NLA
+ if ELEM5(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE) make_trans_verts(bmat[0], bmat[1], 0);
+#else
+ if ELEM4(G.obedit->type, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE) make_trans_verts(bmat[0], bmat[1], 0);
+#endif
+ if(tottrans==0) return;
+
+ Mat3CpyMat4(bmat, G.obedit->obmat);
+
+ tv= transvmain;
+ for(a=0; a<tottrans; a++, tv++) {
+ VECCOPY(vec, tv->loc);
+ Mat3MulVecfl(bmat, vec);
+ VecAddf(vec, vec, G.obedit->obmat[3]);
+ VecAddf(centroid, centroid, vec);
+ DO_MINMAX(vec, min, max);
+ }
+
+ if(G.vd->around==V3D_CENTROID) {
+ VecMulf(centroid, 1.0/(float)tottrans);
+ VECCOPY(curs, centroid);
+ }
+ else {
+ curs[0]= (min[0]+max[0])/2;
+ curs[1]= (min[1]+max[1])/2;
+ curs[2]= (min[2]+max[2])/2;
+ }
+ MEM_freeN(transvmain);
+ transvmain= 0;
+ }
+ else {
+ base= (G.scene->base.first);
+ while(base) {
+ if(((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
+ VECCOPY(vec, base->object->obmat[3]);
+ VecAddf(centroid, centroid, vec);
+ DO_MINMAX(vec, min, max);
+ count++;
+ }
+ base= base->next;
+ }
+ if(count) {
+ if(G.vd->around==V3D_CENTROID) {
+ VecMulf(centroid, 1.0/(float)count);
+ VECCOPY(curs, centroid);
+ }
+ else {
+ curs[0]= (min[0]+max[0])/2;
+ curs[1]= (min[1]+max[1])/2;
+ curs[2]= (min[2]+max[2])/2;
+ }
+ }
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+ }
+}