resolve some compiler warnings with intel c/c++ compiler
[blender.git] / source / blender / src / edit.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <math.h>
31 #include <string.h>
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 #ifndef WIN32
38 #include <unistd.h>
39 #else
40 #include <io.h>
41 #endif   
42
43 #include "MEM_guardedalloc.h"
44
45 #include "BMF_Api.h"
46
47 #include "PIL_time.h"
48
49 #include "DNA_action_types.h"
50 #include "DNA_armature_types.h"
51 #include "DNA_curve_types.h"
52 #include "DNA_group_types.h"
53 #include "DNA_ipo_types.h"
54 #include "DNA_lattice_types.h"
55 #include "DNA_meta_types.h"
56 #include "DNA_mesh_types.h"
57 #include "DNA_modifier_types.h"
58 #include "DNA_object_types.h"
59 #include "DNA_particle_types.h"
60 #include "DNA_screen_types.h"
61 #include "DNA_scene_types.h"
62 #include "DNA_space_types.h"
63 #include "DNA_view3d_types.h"
64 #include "DNA_userdef_types.h"  /* for U.dupflag */
65 #include "BLI_blenlib.h"
66 #include "BLI_arithb.h"
67 #include "BLI_editVert.h"
68 #include "BLI_linklist.h"
69
70 #include "BKE_action.h"
71 #include "BKE_armature.h"
72 #include "BKE_anim.h"
73 #include "BKE_curve.h"
74 #include "BKE_depsgraph.h"
75 #include "BKE_DerivedMesh.h"
76 #include "BKE_displist.h"
77 #include "BKE_global.h"
78 #include "BKE_ipo.h"
79 #include "BKE_lattice.h"
80 #include "BKE_mesh.h"
81 #include "BKE_modifier.h"
82 #include "BKE_object.h"
83 #include "BKE_particle.h"
84 #include "BKE_utildefines.h"
85
86 #ifdef WITH_VERSE
87 #include "BKE_verse.h"
88 #endif
89
90 #include "BIF_editmesh.h"
91 #include "BIF_editview.h"
92 #include "BIF_editarmature.h"
93 #include "BIF_editparticle.h"
94 #include "BIF_gl.h"
95 #include "BIF_glutil.h"
96 #include "BIF_interface.h"
97 #include "BIF_mywindow.h"
98 #include "BIF_resources.h"
99 #include "BIF_space.h"
100 #include "BIF_screen.h"
101 #include "BIF_toolbox.h"
102
103 #ifdef WITH_VERSE
104 #include "BIF_verse.h"
105 #endif
106
107 #include "BSE_edit.h"
108 #include "BSE_drawipo.h"
109 #include "BSE_drawview.h"
110 #include "BSE_trans_types.h"
111 #include "BSE_view.h"
112
113 #include "BDR_editobject.h"
114 #include "BDR_editmball.h"
115 #include "BDR_editcurve.h"
116
117 /* old stuff */
118 #include "blendef.h"
119 #include "mydevice.h"
120
121 /*#include "armature.h"*/
122 /*  #include "edit.h" */
123 #include "nla.h"
124 #include "transform.h"
125
126 #ifdef __NLA
127 #include "BIF_editarmature.h"
128 #endif
129
130
131 /* circle selection callback */
132 typedef void (*select_CBfunc)(short selecting, Object *editobj, short *mval, float rad);
133
134 extern void obedit_selectionCB(short selecting, Object *editobj, 
135                                short *mval, float rad);
136 extern void uvedit_selectionCB(short selecting, Object *editobj, 
137                                short *mval, float rad);
138
139 static void circle_selectCB(select_CBfunc func);
140
141 /* local protos ---------------*/
142 static void snap_curs_to_firstsel(void);
143
144 /* flag==2 only border, flag==3 cross+border
145    flag==5 cross + border + start&end frame
146  */
147 int get_border(rcti *rect, short flag)
148 {
149         float dvec[4], fac1, fac2;
150         int retval=1;
151         unsigned short event= 0;
152         short mval[2], mvalo[4], val, x1, y1;
153         char str[64];
154
155         mywinset(G.curscreen->mainwin);
156         
157         /* slightly larger, 1 pixel at the edge */
158         glReadBuffer(GL_FRONT);
159         glDrawBuffer(GL_FRONT);
160
161         /* removed my_get_frontbuffer, this crashes when it gets a part outside the screen */
162         /* solved it with just a redraw! */
163
164         mywinset(curarea->win);
165         
166         glDrawBuffer(GL_FRONT);
167         persp(PERSP_WIN);
168         initgrabz(0.0, 0.0, 0.0);
169         
170         if(flag & 1) {
171                 getmouseco_areawin(mvalo);
172
173                 /* draws the selection initial cross */
174                 sdrawXORline4(0, 0,  mvalo[1],  curarea->winx,  mvalo[1]);
175                 sdrawXORline4(1, mvalo[0],  0,  mvalo[0],  curarea->winy); 
176                 bglFlush();
177                 
178                 while(TRUE) {
179                 
180                         /* selection loop while mouse pressed */
181                         getmouseco_areawin(mval);
182                         
183                         if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
184
185                                 /* aiming cross */
186                                 sdrawXORline4(0, 0,  mval[1],  curarea->winx,  mval[1]);
187                                 sdrawXORline4(1, mval[0],  0,  mval[0],  curarea->winy);
188                                 bglFlush();
189
190                                 mvalo[0]= mval[0];
191                                 mvalo[1]= mval[1];
192                         }
193                         event= extern_qread(&val);
194
195                         if(event && val) {
196
197                                 /* for when a renderwindow is open, and a mouse cursor activates it */
198                                 persp(PERSP_VIEW);
199                                 mywinset(curarea->win);
200                                 persp(PERSP_WIN);
201                                 
202                                 if(event==ESCKEY) {
203                                         retval= 0;
204                                         break;
205                                 }
206                                 else if(event==BKEY) {
207                                         /* b has been pressed twice: proceed with circle select */
208                                         retval= 0;
209                                         break;
210                                 }
211                                 else if(event==LEFTMOUSE) break;
212                                 else if(event==MIDDLEMOUSE) break;
213                                 else if(event==RIGHTMOUSE) break;
214                         }
215                         else PIL_sleep_ms(10);
216                         
217                 } /* end while (TRUE) */
218
219                 /* erase XORed lines */
220                 sdrawXORline4(-1, 0, 0, 0, 0);
221         }
222         else getmouseco_areawin(mval);
223         
224         if(retval) {
225                 /* box select */
226                 x1= mval[0];
227                 y1= mval[1];
228                 
229                 getmouseco_areawin(mvalo);
230
231                 sdrawXORline4(0, x1, y1, x1, mvalo[1]); 
232                 sdrawXORline4(1, x1, mvalo[1], mvalo[0], mvalo[1]); 
233                 sdrawXORline4(2, mvalo[0], mvalo[1], mvalo[0], y1); 
234                 sdrawXORline4(3,  mvalo[0], y1, x1, y1); 
235                 bglFlush();
236                         
237                 while(TRUE) {
238                         getmouseco_areawin(mval);
239                         if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
240
241                                 sdrawXORline4(0, x1, y1, x1, mval[1]); 
242                                 sdrawXORline4(1, x1, mval[1], mval[0], mval[1]); 
243                                 sdrawXORline4(2, mval[0], mval[1], mval[0], y1); 
244                                 sdrawXORline4(3,  mval[0], y1, x1, y1); 
245                                 
246                                 /* draw size information in corner */
247                                 if(curarea->spacetype==SPACE_VIEW3D) {
248                                         BIF_ThemeColor(TH_BACK);
249                                         glRecti(10, 25, 250, 40);
250         
251                                         if(G.vd->persp==V3D_ORTHO) {
252                                                 window_to_3d(dvec, mvalo[0]-x1, mvalo[1]-y1);
253         
254                                                 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]));
255                                                 glColor3f(0.0, 0.0, 0.0); 
256                                                 glRasterPos2i(15,  27);
257                                                 BMF_DrawString(G.fonts, str);
258                                                 glColor3f(0.7, 0.7, 0.7); 
259                                                 glRasterPos2i(16,  28);
260                                                 BMF_DrawString(G.fonts, str);
261                                         }
262                                         else if(G.vd->persp==V3D_CAMOB) {
263                                                 rctf vb;
264         
265                                                 calc_viewborder(G.vd, &vb);
266         
267                                                 fac1= (mvalo[0]-x1)/( (float) (vb.xmax-vb.xmin) );
268                                                 fac1*= 0.01*G.scene->r.size*G.scene->r.xsch;
269                                                 
270                                                 fac2= (mvalo[1]-y1)/( (float) (vb.ymax-vb.ymin) );
271                                                 fac2*= 0.01*G.scene->r.size*G.scene->r.ysch;
272                                                 
273                                                 sprintf(str, "X %.1f  Y %.1f  Dia %.1f", fabs(fac1), fabs(fac2), sqrt(fac1*fac1 + fac2*fac2) );
274                                                 glColor3f(0.0, 0.0, 0.0); 
275                                                 glRasterPos2i(15,  27);
276                                                 BMF_DrawString(G.fonts, str);
277                                                 glColor3f(0.7, 0.7, 0.7); 
278                                                 glRasterPos2i(16,  28);
279                                                 BMF_DrawString(G.fonts, str);
280                                         }
281                                 }
282                                 else if(curarea->spacetype==SPACE_IPO) {
283                                         SpaceIpo *sipo= curarea->spacedata.first;
284         
285                                         BIF_ThemeColor(TH_BACK);
286                                         glRecti(20, 30, 170, 40);
287                                                                 
288                                         mvalo[2]= x1;
289                                         mvalo[3]= y1;
290                                         areamouseco_to_ipoco(&sipo->v2d, mval, dvec, dvec+1);
291                                         areamouseco_to_ipoco(&sipo->v2d, mvalo+2, dvec+2, dvec+3);
292
293                                         if (flag == 5) {
294                                                 /* setting preview range */
295                                                 if (dvec[0] < dvec[2])
296                                                         sprintf(str, "Preview Range: %d to %d", (int)dvec[0], (int)dvec[2]);
297                                                 else
298                                                         sprintf(str, "Preview Range: %d to %d", (int)dvec[2], (int)dvec[0]);
299                                         }
300                                         else
301                                                 sprintf(str, "Time: %.4f  Y %.4f", dvec[0]-dvec[2], dvec[1]-dvec[3]);
302                                         
303                                         BIF_ThemeColor(TH_BACK);
304                                         glRecti(14, 24, 165, 38);
305                                         
306                                         glColor3f(0.0, 0.0, 0.0); 
307                                         glRasterPos2i(15,  27);
308                                         BMF_DrawString(G.fonts, str);
309                                         glColor3f(0.8, 0.8, 0.8); 
310                                         glRasterPos2i(16,  28);
311                                         BMF_DrawString(G.fonts, str);
312                                 }
313                                 else if ((ELEM3(curarea->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_TIME)) && flag==5) {
314                                         /* only while setting preview range */
315                                         View2D *v2d;
316                                         
317                                         switch (curarea->spacetype) 
318                                         {
319                                                 case SPACE_ACTION:
320                                                 {
321                                                         SpaceAction *saaction= curarea->spacedata.first;
322                                                         v2d= &saaction->v2d;
323                                                 }
324                                                         break;
325                                                 case SPACE_NLA:
326                                                 {
327                                                         SpaceNla *snla= curarea->spacedata.first;
328                                                         v2d= &snla->v2d;
329                                                 }
330                                                         break;
331                                                 default:
332                                                         v2d= G.v2d;
333                                                         break;
334                                         }
335                                         
336                                         mvalo[2]= x1;
337                                         mvalo[3]= y1;
338                                         areamouseco_to_ipoco(v2d, mval, dvec, dvec+1);
339                                         areamouseco_to_ipoco(v2d, mvalo+2, dvec+2, dvec+3);
340                                         
341                                         if (dvec[0] < dvec[2])
342                                                 sprintf(str, "Preview Range: %d to %d", (int)dvec[0], (int)dvec[2]);
343                                         else
344                                                 sprintf(str, "Preview Range: %d to %d", (int)dvec[2], (int)dvec[0]);
345                                         
346                                         BIF_ThemeColor(TH_BACK);
347                                         glRecti(14, 24, 165, 38);
348                                         
349                                         glColor3f(0.0, 0.0, 0.0); 
350                                         glRasterPos2i(15,  27);
351                                         BMF_DrawString(G.fonts, str);
352                                         glColor3f(0.8, 0.8, 0.8); 
353                                         glRasterPos2i(16,  28);
354                                         BMF_DrawString(G.fonts, str);
355                                 }
356
357                                 bglFlush();
358
359                                 mvalo[0]= mval[0];
360                                 mvalo[1]= mval[1];
361                         }
362                         
363                         event= extern_qread(&val);
364                         
365                         if(event && val==0) {
366                                 /* still because of the renderwindow... */
367                                 persp(PERSP_VIEW);
368                                 mywinset(curarea->win);
369                                 persp(PERSP_WIN);
370                                 
371                                 if(event==ESCKEY) {
372                                         retval= 0;
373                                         break;
374                                 }
375                                 else if(event==LEFTMOUSE) break;
376                                 else if(event==MIDDLEMOUSE) break;
377                                 else if(event==RIGHTMOUSE) break;
378                         }
379                         
380                 } /* end while (TRUE) */
381                 sdrawXORline4(-1, 0, 0, 0, 0);
382                 
383                 if(retval) {
384                         rect->xmin= x1;
385                         rect->ymin= y1;
386                         rect->xmax= mval[0];
387                         rect->ymax= mval[1];
388                         retval= event;
389
390                         /* normalize */
391                         if(rect->xmin>rect->xmax) SWAP(int, rect->xmin, rect->xmax);
392                         if(rect->ymin>rect->ymax) SWAP(int, rect->ymin, rect->ymax);
393                         
394                         if(rect->xmin==rect->xmax) retval= 0;
395                         if(rect->ymin==rect->ymax) retval= 0;
396                 }
397         }
398
399
400         /* clear */
401         if(event!=BKEY) {
402                 if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_IPO) {
403                         scrarea_queue_winredraw(curarea);
404                 }
405                 else if ELEM3(curarea->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_TIME) {
406                         scrarea_queue_winredraw(curarea); // only really needed for 
407                 }
408         }
409         
410         bglFlush();
411         glReadBuffer(GL_BACK);
412         glDrawBuffer(GL_BACK);
413
414         persp(PERSP_VIEW);
415         
416         /* pressed B again ? -> brush select */
417         if(event==BKEY) {
418                 setlinestyle(0);
419                 switch (curarea->spacetype) {
420                 case SPACE_VIEW3D:
421                         if (G.obedit) {
422                                 if ELEM4(G.obedit->type, OB_MESH, OB_CURVE, OB_SURF, OB_LATTICE) {
423                                         circle_selectCB(&obedit_selectionCB);
424                                 }
425                         }
426                         else if (FACESEL_PAINT_TEST) {
427                                 circle_selectCB(&obedit_selectionCB);
428                         }
429                         else if (G.f&G_PARTICLEEDIT) {
430                                 circle_selectCB(&PE_selectionCB);
431                         }
432                         return 0;
433                         
434                 case SPACE_IMAGE: // brush select in UV editor
435                         circle_selectCB(&uvedit_selectionCB);
436                         // this is a hack; we return 0 that the caller from get_border
437                         // doesn't execute the selection code for border select..
438                         return 0;
439                 }
440         }
441         return retval;
442 }
443
444 void draw_sel_circle(short *mval, short *mvalo, float rad, float rado, int selecting)
445 {
446         static short no_mvalo=0;
447
448         if(mval==NULL && mvalo==NULL) { /* signal */
449                 no_mvalo= 1;
450                 return;
451         }
452
453         persp(PERSP_WIN);
454         glReadBuffer(GL_FRONT);
455         glDrawBuffer(GL_FRONT);
456         //setlinestyle(2);
457
458         /* draw circle */
459         if(mvalo && no_mvalo==0) {
460                 fdrawXORcirc(mvalo[0], mvalo[1], rado);
461         }
462         
463         if(mval) {
464                 fdrawXORcirc(mval[0], mval[1], rad);
465         }
466         //setlinestyle(0);
467
468         bglFlush();
469         persp(PERSP_VIEW);
470         glDrawBuffer(GL_BACK);
471         glReadBuffer(GL_BACK);
472
473         no_mvalo= 0;
474 }
475
476 /** This function does the same as editview.c:circle_select(),
477   * but the selection actions are defined by a callback, making
478   * it (hopefully) reusable for other windows than the 3D view.
479   */
480
481 static void circle_selectCB(select_CBfunc callback)
482 {
483         static float rad= 40.0;
484         float rado= rad;
485         int firsttime=1;
486         int escape= 0;
487         unsigned short event;
488         short mvalo[2], mval[2], val;
489         short selecting=0;
490         Object *obj;
491         
492         if(G.obedit) obj = G.obedit;
493         else obj = OBACT;
494
495         mywinset(curarea->win);
496         
497         getmouseco_areawin(mvalo);
498         mval[0]= mvalo[0]; mval[1]= mvalo[1];
499
500         draw_sel_circle(mval, NULL, rad, 0.0, selecting); // draws frontbuffer, but sets backbuf again
501         
502         while(TRUE) {
503                 
504                 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || rado!=rad || firsttime) {
505                         firsttime= 0;
506                         
507                         if(selecting) {
508                                 callback(selecting, obj, mval, rad);
509                         }
510
511                         draw_sel_circle(mval, mvalo, rad, rado, selecting);
512                 
513                         mvalo[0]= mval[0];
514                         mvalo[1]= mval[1];
515                         rado= rad;
516
517                 }
518                 
519                 while(qtest()) {
520                         event= extern_qread(&val);
521                         if (event) {
522
523                                 /* for when another window is open and a mouse cursor activates it */
524                                 if(event!=MOUSEY && event!=MOUSEX) mywinset(curarea->win);
525                                 
526                                 getmouseco_areawin(mval);       // important to do here, trust events!
527                                 
528                                 switch(event) {
529                         
530                                 case LEFTMOUSE:
531                                 case MIDDLEMOUSE:
532                                         if(val) selecting= event;
533                                         else selecting= 0;
534                                         firsttime= 1;
535                                         
536                                         break;
537                                 case PAGEUPKEY:
538                                 case WHEELDOWNMOUSE:
539                                 case PADPLUSKEY:
540                                 case EQUALKEY:
541                                         if(val) if(rad<200.0) rad*= 1.2;
542                                         break;
543                                 case PAGEDOWNKEY:
544                                 case WHEELUPMOUSE:
545                                 case PADMINUS:
546                                 case MINUSKEY:
547                                         if(val) if(rad>5.0) rad/= 1.2;
548                                         break;
549                                 
550                                 case ESCKEY: case SPACEKEY: case RIGHTMOUSE: case INPUTCHANGE: 
551                                 case GKEY: case SKEY: case RKEY: case XKEY: case EKEY: case TABKEY:
552                                         escape= 1;
553                                         break;
554
555                                 }
556                                 
557                                 if(escape) break;
558                         }
559                 }
560                 PIL_sleep_ms(10);
561                 
562                 if(escape) break;
563         }
564         
565         /* clear circle */
566         draw_sel_circle(NULL, mvalo, 0, rad, 1);
567         BIF_undo_push("Circle Select");
568         countall();
569         allqueue(REDRAWINFO, 0);
570 }
571
572 static void count_object(Object *ob, int sel, int totob)
573 {
574         Mesh *me;
575         Curve *cu;
576         DerivedMesh *dm;
577         int tot=0, totf=0;
578
579         switch(ob->type) {
580         case OB_MESH:
581                         G.totmesh+=totob;
582                         me= get_mesh(ob);
583                         if(me) {
584                                         int totvert, totedge, totface;
585                                         dm = mesh_get_derived_final(ob, get_viewedit_datamask());
586                                         totvert = dm->getNumVerts(dm);
587                                         totedge = dm->getNumEdges(dm);
588                                         totface = dm->getNumFaces(dm);
589
590                                         G.totvert+= totvert*totob;
591                                         G.totedge+= totedge*totob;
592                                         G.totface+= totface*totob;
593                                         if(sel) {
594                                                         G.totvertsel+= totvert;
595                                                         G.totfacesel+= totface;
596                                         }
597                         }
598                         break;
599
600         case OB_LAMP:
601                 G.totlamp+=totob;
602                 break;
603         case OB_SURF:
604         case OB_CURVE:
605         case OB_FONT:
606                 G.totcurve+=totob;
607                 tot=totf= 0;
608                 cu= ob->data;
609                 if(cu->disp.first)
610                         count_displist( &cu->disp, &tot, &totf);
611                 tot*= totob;
612                 totf*= totob;
613                 G.totvert+= tot;
614                 G.totface+= totf;
615                 if(sel) {
616                         G.totvertsel+= tot;
617                         G.totfacesel+= totf;
618                 }
619                 break;
620         case OB_MBALL:
621                 count_displist( &ob->disp, &tot, &totf);
622                 tot*= totob;
623                 totf*= totob;
624                 G.totvert+= tot;
625                 G.totface+= totf;
626                 if(sel) {
627                         G.totvertsel+= tot;
628                         G.totfacesel+= totf;
629                 }
630                 break;
631         }
632         
633 }
634
635 /* countall does statistics */
636 /* is called on most actions, like select/add/delete/layermove */
637 void countall()
638 {
639         extern ListBase editNurb;
640         Base *base;
641         Object *ob= OBACT;
642         Mesh *me;
643         Nurb *nu;
644         BezTriple *bezt;
645         BPoint *bp;
646         MetaElem *ml;
647         struct EditBone *ebo;
648         int a;
649
650         G.totvert= G.totvertsel= G.totedge= G.totedgesel= G.totfacesel= G.totface= G.totobj= 
651             G.totmesh= G.totlamp= G.totcurve= G.totobjsel= G.totbone= G.totbonesel=  0;
652
653         if(G.obedit) {
654                 
655                 if(G.obedit->type==OB_MESH) {
656                         EditMesh *em = G.editMesh;
657                         EditVert *eve;
658                         EditEdge *eed;
659                         EditFace *efa;
660                         
661                         for(eve= em->verts.first; eve; eve= eve->next) {
662                                 G.totvert++;
663                                 if(eve->f & SELECT) G.totvertsel++;
664                         }
665                         for(eed= em->edges.first; eed; eed= eed->next) {
666                                 G.totedge++;
667                                 if(eed->f & SELECT) G.totedgesel++;
668                         }
669                         for(efa= em->faces.first; efa; efa= efa->next) {
670                                 G.totface++;
671                                 if(efa->f & SELECT) G.totfacesel++;
672                         }
673                         
674                         EM_validate_selections();
675                 }
676                 else if (G.obedit->type==OB_ARMATURE){
677                         for (ebo=G.edbo.first;ebo;ebo=ebo->next){
678                                 G.totbone++;
679                                 
680                                 /* Sync selection to parent for connected children */
681                                 if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
682                                         G.totvert--;
683                                         if (ebo->parent->flag & BONE_TIPSEL)
684                                                 ebo->flag |= BONE_ROOTSEL;
685                                         else
686                                                 ebo->flag &= ~BONE_ROOTSEL;
687                                 }
688                                 
689                                 if (ebo->flag & BONE_TIPSEL)
690                                         G.totvertsel++;
691                                 if (ebo->flag & BONE_ROOTSEL)
692                                         G.totvertsel++;
693                                 
694                                 if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL))
695                                         ebo->flag |= BONE_SELECTED;
696                                 else
697                                         ebo->flag &= ~BONE_SELECTED;
698                                 
699                                 if(ebo->flag & BONE_SELECTED) G.totbonesel++;
700
701                                 //      If this is a connected child and it's parent is being moved, remove our root
702                                 if ((ebo->flag & BONE_CONNECTED)&& (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL)){
703                                         G.totvertsel--;
704                                 }
705
706                                 G.totvert+=2;
707                         }
708                 }
709                 else if ELEM3(G.obedit->type, OB_CURVE, OB_SURF, OB_FONT) {
710                         nu= editNurb.first;
711                         while(nu) {
712                                 if((nu->type & 7)==CU_BEZIER) {
713                                         bezt= nu->bezt;
714                                         a= nu->pntsu;
715                                         while(a--) {
716                                                 G.totvert+=3;
717                                                 if(bezt->f1) G.totvertsel++;
718                                                 if(bezt->f2) G.totvertsel++;
719                                                 if(bezt->f3) G.totvertsel++;
720                                                 bezt++;
721                                         }
722                                 }
723                                 else {
724                                         bp= nu->bp;
725                                         a= nu->pntsu*nu->pntsv;
726                                         while(a--) {
727                                                 G.totvert++;
728                                                 if(bp->f1 & SELECT) G.totvertsel++;
729                                                 bp++;
730                                         }
731                                 }
732                                 nu= nu->next;
733                         }
734                 }
735                 else if(G.obedit->type==OB_MBALL) {
736                         /* editmball.c */
737                         extern ListBase editelems;  /* go away ! */
738                         
739                         ml= editelems.first;
740                         while(ml) {
741                                 G.totvert++;
742                                 if(ml->flag & SELECT) G.totvertsel++;
743                                 ml= ml->next;
744                         }
745                 }
746                 else if(G.obedit->type==OB_LATTICE) {
747                         bp= editLatt->def;
748                         
749                         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
750                         while(a--) {
751                                 G.totvert++;
752                                 if(bp->f1 & SELECT) G.totvertsel++;
753                                 bp++;
754                         }
755                 }
756                 
757                 allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
758                 return;
759         }
760         else if(ob && (ob->flag & OB_POSEMODE)) {
761                 if(ob->pose) {
762                         bArmature *arm= ob->data;
763                         bPoseChannel *pchan;
764                         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
765                                 G.totbone++;
766                                 if(pchan->bone && (pchan->bone->flag & BONE_SELECTED))
767                                         if(pchan->bone->layer & arm->layer)
768                                                 G.totbonesel++;
769                         }
770                 }
771                 allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
772                 return;
773         }
774         else if(FACESEL_PAINT_TEST) {
775                 me= get_mesh((G.scene->basact) ? (G.scene->basact->object) : 0);
776                 if(me) {
777                         G.totface= me->totface;
778                         G.totvert= me->totvert;
779                 }
780                 allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
781                 return;
782         }
783
784         if(G.scene==NULL) return;
785
786         base= (G.scene->base.first);
787         while(base) {
788                 if(G.scene->lay & base->lay) {
789                         ob= base->object;       /* warning, ob not is obact anymore */
790                         
791                         if(base->flag & SELECT) G.totobjsel++;
792
793                         if(ob->transflag & OB_DUPLIPARTS) {
794                                 ParticleSystem *psys;
795                                 ParticleSettings *part;
796                                 int step_nbr;
797
798                                 for(psys=ob->particlesystem.first; psys; psys=psys->next){
799                                         part=psys->part;
800                                         
801                                         //if(psys->flag&PSYS_BAKED && part->draw&PART_DRAW_KEYS)
802                                         //      step_nbr=part->keys_step;
803                                         //else
804                                                 step_nbr=1;
805
806                                         if(part->draw_as==PART_DRAW_OB && part->dup_ob){
807                                                 int tot=count_particles(psys);
808                                                 count_object(part->dup_ob, 0, tot*step_nbr);
809                                         }
810                                         else if(part->draw_as==PART_DRAW_GR && part->dup_group){
811                                                 GroupObject *go;
812                                                 int tot, totgroup=0, cur=0;
813                                                 
814                                                 go= part->dup_group->gobject.first;
815                                                 while(go){
816                                                         go=go->next;
817                                                         totgroup++;
818                                                 }
819                                                 go= part->dup_group->gobject.first;
820                                                 while(go){
821                                                         tot=count_particles_mod(psys,totgroup,cur);
822                                                         count_object(go->ob, 0, tot*step_nbr);
823                                                         cur++;
824                                                         go=go->next;
825                                                 }
826                                         }
827                                 }
828                                 
829                                 count_object(ob, base->flag & SELECT, 1);
830                                 G.totobj++;
831                         }
832                         else if(ob->parent && (ob->parent->transflag & (OB_DUPLIVERTS|OB_DUPLIFACES))) {
833                                 int tot= count_duplilist(ob->parent);
834                                 G.totobj+=tot;
835                                 count_object(ob, base->flag & SELECT, tot);
836                         }
837                         else if(ob->transflag & OB_DUPLIFRAMES) {
838                                 int tot= count_duplilist(ob);
839                                 G.totobj+=tot;
840                                 count_object(ob, base->flag & SELECT, tot);
841                         }
842                         else if((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
843                                 int tot= count_duplilist(ob);
844                                 G.totobj+=tot;
845                                 count_object(ob, base->flag & SELECT, tot);
846                         }
847                         else {
848                                 count_object(ob, base->flag & SELECT, 1);
849                                 G.totobj++;
850                         }
851                 }
852                 base= base->next;
853         }
854         allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
855 }
856
857 /* ************************************************** */
858 /* ********************* old transform stuff ******** */
859 /* ************************************************** */
860
861 static TransVert *transvmain=NULL;
862 static int tottrans= 0;
863
864 /* copied from editobject.c, now uses (almost) proper depgraph */
865 static void special_transvert_update(void)
866 {
867         
868         if(G.obedit) {
869                 
870                 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
871                 
872                 if(G.obedit->type==OB_MESH) {
873 #ifdef WITH_VERSE
874                         if(G.editMesh->vnode)
875                                 sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
876 #endif
877                         recalc_editnormals();   // does face centers too
878                 }
879                 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
880                         extern ListBase editNurb;
881                         Nurb *nu= editNurb.first;
882                         while(nu) {
883                                 test2DNurb(nu);
884                                 testhandlesNurb(nu); /* test for bezier too */
885                                 nu= nu->next;
886                         }
887                 }
888                 else if(G.obedit->type==OB_ARMATURE){
889                         bArmature *arm= G.obedit->data;
890                         EditBone *ebo;
891                         TransVert *tv= transvmain;
892                         int a=0;
893                         
894                         /* Ensure all bone tails are correctly adjusted */
895                         for (ebo=G.edbo.first; ebo; ebo=ebo->next) {
896                                 /* adjust tip if both ends selected */
897                                 if ((ebo->flag & BONE_ROOTSEL) && (ebo->flag & BONE_TIPSEL)) {
898                                         if (tv) {
899                                                 float diffvec[3];
900                                                 
901                                                 VecSubf(diffvec, tv->loc, tv->oldloc);
902                                                 VecAddf(ebo->tail, ebo->tail, diffvec);
903                                                 
904                                                 a++;
905                                                 if (a<tottrans) tv++;
906                                         }
907                                 }
908                         }
909                         
910                         /* Ensure all bones are correctly adjusted */
911                         for (ebo=G.edbo.first; ebo; ebo=ebo->next) {
912                                 if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
913                                         /* If this bone has a parent tip that has been moved */
914                                         if (ebo->parent->flag & BONE_TIPSEL){
915                                                 VECCOPY (ebo->head, ebo->parent->tail);
916                                         }
917                                         /* If this bone has a parent tip that has NOT been moved */
918                                         else{
919                                                 VECCOPY (ebo->parent->tail, ebo->head);
920                                         }
921                                 }
922                         }
923                         if(arm->flag & ARM_MIRROR_EDIT) 
924                                 transform_armature_mirror_update();
925                 }
926                 else if(G.obedit->type==OB_LATTICE) {
927                         if(editLatt->flag & LT_OUTSIDE) outside_lattice(editLatt);
928                 }
929         }
930 }
931
932 /* copied from editobject.c, needs to be replaced with new transform code still */
933 /* mode: 1 = proportional, 2 = all joints (for bones only) */
934 static void make_trans_verts(float *min, float *max, int mode)  
935 {
936         extern ListBase editNurb;
937         EditMesh *em = G.editMesh;
938         Nurb *nu;
939         BezTriple *bezt;
940         BPoint *bp;
941         TransVert *tv=NULL;
942         MetaElem *ml;
943         EditVert *eve;
944         EditBone        *ebo;
945         float total, center[3], centroid[3];
946         int a;
947
948         tottrans= 0; // global!
949         
950         INIT_MINMAX(min, max);
951         centroid[0]=centroid[1]=centroid[2]= 0.0;
952         
953         /* note for transform refactor: dont rely on countall anymore... its ancient */
954         /* I skip it for editmesh now (ton) */
955         if(G.obedit->type!=OB_MESH) {
956                 countall();
957                 if(mode) tottrans= G.totvert;
958                 else tottrans= G.totvertsel;
959
960                 if(G.totvertsel==0) {
961                         tottrans= 0;
962                         return;
963                 }
964                 tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
965         }
966         
967         /* we count again because of hide (old, not for mesh!) */
968         tottrans= 0;
969         
970         if(G.obedit->type==OB_MESH) {
971                 int proptrans= 0;
972                 
973                 // transform now requires awareness for select mode, so we tag the f1 flags in verts
974                 tottrans= 0;
975                 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
976                         for(eve= em->verts.first; eve; eve= eve->next) {
977                                 if(eve->h==0 && (eve->f & SELECT)) {
978                                         eve->f1= SELECT;
979                                         tottrans++;
980                                 }
981                                 else eve->f1= 0;
982                         }
983                 }
984                 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
985                         EditEdge *eed;
986                         for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
987                         for(eed= em->edges.first; eed; eed= eed->next) {
988                                 if(eed->h==0 && (eed->f & SELECT)) eed->v1->f1= eed->v2->f1= SELECT;
989                         }
990                         for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
991                 }
992                 else {
993                         EditFace *efa;
994                         for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
995                         for(efa= em->faces.first; efa; efa= efa->next) {
996                                 if(efa->h==0 && (efa->f & SELECT)) {
997                                         efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
998                                         if(efa->v4) efa->v4->f1= SELECT;
999                                 }
1000                         }
1001                         for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
1002                 }
1003                 
1004                 /* proportional edit exception... */
1005                 if((mode & 1) && tottrans) {
1006                         for(eve= em->verts.first; eve; eve= eve->next) {
1007                                 if(eve->h==0) {
1008                                         eve->f1 |= 2;
1009                                         proptrans++;
1010                                 }
1011                         }
1012                         if(proptrans>tottrans) tottrans= proptrans;
1013                 }
1014                 
1015                 /* and now make transverts */
1016                 if(tottrans) {
1017                         tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
1018
1019                         for(eve= em->verts.first; eve; eve= eve->next) {
1020                                 if(eve->f1) {
1021                                         VECCOPY(tv->oldloc, eve->co);
1022                                         tv->loc= eve->co;
1023                                         if(eve->no[0]!=0.0 || eve->no[1]!=0.0 ||eve->no[2]!=0.0)
1024                                                 tv->nor= eve->no; // note this is a hackish signal (ton)
1025                                         tv->flag= eve->f1 & SELECT;
1026                                         tv++;
1027                                 }
1028                         }
1029                 }
1030         }
1031         else if (G.obedit->type==OB_ARMATURE){
1032                 bArmature *arm= G.obedit->data;
1033                 
1034                 for (ebo=G.edbo.first;ebo;ebo=ebo->next){
1035                         if(ebo->layer & arm->layer) {
1036                                 short tipsel= (ebo->flag & BONE_TIPSEL);
1037                                 short rootsel= (ebo->flag & BONE_ROOTSEL);
1038                                 short rootok= (!(ebo->parent && (ebo->flag & BONE_CONNECTED) && ebo->parent->flag & BONE_TIPSEL));
1039                                 
1040                                 if ((tipsel && rootsel) || (rootsel)) {
1041                                         /* Don't add the tip (unless mode & 2, for getting all joints), 
1042                                          * otherwise we get zero-length bones as tips will snap to the same
1043                                          * location as heads. 
1044                                          */
1045                                         if (rootok) {
1046                                                 VECCOPY (tv->oldloc, ebo->head);
1047                                                 tv->loc= ebo->head;
1048                                                 tv->nor= NULL;
1049                                                 tv->flag= 1;
1050                                                 tv++;
1051                                                 tottrans++;
1052                                         }       
1053                                         
1054                                         if ((mode & 2) && (tipsel)) {
1055                                                 VECCOPY (tv->oldloc, ebo->tail);
1056                                                 tv->loc= ebo->tail;
1057                                                 tv->nor= NULL;
1058                                                 tv->flag= 1;
1059                                                 tv++;
1060                                                 tottrans++;
1061                                         }                                       
1062                                 }
1063                                 else if (tipsel) {
1064                                         VECCOPY (tv->oldloc, ebo->tail);
1065                                         tv->loc= ebo->tail;
1066                                         tv->nor= NULL;
1067                                         tv->flag= 1;
1068                                         tv++;
1069                                         tottrans++;
1070                                 }
1071                         }                       
1072                 }
1073         }
1074         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
1075                 nu= editNurb.first;
1076                 while(nu) {
1077                         if((nu->type & 7)==CU_BEZIER) {
1078                                 a= nu->pntsu;
1079                                 bezt= nu->bezt;
1080                                 while(a--) {
1081                                         if(bezt->hide==0) {
1082                                                 if((mode & 1) || (bezt->f1 & SELECT)) {
1083                                                         VECCOPY(tv->oldloc, bezt->vec[0]);
1084                                                         tv->loc= bezt->vec[0];
1085                                                         tv->flag= bezt->f1 & SELECT;
1086                                                         tv++;
1087                                                         tottrans++;
1088                                                 }
1089                                                 if((mode & 1) || (bezt->f2 & SELECT)) {
1090                                                         VECCOPY(tv->oldloc, bezt->vec[1]);
1091                                                         tv->loc= bezt->vec[1];
1092                                                         tv->val= &(bezt->alfa);
1093                                                         tv->oldval= bezt->alfa;
1094                                                         tv->flag= bezt->f2 & SELECT;
1095                                                         tv++;
1096                                                         tottrans++;
1097                                                 }
1098                                                 if((mode & 1) || (bezt->f3 & SELECT)) {
1099                                                         VECCOPY(tv->oldloc, bezt->vec[2]);
1100                                                         tv->loc= bezt->vec[2];
1101                                                         tv->flag= bezt->f3 & SELECT;
1102                                                         tv++;
1103                                                         tottrans++;
1104                                                 }
1105                                         }
1106                                         bezt++;
1107                                 }
1108                         }
1109                         else {
1110                                 a= nu->pntsu*nu->pntsv;
1111                                 bp= nu->bp;
1112                                 while(a--) {
1113                                         if(bp->hide==0) {
1114                                                 if((mode & 1) || (bp->f1 & SELECT)) {
1115                                                         VECCOPY(tv->oldloc, bp->vec);
1116                                                         tv->loc= bp->vec;
1117                                                         tv->val= &(bp->alfa);
1118                                                         tv->oldval= bp->alfa;
1119                                                         tv->flag= bp->f1 & SELECT;
1120                                                         tv++;
1121                                                         tottrans++;
1122                                                 }
1123                                         }
1124                                         bp++;
1125                                 }
1126                         }
1127                         nu= nu->next;
1128                 }
1129         }
1130         else if(G.obedit->type==OB_MBALL) {
1131                 extern ListBase editelems;  /* go away ! */
1132                 ml= editelems.first;
1133                 while(ml) {
1134                         if(ml->flag & SELECT) {
1135                                 tv->loc= &ml->x;
1136                                 VECCOPY(tv->oldloc, tv->loc);
1137                                 tv->val= &(ml->rad);
1138                                 tv->oldval= ml->rad;
1139                                 tv->flag= 1;
1140                                 tv++;
1141                                 tottrans++;
1142                         }
1143                         ml= ml->next;
1144                 }
1145         }
1146         else if(G.obedit->type==OB_LATTICE) {
1147                 bp= editLatt->def;
1148                 
1149                 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1150                 
1151                 while(a--) {
1152                         if((mode & 1) || (bp->f1 & SELECT)) {
1153                                 if(bp->hide==0) {
1154                                         VECCOPY(tv->oldloc, bp->vec);
1155                                         tv->loc= bp->vec;
1156                                         tv->flag= bp->f1 & SELECT;
1157                                         tv++;
1158                                         tottrans++;
1159                                 }
1160                         }
1161                         bp++;
1162                 }
1163         }
1164         
1165         /* cent etc */
1166         tv= transvmain;
1167         total= 0.0;
1168         for(a=0; a<tottrans; a++, tv++) {
1169                 if(tv->flag & SELECT) {
1170                         centroid[0]+= tv->oldloc[0];
1171                         centroid[1]+= tv->oldloc[1];
1172                         centroid[2]+= tv->oldloc[2];
1173                         total+= 1.0;
1174                         DO_MINMAX(tv->oldloc, min, max);
1175                 }
1176         }
1177         if(total!=0.0) {
1178                 centroid[0]/= total;
1179                 centroid[1]/= total;
1180                 centroid[2]/= total;
1181         }
1182
1183         center[0]= (min[0]+max[0])/2.0;
1184         center[1]= (min[1]+max[1])/2.0;
1185         center[2]= (min[2]+max[2])/2.0;
1186         
1187 }
1188
1189 void snap_sel_to_grid()
1190 {
1191         extern float originmat[3][3];   /* object.c */
1192         TransVert *tv;
1193         Base *base;
1194         Object *ob;
1195         float gridf, imat[3][3], bmat[3][3], vec[3];
1196         int a;
1197
1198         gridf= G.vd->gridview;
1199
1200
1201         if(G.obedit) {
1202                 tottrans= 0;
1203                 
1204                 if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) 
1205                         make_trans_verts(bmat[0], bmat[1], 0);
1206                 if(tottrans==0) return;
1207                 
1208                 Mat3CpyMat4(bmat, G.obedit->obmat);
1209                 Mat3Inv(imat, bmat);
1210                 
1211                 tv= transvmain;
1212                 for(a=0; a<tottrans; a++, tv++) {
1213                         
1214                         VECCOPY(vec, tv->loc);
1215                         Mat3MulVecfl(bmat, vec);
1216                         VecAddf(vec, vec, G.obedit->obmat[3]);
1217                         vec[0]= G.vd->gridview*floor(.5+ vec[0]/gridf);
1218                         vec[1]= G.vd->gridview*floor(.5+ vec[1]/gridf);
1219                         vec[2]= G.vd->gridview*floor(.5+ vec[2]/gridf);
1220                         VecSubf(vec, vec, G.obedit->obmat[3]);
1221                         
1222                         Mat3MulVecfl(imat, vec);
1223                         VECCOPY(tv->loc, vec);
1224                         
1225                 }
1226                 
1227                 special_transvert_update();
1228                 
1229                 MEM_freeN(transvmain);
1230                 transvmain= 0;
1231         
1232                 allqueue(REDRAWVIEW3D, 0);
1233                 return;
1234         }
1235
1236         base= (G.scene->base.first);
1237         while(base) {
1238                 if( ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) && ((base)->object->id.lib==0))) {
1239                         ob= base->object;
1240                         if(ob->flag & OB_POSEMODE) {
1241                                 bPoseChannel *pchan;
1242                                 bArmature *arm= ob->data;
1243                                 
1244                                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1245                                         if(pchan->bone->flag & BONE_SELECTED) {
1246                                                 if(pchan->bone->layer & arm->layer) {
1247                                                         if((pchan->bone->flag & BONE_CONNECTED)==0) { 
1248                                                                 float vecN[3], nLoc[3]; 
1249                                                                 
1250                                                                 /* get nearest grid point to snap to */
1251                                                                 VECCOPY(nLoc, pchan->pose_mat[3]);
1252                                                                 vec[0]= gridf * (float)(floor(.5+ nLoc[0]/gridf));
1253                                                                 vec[1]= gridf * (float)(floor(.5+ nLoc[1]/gridf));
1254                                                                 vec[2]= gridf * (float)(floor(.5+ nLoc[2]/gridf));
1255                                                                 
1256                                                                 /* get bone-space location of grid point */
1257                                                                 armature_loc_pose_to_bone(pchan, vec, vecN);
1258                                                                 
1259                                                                 /* adjust location */
1260                                                                 VECCOPY(pchan->loc, vecN);
1261                                                         }
1262                                                         /* if the bone has a parent and is connected to the parent, 
1263                                                          * don't do anything - will break chain unless we do auto-ik. 
1264                                                          */
1265                                                 }
1266                                         }
1267                                 }
1268                                 ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
1269                                 
1270                                 /* auto-keyframing */
1271                                 autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
1272                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1273                         }
1274                         else {
1275                                 ob->recalc |= OB_RECALC_OB;
1276                                 
1277                                 vec[0]= -ob->obmat[3][0]+G.vd->gridview*floor(.5+ ob->obmat[3][0]/gridf);
1278                                 vec[1]= -ob->obmat[3][1]+G.vd->gridview*floor(.5+ ob->obmat[3][1]/gridf);
1279                                 vec[2]= -ob->obmat[3][2]+G.vd->gridview*floor(.5+ ob->obmat[3][2]/gridf);
1280                                 
1281                                 if(ob->parent) {
1282                                         where_is_object(ob);
1283                                         
1284                                         Mat3Inv(imat, originmat);
1285                                         Mat3MulVecfl(imat, vec);
1286                                         ob->loc[0]+= vec[0];
1287                                         ob->loc[1]+= vec[1];
1288                                         ob->loc[2]+= vec[2];
1289                                 }
1290                                 else {
1291                                         ob->loc[0]+= vec[0];
1292                                         ob->loc[1]+= vec[1];
1293                                         ob->loc[2]+= vec[2];
1294                                 }
1295 #ifdef WITH_VERSE
1296                                 if(ob->vnode) b_verse_send_transformation(ob);
1297 #endif
1298                         
1299                                 /* auto-keyframing */
1300                                 autokeyframe_ob_cb_func(ob, TFM_TRANSLATION);
1301                         }
1302                 }
1303
1304                 base= base->next;
1305         }
1306         DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0);
1307         allqueue(REDRAWVIEW3D, 0);
1308 }
1309
1310 void snap_sel_to_curs()
1311 {
1312         extern float originmat[3][3];   /* object.c */
1313         TransVert *tv;
1314         Base *base;
1315         Object *ob;
1316         float *curs, imat[3][3], bmat[3][3], vec[3];
1317         int a;
1318
1319         curs= give_cursor();
1320
1321         if(G.obedit) {
1322                 tottrans= 0;
1323                 
1324                 if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) 
1325                         make_trans_verts(bmat[0], bmat[1], 0);
1326                 if(tottrans==0) return;
1327                 
1328                 Mat3CpyMat4(bmat, G.obedit->obmat);
1329                 Mat3Inv(imat, bmat);
1330                 
1331                 tv= transvmain;
1332                 for(a=0; a<tottrans; a++, tv++) {
1333                         vec[0]= curs[0]-G.obedit->obmat[3][0];
1334                         vec[1]= curs[1]-G.obedit->obmat[3][1];
1335                         vec[2]= curs[2]-G.obedit->obmat[3][2];
1336                         
1337                         Mat3MulVecfl(imat, vec);
1338                         VECCOPY(tv->loc, vec);
1339                 }
1340                 
1341                 special_transvert_update();
1342                 
1343                 MEM_freeN(transvmain);
1344                 transvmain= 0;
1345                 
1346                 allqueue(REDRAWVIEW3D, 0);
1347                 return;
1348         }
1349
1350         base= (G.scene->base.first);
1351         while(base) {
1352                 if( ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) && ((base)->object->id.lib==0))) {
1353                         ob= base->object;
1354                         if(ob->flag & OB_POSEMODE) {
1355                                 bPoseChannel *pchan;
1356                                 bArmature *arm= ob->data;
1357                                 float cursp[3];
1358                                 
1359                                 Mat4Invert(ob->imat, ob->obmat);
1360                                 VECCOPY(cursp, curs);
1361                                 Mat4MulVecfl(ob->imat, cursp);
1362                                 
1363                                 for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
1364                                         if(pchan->bone->flag & BONE_SELECTED) {
1365                                                 if(pchan->bone->layer & arm->layer) {
1366                                                         if((pchan->bone->flag & BONE_CONNECTED)==0) { 
1367                                                                 float curspn[3];
1368                                                                 
1369                                                                 /* get location of cursor in bone-space */
1370                                                                 armature_loc_pose_to_bone(pchan, cursp, curspn);
1371                                                                 
1372                                                                 /* calculate new position */
1373                                                                 VECCOPY(pchan->loc, curspn);
1374                                                         }
1375                                                         /* if the bone has a parent and is connected to the parent, 
1376                                                          * don't do anything - will break chain unless we do auto-ik. 
1377                                                          */
1378                                                 }
1379                                         }
1380                                 }
1381                                 ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
1382                                 
1383                                 /* auto-keyframing */
1384                                 autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
1385                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1386                         }
1387                         else {
1388                                 ob->recalc |= OB_RECALC_OB;
1389                                 
1390                                 vec[0]= -ob->obmat[3][0] + curs[0];
1391                                 vec[1]= -ob->obmat[3][1] + curs[1];
1392                                 vec[2]= -ob->obmat[3][2] + curs[2];
1393                                 
1394                                 if(ob->parent) {
1395                                         where_is_object(ob);
1396                                         
1397                                         Mat3Inv(imat, originmat);
1398                                         Mat3MulVecfl(imat, vec);
1399                                         ob->loc[0]+= vec[0];
1400                                         ob->loc[1]+= vec[1];
1401                                         ob->loc[2]+= vec[2];
1402                                 }
1403                                 else {
1404                                         ob->loc[0]+= vec[0];
1405                                         ob->loc[1]+= vec[1];
1406                                         ob->loc[2]+= vec[2];
1407                                 }
1408 #ifdef WITH_VERSE
1409                                 if(ob->vnode) b_verse_send_transformation(ob);
1410 #endif
1411                                 
1412                                 /* auto-keyframing */
1413                                 autokeyframe_ob_cb_func(ob, TFM_TRANSLATION);
1414                         }
1415                 }
1416
1417                 base= base->next;
1418         }
1419         DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0);
1420         allqueue(REDRAWVIEW3D, 0);
1421 }
1422
1423 void snap_curs_to_grid()
1424 {
1425         float gridf, *curs;
1426
1427         gridf= G.vd->gridview;
1428         curs= give_cursor();
1429
1430         curs[0]= G.vd->gridview*floor(.5+curs[0]/gridf);
1431         curs[1]= G.vd->gridview*floor(.5+curs[1]/gridf);
1432         curs[2]= G.vd->gridview*floor(.5+curs[2]/gridf);
1433
1434         allqueue(REDRAWVIEW3D, 0);
1435 }
1436
1437 void snap_curs_to_sel()
1438 {
1439         TransVert *tv;
1440         Base *base;
1441         float *curs, bmat[3][3], vec[3], min[3], max[3], centroid[3];
1442         int count, a;
1443
1444         curs= give_cursor();
1445
1446         count= 0;
1447         INIT_MINMAX(min, max);
1448         centroid[0]= centroid[1]= centroid[2]= 0.0;
1449
1450         if(G.obedit) {
1451                 tottrans=0;
1452                 
1453                 if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) 
1454                         make_trans_verts(bmat[0], bmat[1], 2);
1455                 if(tottrans==0) return;
1456                 
1457                 Mat3CpyMat4(bmat, G.obedit->obmat);
1458                 
1459                 tv= transvmain;
1460                 for(a=0; a<tottrans; a++, tv++) {
1461                         VECCOPY(vec, tv->loc);
1462                         Mat3MulVecfl(bmat, vec);
1463                         VecAddf(vec, vec, G.obedit->obmat[3]);
1464                         VecAddf(centroid, centroid, vec);
1465                         DO_MINMAX(vec, min, max);
1466                 }
1467                 
1468                 if(G.vd->around==V3D_CENTROID) {
1469                         VecMulf(centroid, 1.0/(float)tottrans);
1470                         VECCOPY(curs, centroid);
1471                 }
1472                 else {
1473                         curs[0]= (min[0]+max[0])/2;
1474                         curs[1]= (min[1]+max[1])/2;
1475                         curs[2]= (min[2]+max[2])/2;
1476                 }
1477                 MEM_freeN(transvmain);
1478                 transvmain= 0;
1479         }
1480         else {
1481                 Object *ob= OBACT;
1482                 
1483                 if(ob && (ob->flag & OB_POSEMODE)) {
1484                         bArmature *arm= ob->data;
1485                         bPoseChannel *pchan;
1486                         for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
1487                                 if(arm->layer & pchan->bone->layer) {
1488                                         if(pchan->bone->flag & BONE_SELECTED) {
1489                                                 VECCOPY(vec, pchan->pose_head);
1490                                                 Mat4MulVecfl(ob->obmat, vec);
1491                                                 VecAddf(centroid, centroid, vec);
1492                                                 DO_MINMAX(vec, min, max);
1493                                                 count++;
1494                                         }
1495                                 }
1496                         }
1497                 }
1498                 else {
1499                         for(base= G.scene->base.first; base; base= base->next) {
1500                                 if(((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
1501                                         VECCOPY(vec, base->object->obmat[3]);
1502                                         VecAddf(centroid, centroid, vec);
1503                                         DO_MINMAX(vec, min, max);
1504                                         count++;
1505                                 }
1506                         }
1507                 }
1508                 if(count) {
1509                         if(G.vd->around==V3D_CENTROID) {
1510                                 VecMulf(centroid, 1.0/(float)count);
1511                                 VECCOPY(curs, centroid);
1512                         }
1513                         else {
1514                                 curs[0]= (min[0]+max[0])/2;
1515                                 curs[1]= (min[1]+max[1])/2;
1516                                 curs[2]= (min[2]+max[2])/2;
1517                         }
1518                 }
1519         }
1520         allqueue(REDRAWVIEW3D, 0);
1521 }
1522
1523 void snap_curs_to_active()
1524 {
1525         float *curs;
1526         curs = give_cursor();
1527
1528         if (G.obedit)
1529         {
1530                 if (G.obedit->type == OB_MESH)
1531                 {
1532                         /* check active */
1533                         EditSelection ese;
1534                         if (EM_get_actSelection(&ese)) {
1535                                 EM_editselection_center(curs, &ese);
1536                         }
1537                         
1538                         Mat4MulVecfl(G.obedit->obmat, curs);
1539                 }
1540         }
1541         else
1542         {
1543                 if (BASACT)
1544                 {
1545                         VECCOPY(curs, BASACT->object->obmat[3]);
1546                 }
1547         }
1548         allqueue(REDRAWVIEW3D, 0);
1549 }
1550
1551 static void snap_curs_to_firstsel()
1552 {
1553         TransVert *tv;
1554         Base *base;
1555         float *curs, bmat[3][3], vec[3], min[3], max[3], centroid[3];
1556         int count;
1557
1558         curs= give_cursor();
1559
1560         count= 0;
1561         INIT_MINMAX(min, max);
1562         centroid[0]= centroid[1]= centroid[2]= 0.0;
1563
1564         if(G.obedit) {
1565                 tottrans=0;
1566                 
1567                 if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) 
1568                         make_trans_verts(bmat[0], bmat[1], 0);
1569                 if(tottrans==0) return;
1570                 
1571                 Mat3CpyMat4(bmat, G.obedit->obmat);
1572                 
1573                 tv= transvmain;
1574                 VECCOPY(vec, tv->loc);
1575                         /*Mat3MulVecfl(bmat, vec);
1576                         VecAddf(vec, vec, G.obedit->obmat[3]);
1577                         VecAddf(centroid, centroid, vec);
1578                         DO_MINMAX(vec, min, max);*/
1579                 
1580                 if(G.vd->around==V3D_CENTROID) {
1581                         VecMulf(vec, 1.0/(float)tottrans);
1582                         VECCOPY(curs, vec);
1583                 }
1584                 else {
1585                         curs[0]= vec[0];
1586                         curs[1]= vec[1];
1587                         curs[2]= vec[2];
1588                 }
1589                 MEM_freeN(transvmain);
1590                 transvmain= 0;
1591         }
1592         else {
1593                 base= (G.scene->base.first);
1594                 while(base) {
1595                         if(((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
1596                                 VECCOPY(vec, base->object->obmat[3]);
1597                                 VecAddf(centroid, centroid, vec);
1598                                 DO_MINMAX(vec, min, max);
1599                                 count++;
1600                         }
1601                         base= base->next;
1602                 }
1603                 if(count) {
1604                         if(G.vd->around==V3D_CENTROID) {
1605                                 VecMulf(centroid, 1.0/(float)count);
1606                                 VECCOPY(curs, centroid);
1607                         }
1608                         else {
1609                                 curs[0]= (min[0]+max[0])/2;
1610                                 curs[1]= (min[1]+max[1])/2;
1611                                 curs[2]= (min[2]+max[2])/2;
1612                         }
1613                 }
1614         }
1615         allqueue(REDRAWVIEW3D, 0);
1616 }
1617
1618 void snap_to_center()
1619 {
1620         extern float originmat[3][3];
1621         TransVert *tv;
1622         Base *base;
1623         Object *ob;
1624         float snaploc[3], imat[3][3], bmat[3][3], vec[3], min[3], max[3], centroid[3];
1625         int count, a;
1626
1627         /*calculate the snaplocation (centerpoint) */
1628         count= 0;
1629         INIT_MINMAX(min, max);
1630         centroid[0]= centroid[1]= centroid[2]= 0.0f;
1631         snaploc[0]= snaploc[1]= snaploc[2]= 0.0f;
1632
1633         if(G.obedit) {
1634                 tottrans= 0;
1635                 
1636                 if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) 
1637                         make_trans_verts(bmat[0], bmat[1], 0);
1638                 if(tottrans==0) return;
1639                 
1640                 Mat3CpyMat4(bmat, G.obedit->obmat);
1641                 Mat3Inv(imat, bmat);
1642                 
1643                 tv= transvmain;
1644                 for(a=0; a<tottrans; a++, tv++) {
1645                         VECCOPY(vec, tv->loc);
1646                         Mat3MulVecfl(bmat, vec);
1647                         VecAddf(vec, vec, G.obedit->obmat[3]);
1648                         VecAddf(centroid, centroid, vec);
1649                         DO_MINMAX(vec, min, max);
1650                 }
1651                 
1652                 if(G.vd->around==V3D_CENTROID) {
1653                         VecMulf(centroid, 1.0/(float)tottrans);
1654                         VECCOPY(snaploc, centroid);
1655                 }
1656                 else {
1657                         snaploc[0]= (min[0]+max[0])/2;
1658                         snaploc[1]= (min[1]+max[1])/2;
1659                         snaploc[2]= (min[2]+max[2])/2;
1660                 }
1661                 
1662                 MEM_freeN(transvmain);
1663                 transvmain= 0;
1664         }
1665         else {
1666                 base= (G.scene->base.first);
1667                 while(base) {
1668                         if(((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
1669                                 ob= base->object;
1670                                 if(ob->flag & OB_POSEMODE) {
1671                                         bPoseChannel *pchan;
1672                                         bArmature *arm= ob->data;
1673                                         
1674                                         for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
1675                                                 if(pchan->bone->flag & BONE_SELECTED) {
1676                                                         if(pchan->bone->layer & arm->layer) {
1677                                                                 VECCOPY(vec, pchan->pose_mat[3]);
1678                                                                 VecAddf(centroid, centroid, vec);
1679                                                                 DO_MINMAX(vec, min, max);
1680                                                                 count++;
1681                                                         }
1682                                                 }
1683                                         }
1684                                 }
1685                                 else {
1686                                         /* not armature bones (i.e. objects) */
1687                                         VECCOPY(vec, base->object->obmat[3]);
1688                                         VecAddf(centroid, centroid, vec);
1689                                         DO_MINMAX(vec, min, max);
1690                                         count++;
1691                                 }
1692                         }
1693                         base= base->next;
1694                 }
1695                 if(count) {
1696                         if(G.vd->around==V3D_CENTROID) {
1697                                 VecMulf(centroid, 1.0/(float)count);
1698                                 VECCOPY(snaploc, centroid);
1699                         }
1700                         else {
1701                                 snaploc[0]= (min[0]+max[0])/2;
1702                                 snaploc[1]= (min[1]+max[1])/2;
1703                                 snaploc[2]= (min[2]+max[2])/2;
1704                         }
1705                 }
1706         }
1707
1708         /* Snap the selection to the snaplocation (duh!) */
1709         if(G.obedit) {
1710                 tottrans= 0;
1711                 
1712                 if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) 
1713                         make_trans_verts(bmat[0], bmat[1], 0);
1714                 if(tottrans==0) return;
1715                 
1716                 Mat3CpyMat4(bmat, G.obedit->obmat);
1717                 Mat3Inv(imat, bmat);
1718                 
1719                 tv= transvmain;
1720                 for(a=0; a<tottrans; a++, tv++) {
1721                         vec[0]= snaploc[0]-G.obedit->obmat[3][0];
1722                         vec[1]= snaploc[1]-G.obedit->obmat[3][1];
1723                         vec[2]= snaploc[2]-G.obedit->obmat[3][2];
1724                         
1725                         Mat3MulVecfl(imat, vec);
1726                         VECCOPY(tv->loc, vec);
1727                 }
1728                 
1729                 special_transvert_update();
1730                 
1731                 MEM_freeN(transvmain);
1732                 transvmain= 0;
1733                 
1734                 allqueue(REDRAWVIEW3D, 0);
1735                 return;
1736         }
1737
1738         base= (G.scene->base.first);
1739         while(base) {
1740                 if( ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) && ((base)->object->id.lib==0))) {
1741                         ob= base->object;
1742                         if(ob->flag & OB_POSEMODE) {
1743                                 bPoseChannel *pchan;
1744                                 bArmature *arm= ob->data;
1745                                 
1746                                 for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
1747                                         if(pchan->bone->flag & BONE_SELECTED) {
1748                                                 if(pchan->bone->layer & arm->layer) {
1749                                                         if((pchan->bone->flag & BONE_CONNECTED)==0) { 
1750                                                                 /* get location of cursor in bone-space */
1751                                                                 armature_loc_pose_to_bone(pchan, snaploc, vec);
1752                                                                 
1753                                                                 /* calculate new position */
1754                                                                 VECCOPY(pchan->loc, vec);
1755                                                         }
1756                                                         /* if the bone has a parent and is connected to the parent, 
1757                                                          * don't do anything - will break chain unless we do auto-ik. 
1758                                                          */
1759                                                 }
1760                                         }
1761                                 }
1762                                 
1763                                 /* auto-keyframing */
1764                                 ob->pose->flag |= POSE_DO_UNLOCK;
1765                                 autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
1766                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1767                         }
1768                         else {
1769                                 ob->recalc |= OB_RECALC_OB;
1770                                 
1771                                 vec[0]= -ob->obmat[3][0] + snaploc[0];
1772                                 vec[1]= -ob->obmat[3][1] + snaploc[1];
1773                                 vec[2]= -ob->obmat[3][2] + snaploc[2];
1774                                 
1775                                 if(ob->parent) {
1776                                         where_is_object(ob);
1777                                         
1778                                         Mat3Inv(imat, originmat);
1779                                         Mat3MulVecfl(imat, vec);
1780                                         ob->loc[0]+= vec[0];
1781                                         ob->loc[1]+= vec[1];
1782                                         ob->loc[2]+= vec[2];
1783                                 }
1784                                 else {
1785                                         ob->loc[0]+= vec[0];
1786                                         ob->loc[1]+= vec[1];
1787                                         ob->loc[2]+= vec[2];
1788                                 }
1789 #ifdef WITH_VERSE
1790                                 if(ob->vnode) b_verse_send_transformation(ob);
1791 #endif
1792                                 
1793                                 /* auto-keyframing */
1794                                 autokeyframe_ob_cb_func(ob, TFM_TRANSLATION);
1795                         }
1796                 }
1797                 
1798                 base= base->next;
1799         }
1800         DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0);
1801         allqueue(REDRAWVIEW3D, 0);
1802 }
1803
1804
1805 void snapmenu()
1806 {
1807         short event;
1808
1809         event = pupmenu("Snap %t|Selection -> Grid%x1|Selection -> Cursor%x2|Selection -> Center%x3|%l|Cursor -> Selection%x4|Cursor -> Grid%x5|Cursor -> Active%x6");
1810
1811         switch (event) {
1812                 case 1: /*Selection to grid*/
1813                     snap_sel_to_grid();
1814                         BIF_undo_push("Snap selection to grid");
1815                     break;
1816                 case 2: /*Selection to cursor*/
1817                     snap_sel_to_curs();
1818                         BIF_undo_push("Snap selection to cursor");
1819                     break;
1820                 case 3: /*Selection to center of selection*/
1821                     snap_to_center();
1822                         BIF_undo_push("Snap selection to center");
1823                     break;
1824                 case 4: /*Cursor to selection*/
1825                     snap_curs_to_sel();
1826                     break;
1827                 case 5: /*Cursor to grid*/
1828                     snap_curs_to_grid();
1829                     break;
1830                 case 6: /*Cursor to Active*/
1831                     snap_curs_to_active();
1832                         BIF_undo_push("Snap selection to center");
1833                     break;
1834         }
1835 }
1836
1837 void alignmenu()
1838 {
1839         short val;
1840         char *str_menu = BIF_menustringTransformOrientation("Align");
1841         val= pupmenu(str_menu);
1842         MEM_freeN(str_menu);
1843
1844         if (val >= 0)
1845         {
1846                 short old_val = G.vd->twmode; 
1847                 G.vd->twmode = val;
1848                 initTransform(TFM_ALIGN, CTX_NO_PET|CTX_AUTOCONFIRM);
1849                 Transform();
1850                 G.vd->twmode = old_val;
1851         }
1852 }
1853
1854 #define MERGELIMIT 0.001
1855 void mergemenu(void)
1856 {       
1857
1858         short event;
1859         int remCount = 0;
1860         
1861         if(G.scene->selectmode & SCE_SELECT_VERTEX)
1862                 if(G.editMesh->selected.first && G.editMesh->selected.last && 
1863                         ((EditSelection*)G.editMesh->selected.first)->type == EDITVERT && ((EditSelection*)G.editMesh->selected.last)->type == EDITVERT) 
1864                                 event = pupmenu("Merge %t|At First %x6|At Last%x1|At Center%x3|At Cursor%x4|Collapse%x2");
1865                 else if (G.editMesh->selected.first && ((EditSelection*)G.editMesh->selected.first)->type == EDITVERT) 
1866                         event = pupmenu("Merge %t|At First %x6|At Center%x3|At Cursor%x4|Collapse%x2");
1867                 else if (G.editMesh->selected.last && ((EditSelection*)G.editMesh->selected.last)->type == EDITVERT) 
1868                         event = pupmenu("Merge %t|At Last %x1|At Center%x3|At Cursor%x4|Collapse%x2");
1869                 else event = pupmenu("Merge %t|At Center%x3|At Cursor%x4|Collapse%x2");
1870         else event = pupmenu("Merge %t|At Center%x3|At Cursor%x4|Collapse%x2");
1871         switch (event)
1872         {
1873                 case -1:
1874                         return;
1875                 case 3:
1876                         if(G.qual & LR_CTRLKEY) remCount = merge_target(0,1);
1877                         else remCount = merge_target(0,0);
1878                         BIF_undo_push("Merge at center");
1879                         break;
1880                 case 4:
1881                         if(G.qual & LR_CTRLKEY) remCount = merge_target(1,1);
1882                         else remCount = merge_target(1,0);
1883                         BIF_undo_push("Merge at cursor");
1884                         break;
1885                 case 1:
1886                         if(G.qual & LR_CTRLKEY) remCount = merge_firstlast(0,1);
1887                         else remCount = merge_firstlast(0,0);
1888                         BIF_undo_push("Merge at last selected");
1889                         break;
1890                 case 6:
1891                         if(G.qual & LR_CTRLKEY) remCount = merge_firstlast(1,1);
1892                         else remCount = merge_firstlast(1,0);
1893                         BIF_undo_push("Merge at first selected");
1894                         break;
1895                 case 2:
1896                         remCount = collapseEdges();
1897                         BIF_undo_push("Collapse");
1898                         break;
1899         }
1900         notice("Removed %d Vertices", remCount);
1901         allqueue(REDRAWVIEW3D, 0);
1902         countall();
1903 }
1904 #undef MERGELIMIT
1905
1906
1907 void delete_context_selected(void) 
1908 {
1909         if(G.obedit) {
1910                 if(G.obedit->type==OB_MESH) delete_mesh();
1911                 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) delNurb();
1912                 else if(G.obedit->type==OB_MBALL) delete_mball();
1913                 else if (G.obedit->type==OB_ARMATURE) delete_armature();
1914         }
1915         else if(G.f & G_PARTICLEEDIT){
1916                 PE_delete_particle();
1917         }
1918         else delete_obj(0);
1919 }
1920
1921 void duplicate_context_selected(void) 
1922 {
1923         if(G.obedit) {
1924                 if(G.obedit->type==OB_MESH) adduplicate_mesh();
1925                 else if(G.obedit->type==OB_ARMATURE) adduplicate_armature();
1926                 else if(G.obedit->type==OB_MBALL) adduplicate_mball();
1927                 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) adduplicate_nurb();
1928         }
1929         else if(G.f & G_PARTICLEEDIT);
1930         else
1931                 adduplicate(0, U.dupflag);
1932 }
1933
1934 void toggle_shading(void) 
1935 {
1936         if(G.qual & LR_SHIFTKEY) {
1937                 if(G.qual & LR_ALTKEY) {
1938                         reshadeall_displist();
1939                         G.vd->drawtype= OB_SHADED;
1940                 }
1941                 else {
1942                         if(G.vd->drawtype== OB_SHADED) G.vd->drawtype= OB_WIRE;
1943                         else G.vd->drawtype= OB_SHADED;
1944                 }
1945         }
1946         else if(G.qual & LR_ALTKEY) {
1947                 if(G.vd->drawtype== OB_TEXTURE) G.vd->drawtype= OB_SOLID;
1948                 else G.vd->drawtype= OB_TEXTURE;
1949         }
1950         else {
1951                 if(G.vd->drawtype==OB_SOLID || G.vd->drawtype==OB_SHADED) G.vd->drawtype= OB_WIRE;
1952                 else G.vd->drawtype= OB_SOLID;
1953         }
1954         
1955         if(G.vd->drawtype != OB_WIRE && G.vd->depths) {
1956                 G.vd->depths->damaged= 1;
1957         }
1958 }
1959
1960 int minmax_verts(float *min, float *max)
1961 {
1962         TransVert *tv;
1963         float centroid[3], vec[3], bmat[3][3];
1964         int a;
1965
1966         tottrans=0;
1967         if ELEM5(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE) 
1968                 make_trans_verts(bmat[0], bmat[1], 2);
1969         if(tottrans==0) return 0;
1970
1971         Mat3CpyMat4(bmat, G.obedit->obmat);
1972         
1973         tv= transvmain;
1974         for(a=0; a<tottrans; a++, tv++) {               
1975                 VECCOPY(vec, tv->loc);
1976                 Mat3MulVecfl(bmat, vec);
1977                 VecAddf(vec, vec, G.obedit->obmat[3]);
1978                 VecAddf(centroid, centroid, vec);
1979                 DO_MINMAX(vec, min, max);               
1980         }
1981         
1982         MEM_freeN(transvmain);
1983         transvmain= 0;
1984         return 1;
1985 }
1986