4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
43 #include "MEM_guardedalloc.h"
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"
70 #include "BKE_action.h"
71 #include "BKE_armature.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"
79 #include "BKE_lattice.h"
81 #include "BKE_modifier.h"
82 #include "BKE_object.h"
83 #include "BKE_particle.h"
84 #include "BKE_utildefines.h"
87 #include "BKE_verse.h"
90 #include "BIF_editmesh.h"
91 #include "BIF_editview.h"
92 #include "BIF_editarmature.h"
93 #include "BIF_editparticle.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 #include "BIF_sketch.h"
105 #include "BIF_verse.h"
108 #include "BSE_edit.h"
109 #include "BSE_drawipo.h"
110 #include "BSE_drawview.h"
111 #include "BSE_trans_types.h"
112 #include "BSE_view.h"
114 #include "BDR_editobject.h"
115 #include "BDR_editmball.h"
116 #include "BDR_editcurve.h"
120 #include "mydevice.h"
122 /*#include "armature.h"*/
123 /* #include "edit.h" */
125 #include "transform.h"
128 #include "BIF_editarmature.h"
132 /* circle selection callback */
133 typedef void (*select_CBfunc)(short selecting, Object *editobj, short *mval, float rad);
135 extern void obedit_selectionCB(short selecting, Object *editobj,
136 short *mval, float rad);
137 extern void uvedit_selectionCB(short selecting, Object *editobj,
138 short *mval, float rad);
140 static void circle_selectCB(select_CBfunc func);
143 /* flag==2 only border, flag==3 cross+border
144 flag==5 cross + border + start&end frame
146 int get_border(rcti *rect, short flag)
148 float dvec[4], fac1, fac2;
150 unsigned short event= 0;
151 short mval[2], mvalo[4], val, x1, y1;
154 mywinset(G.curscreen->mainwin);
156 /* slightly larger, 1 pixel at the edge */
157 glReadBuffer(GL_FRONT);
158 glDrawBuffer(GL_FRONT);
160 /* removed my_get_frontbuffer, this crashes when it gets a part outside the screen */
161 /* solved it with just a redraw! */
163 mywinset(curarea->win);
165 glDrawBuffer(GL_FRONT);
167 initgrabz(0.0, 0.0, 0.0);
170 getmouseco_areawin(mvalo);
172 /* draws the selection initial cross */
173 sdrawXORline4(0, 0, mvalo[1], curarea->winx, mvalo[1]);
174 sdrawXORline4(1, mvalo[0], 0, mvalo[0], curarea->winy);
179 /* selection loop while mouse pressed */
180 getmouseco_areawin(mval);
182 if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
185 sdrawXORline4(0, 0, mval[1], curarea->winx, mval[1]);
186 sdrawXORline4(1, mval[0], 0, mval[0], curarea->winy);
192 event= extern_qread(&val);
196 /* for when a renderwindow is open, and a mouse cursor activates it */
198 mywinset(curarea->win);
205 else if(event==BKEY) {
206 /* b has been pressed twice: proceed with circle select */
210 else if(event==LEFTMOUSE) break;
211 else if(event==MIDDLEMOUSE) break;
212 else if(event==RIGHTMOUSE) break;
214 else PIL_sleep_ms(10);
216 } /* end while (TRUE) */
218 /* erase XORed lines */
219 sdrawXORline4(-1, 0, 0, 0, 0);
221 else getmouseco_areawin(mval);
228 getmouseco_areawin(mvalo);
230 sdrawXORline4(0, x1, y1, x1, mvalo[1]);
231 sdrawXORline4(1, x1, mvalo[1], mvalo[0], mvalo[1]);
232 sdrawXORline4(2, mvalo[0], mvalo[1], mvalo[0], y1);
233 sdrawXORline4(3, mvalo[0], y1, x1, y1);
237 getmouseco_areawin(mval);
238 if(mvalo[0]!=mval[0] || mvalo[1]!=mval[1]) {
240 sdrawXORline4(0, x1, y1, x1, mval[1]);
241 sdrawXORline4(1, x1, mval[1], mval[0], mval[1]);
242 sdrawXORline4(2, mval[0], mval[1], mval[0], y1);
243 sdrawXORline4(3, mval[0], y1, x1, y1);
245 /* draw size information in corner */
246 if(curarea->spacetype==SPACE_VIEW3D) {
247 BIF_ThemeColor(TH_BACK);
248 glRecti(10, 25, 250, 40);
250 if(G.vd->persp==V3D_ORTHO) {
251 window_to_3d(dvec, mvalo[0]-x1, mvalo[1]-y1);
253 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]));
254 glColor3f(0.0, 0.0, 0.0);
255 glRasterPos2i(15, 27);
256 BMF_DrawString(G.fonts, str);
257 glColor3f(0.7, 0.7, 0.7);
258 glRasterPos2i(16, 28);
259 BMF_DrawString(G.fonts, str);
261 else if(G.vd->persp==V3D_CAMOB) {
264 calc_viewborder(G.vd, &vb);
266 fac1= (mvalo[0]-x1)/( (float) (vb.xmax-vb.xmin) );
267 fac1*= 0.01*G.scene->r.size*G.scene->r.xsch;
269 fac2= (mvalo[1]-y1)/( (float) (vb.ymax-vb.ymin) );
270 fac2*= 0.01*G.scene->r.size*G.scene->r.ysch;
272 sprintf(str, "X %.1f Y %.1f Dia %.1f", fabs(fac1), fabs(fac2), sqrt(fac1*fac1 + fac2*fac2) );
273 glColor3f(0.0, 0.0, 0.0);
274 glRasterPos2i(15, 27);
275 BMF_DrawString(G.fonts, str);
276 glColor3f(0.7, 0.7, 0.7);
277 glRasterPos2i(16, 28);
278 BMF_DrawString(G.fonts, str);
281 else if(curarea->spacetype==SPACE_IPO) {
282 SpaceIpo *sipo= curarea->spacedata.first;
284 BIF_ThemeColor(TH_BACK);
285 glRecti(20, 30, 170, 40);
289 areamouseco_to_ipoco(&sipo->v2d, mval, dvec, dvec+1);
290 areamouseco_to_ipoco(&sipo->v2d, mvalo+2, dvec+2, dvec+3);
293 /* setting preview range */
294 if (dvec[0] < dvec[2])
295 sprintf(str, "Preview Range: %d to %d", (int)dvec[0], (int)dvec[2]);
297 sprintf(str, "Preview Range: %d to %d", (int)dvec[2], (int)dvec[0]);
300 sprintf(str, "Time: %.4f Y %.4f", dvec[0]-dvec[2], dvec[1]-dvec[3]);
302 BIF_ThemeColor(TH_BACK);
303 glRecti(14, 24, 165, 38);
305 glColor3f(0.0, 0.0, 0.0);
306 glRasterPos2i(15, 27);
307 BMF_DrawString(G.fonts, str);
308 glColor3f(0.8, 0.8, 0.8);
309 glRasterPos2i(16, 28);
310 BMF_DrawString(G.fonts, str);
312 else if ((ELEM3(curarea->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_TIME)) && flag==5) {
313 /* only while setting preview range */
316 switch (curarea->spacetype)
320 SpaceAction *saaction= curarea->spacedata.first;
326 SpaceNla *snla= curarea->spacedata.first;
337 areamouseco_to_ipoco(v2d, mval, dvec, dvec+1);
338 areamouseco_to_ipoco(v2d, mvalo+2, dvec+2, dvec+3);
340 if (dvec[0] < dvec[2])
341 sprintf(str, "Preview Range: %d to %d", (int)dvec[0], (int)dvec[2]);
343 sprintf(str, "Preview Range: %d to %d", (int)dvec[2], (int)dvec[0]);
345 BIF_ThemeColor(TH_BACK);
346 glRecti(14, 24, 165, 38);
348 glColor3f(0.0, 0.0, 0.0);
349 glRasterPos2i(15, 27);
350 BMF_DrawString(G.fonts, str);
351 glColor3f(0.8, 0.8, 0.8);
352 glRasterPos2i(16, 28);
353 BMF_DrawString(G.fonts, str);
362 event= extern_qread(&val);
364 if(event && val==0) {
365 /* still because of the renderwindow... */
367 mywinset(curarea->win);
374 else if(event==LEFTMOUSE) break;
375 else if(event==MIDDLEMOUSE) break;
376 else if(event==RIGHTMOUSE) break;
379 } /* end while (TRUE) */
380 sdrawXORline4(-1, 0, 0, 0, 0);
390 if(rect->xmin>rect->xmax) SWAP(int, rect->xmin, rect->xmax);
391 if(rect->ymin>rect->ymax) SWAP(int, rect->ymin, rect->ymax);
393 if(rect->xmin==rect->xmax) retval= 0;
394 if(rect->ymin==rect->ymax) retval= 0;
401 if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_IPO) {
402 scrarea_queue_winredraw(curarea);
404 else if ELEM3(curarea->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_TIME) {
405 scrarea_queue_winredraw(curarea); // only really needed for
410 glReadBuffer(GL_BACK);
411 glDrawBuffer(GL_BACK);
415 /* pressed B again ? -> brush select */
418 switch (curarea->spacetype) {
421 if ELEM4(G.obedit->type, OB_MESH, OB_CURVE, OB_SURF, OB_LATTICE) {
422 circle_selectCB(&obedit_selectionCB);
425 else if (FACESEL_PAINT_TEST) {
426 circle_selectCB(&obedit_selectionCB);
428 else if (G.f&G_PARTICLEEDIT) {
429 circle_selectCB(&PE_selectionCB);
433 case SPACE_IMAGE: // brush select in UV editor
434 circle_selectCB(&uvedit_selectionCB);
435 // this is a hack; we return 0 that the caller from get_border
436 // doesn't execute the selection code for border select..
443 void draw_sel_circle(short *mval, short *mvalo, float rad, float rado, int selecting)
445 static short no_mvalo=0;
447 if(mval==NULL && mvalo==NULL) { /* signal */
453 glReadBuffer(GL_FRONT);
454 glDrawBuffer(GL_FRONT);
458 if(mvalo && no_mvalo==0) {
459 fdrawXORcirc(mvalo[0], mvalo[1], rado);
463 fdrawXORcirc(mval[0], mval[1], rad);
469 glDrawBuffer(GL_BACK);
470 glReadBuffer(GL_BACK);
475 /** This function does the same as editview.c:circle_select(),
476 * but the selection actions are defined by a callback, making
477 * it (hopefully) reusable for other windows than the 3D view.
480 static void circle_selectCB(select_CBfunc callback)
482 static float rad= 40.0;
486 unsigned short event;
487 short mvalo[2], mval[2], val;
491 if(G.obedit) obj = G.obedit;
494 mywinset(curarea->win);
496 getmouseco_areawin(mvalo);
497 mval[0]= mvalo[0]; mval[1]= mvalo[1];
499 draw_sel_circle(mval, NULL, rad, 0.0, selecting); // draws frontbuffer, but sets backbuf again
503 if(mval[0]!=mvalo[0] || mval[1]!=mvalo[1] || rado!=rad || firsttime) {
507 callback(selecting, obj, mval, rad);
510 draw_sel_circle(mval, mvalo, rad, rado, selecting);
519 event= extern_qread(&val);
522 /* for when another window is open and a mouse cursor activates it */
523 if(event!=MOUSEY && event!=MOUSEX) mywinset(curarea->win);
525 getmouseco_areawin(mval); // important to do here, trust events!
531 if(val) selecting= event;
540 if(val) if(rad<200.0) rad*= 1.2;
546 if(val) if(rad>5.0) rad/= 1.2;
549 case ESCKEY: case SPACEKEY: case RIGHTMOUSE: case INPUTCHANGE:
550 case GKEY: case SKEY: case RKEY: case XKEY: case EKEY: case TABKEY:
565 draw_sel_circle(NULL, mvalo, 0, rad, 1);
566 BIF_undo_push("Circle Select");
568 allqueue(REDRAWINFO, 0);
571 static void count_object(Object *ob, int sel, int totob)
583 int totvert, totedge, totface;
584 dm = mesh_get_derived_final(ob, get_viewedit_datamask());
585 totvert = dm->getNumVerts(dm);
586 totedge = dm->getNumEdges(dm);
587 totface = dm->getNumFaces(dm);
589 G.totvert+= totvert*totob;
590 G.totedge+= totedge*totob;
591 G.totface+= totface*totob;
593 G.totvertsel+= totvert;
594 G.totfacesel+= totface;
609 count_displist( &cu->disp, &tot, &totf);
620 count_displist( &ob->disp, &tot, &totf);
634 /* countall does statistics */
635 /* is called on most actions, like select/add/delete/layermove */
638 extern ListBase editNurb;
646 struct EditBone *ebo;
649 G.totvert= G.totvertsel= G.totedge= G.totedgesel= G.totfacesel= G.totface= G.totobj=
650 G.totmesh= G.totlamp= G.totcurve= G.totobjsel= G.totbone= G.totbonesel= 0;
654 if(G.obedit->type==OB_MESH) {
655 EditMesh *em = G.editMesh;
660 for(eve= em->verts.first; eve; eve= eve->next) {
662 if(eve->f & SELECT) G.totvertsel++;
664 for(eed= em->edges.first; eed; eed= eed->next) {
666 if(eed->f & SELECT) G.totedgesel++;
668 for(efa= em->faces.first; efa; efa= efa->next) {
670 if(efa->f & SELECT) G.totfacesel++;
673 EM_validate_selections();
675 else if (G.obedit->type==OB_ARMATURE){
676 for (ebo=G.edbo.first;ebo;ebo=ebo->next){
679 /* Sync selection to parent for connected children */
680 if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
682 if (ebo->parent->flag & BONE_TIPSEL)
683 ebo->flag |= BONE_ROOTSEL;
685 ebo->flag &= ~BONE_ROOTSEL;
688 if (ebo->flag & BONE_TIPSEL)
690 if (ebo->flag & BONE_ROOTSEL)
693 if ((ebo->flag & BONE_TIPSEL) && (ebo->flag & BONE_ROOTSEL))
694 ebo->flag |= BONE_SELECTED;
696 ebo->flag &= ~BONE_SELECTED;
698 if(ebo->flag & BONE_SELECTED) G.totbonesel++;
700 // If this is a connected child and it's parent is being moved, remove our root
701 if ((ebo->flag & BONE_CONNECTED)&& (ebo->flag & BONE_ROOTSEL) && ebo->parent && (ebo->parent->flag & BONE_TIPSEL)){
708 else if ELEM3(G.obedit->type, OB_CURVE, OB_SURF, OB_FONT) {
711 if((nu->type & 7)==CU_BEZIER) {
716 if(bezt->f1) G.totvertsel++;
717 if(bezt->f2) G.totvertsel++;
718 if(bezt->f3) G.totvertsel++;
724 a= nu->pntsu*nu->pntsv;
727 if(bp->f1 & SELECT) G.totvertsel++;
734 else if(G.obedit->type==OB_MBALL) {
736 extern ListBase editelems; /* go away ! */
741 if(ml->flag & SELECT) G.totvertsel++;
745 else if(G.obedit->type==OB_LATTICE) {
748 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
751 if(bp->f1 & SELECT) G.totvertsel++;
756 allqueue(REDRAWINFO, 1); /* 1, because header->win==0! */
759 else if(ob && (ob->flag & OB_POSEMODE)) {
761 bArmature *arm= ob->data;
763 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
765 if(pchan->bone && (pchan->bone->flag & BONE_SELECTED))
766 if(pchan->bone->layer & arm->layer)
770 allqueue(REDRAWINFO, 1); /* 1, because header->win==0! */
773 else if(FACESEL_PAINT_TEST) {
774 me= get_mesh((G.scene->basact) ? (G.scene->basact->object) : 0);
776 G.totface= me->totface;
777 G.totvert= me->totvert;
779 allqueue(REDRAWINFO, 1); /* 1, because header->win==0! */
783 if(G.scene==NULL) return;
785 base= (G.scene->base.first);
787 if(G.scene->lay & base->lay) {
788 ob= base->object; /* warning, ob not is obact anymore */
790 if(base->flag & SELECT) G.totobjsel++;
792 if(ob->transflag & OB_DUPLIPARTS) {
793 ParticleSystem *psys;
794 ParticleSettings *part;
796 for(psys=ob->particlesystem.first; psys; psys=psys->next){
799 if(part->draw_as==PART_DRAW_OB && part->dup_ob){
800 int tot=count_particles(psys);
801 count_object(part->dup_ob, 0, tot);
803 else if(part->draw_as==PART_DRAW_GR && part->dup_group){
805 int tot, totgroup=0, cur=0;
807 go= part->dup_group->gobject.first;
812 go= part->dup_group->gobject.first;
814 tot=count_particles_mod(psys,totgroup,cur);
815 count_object(go->ob, 0, tot);
822 count_object(ob, base->flag & SELECT, 1);
825 else if(ob->parent && (ob->parent->transflag & (OB_DUPLIVERTS|OB_DUPLIFACES))) {
826 int tot= count_duplilist(ob->parent);
828 count_object(ob, base->flag & SELECT, tot);
830 else if(ob->transflag & OB_DUPLIFRAMES) {
831 int tot= count_duplilist(ob);
833 count_object(ob, base->flag & SELECT, tot);
835 else if((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
836 int tot= count_duplilist(ob);
838 count_object(ob, base->flag & SELECT, tot);
841 count_object(ob, base->flag & SELECT, 1);
847 allqueue(REDRAWINFO, 1); /* 1, because header->win==0! */
850 /* ************************************************** */
851 /* ********************* old transform stuff ******** */
852 /* ************************************************** */
854 static TransVert *transvmain=NULL;
855 static int tottrans= 0;
857 /* copied from editobject.c, now uses (almost) proper depgraph */
858 static void special_transvert_update(void)
863 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
865 if(G.obedit->type==OB_MESH) {
867 if(G.editMesh->vnode)
868 sync_all_verseverts_with_editverts((VNode*)G.editMesh->vnode);
870 recalc_editnormals(); // does face centers too
872 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
873 extern ListBase editNurb;
874 Nurb *nu= editNurb.first;
877 testhandlesNurb(nu); /* test for bezier too */
881 else if(G.obedit->type==OB_ARMATURE){
882 bArmature *arm= G.obedit->data;
884 TransVert *tv= transvmain;
887 /* Ensure all bone tails are correctly adjusted */
888 for (ebo=G.edbo.first; ebo; ebo=ebo->next) {
889 /* adjust tip if both ends selected */
890 if ((ebo->flag & BONE_ROOTSEL) && (ebo->flag & BONE_TIPSEL)) {
894 VecSubf(diffvec, tv->loc, tv->oldloc);
895 VecAddf(ebo->tail, ebo->tail, diffvec);
898 if (a<tottrans) tv++;
903 /* Ensure all bones are correctly adjusted */
904 for (ebo=G.edbo.first; ebo; ebo=ebo->next) {
905 if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
906 /* If this bone has a parent tip that has been moved */
907 if (ebo->parent->flag & BONE_TIPSEL){
908 VECCOPY (ebo->head, ebo->parent->tail);
910 /* If this bone has a parent tip that has NOT been moved */
912 VECCOPY (ebo->parent->tail, ebo->head);
916 if(arm->flag & ARM_MIRROR_EDIT)
917 transform_armature_mirror_update();
919 else if(G.obedit->type==OB_LATTICE) {
920 if(editLatt->flag & LT_OUTSIDE) outside_lattice(editLatt);
925 /* copied from editobject.c, needs to be replaced with new transform code still */
926 /* mode: 1 = proportional, 2 = all joints (for bones only) */
927 static void make_trans_verts(float *min, float *max, int mode)
929 extern ListBase editNurb;
930 EditMesh *em = G.editMesh;
938 float total, center[3], centroid[3];
941 tottrans= 0; // global!
943 INIT_MINMAX(min, max);
944 centroid[0]=centroid[1]=centroid[2]= 0.0;
946 /* note for transform refactor: dont rely on countall anymore... its ancient */
947 /* I skip it for editmesh now (ton) */
948 if(G.obedit->type!=OB_MESH) {
950 if(mode) tottrans= G.totvert;
951 else tottrans= G.totvertsel;
953 if(G.totvertsel==0) {
957 tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
960 /* we count again because of hide (old, not for mesh!) */
963 if(G.obedit->type==OB_MESH) {
966 // transform now requires awareness for select mode, so we tag the f1 flags in verts
968 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
969 for(eve= em->verts.first; eve; eve= eve->next) {
970 if(eve->h==0 && (eve->f & SELECT)) {
977 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
979 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
980 for(eed= em->edges.first; eed; eed= eed->next) {
981 if(eed->h==0 && (eed->f & SELECT)) eed->v1->f1= eed->v2->f1= SELECT;
983 for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
987 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
988 for(efa= em->faces.first; efa; efa= efa->next) {
989 if(efa->h==0 && (efa->f & SELECT)) {
990 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
991 if(efa->v4) efa->v4->f1= SELECT;
994 for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
997 /* proportional edit exception... */
998 if((mode & 1) && tottrans) {
999 for(eve= em->verts.first; eve; eve= eve->next) {
1005 if(proptrans>tottrans) tottrans= proptrans;
1008 /* and now make transverts */
1010 tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
1012 for(eve= em->verts.first; eve; eve= eve->next) {
1014 VECCOPY(tv->oldloc, eve->co);
1016 if(eve->no[0]!=0.0 || eve->no[1]!=0.0 ||eve->no[2]!=0.0)
1017 tv->nor= eve->no; // note this is a hackish signal (ton)
1018 tv->flag= eve->f1 & SELECT;
1024 else if (G.obedit->type==OB_ARMATURE){
1025 bArmature *arm= G.obedit->data;
1027 for (ebo=G.edbo.first;ebo;ebo=ebo->next){
1028 if(ebo->layer & arm->layer) {
1029 short tipsel= (ebo->flag & BONE_TIPSEL);
1030 short rootsel= (ebo->flag & BONE_ROOTSEL);
1031 short rootok= (!(ebo->parent && (ebo->flag & BONE_CONNECTED) && ebo->parent->flag & BONE_TIPSEL));
1033 if ((tipsel && rootsel) || (rootsel)) {
1034 /* Don't add the tip (unless mode & 2, for getting all joints),
1035 * otherwise we get zero-length bones as tips will snap to the same
1036 * location as heads.
1039 VECCOPY (tv->oldloc, ebo->head);
1047 if ((mode & 2) && (tipsel)) {
1048 VECCOPY (tv->oldloc, ebo->tail);
1057 VECCOPY (tv->oldloc, ebo->tail);
1067 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
1070 if((nu->type & 7)==CU_BEZIER) {
1075 if((mode & 1) || (bezt->f1 & SELECT)) {
1076 VECCOPY(tv->oldloc, bezt->vec[0]);
1077 tv->loc= bezt->vec[0];
1078 tv->flag= bezt->f1 & SELECT;
1082 if((mode & 1) || (bezt->f2 & SELECT)) {
1083 VECCOPY(tv->oldloc, bezt->vec[1]);
1084 tv->loc= bezt->vec[1];
1085 tv->val= &(bezt->alfa);
1086 tv->oldval= bezt->alfa;
1087 tv->flag= bezt->f2 & SELECT;
1091 if((mode & 1) || (bezt->f3 & SELECT)) {
1092 VECCOPY(tv->oldloc, bezt->vec[2]);
1093 tv->loc= bezt->vec[2];
1094 tv->flag= bezt->f3 & SELECT;
1103 a= nu->pntsu*nu->pntsv;
1107 if((mode & 1) || (bp->f1 & SELECT)) {
1108 VECCOPY(tv->oldloc, bp->vec);
1110 tv->val= &(bp->alfa);
1111 tv->oldval= bp->alfa;
1112 tv->flag= bp->f1 & SELECT;
1123 else if(G.obedit->type==OB_MBALL) {
1124 extern ListBase editelems; /* go away ! */
1125 ml= editelems.first;
1127 if(ml->flag & SELECT) {
1129 VECCOPY(tv->oldloc, tv->loc);
1130 tv->val= &(ml->rad);
1131 tv->oldval= ml->rad;
1139 else if(G.obedit->type==OB_LATTICE) {
1142 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1145 if((mode & 1) || (bp->f1 & SELECT)) {
1147 VECCOPY(tv->oldloc, bp->vec);
1149 tv->flag= bp->f1 & SELECT;
1161 for(a=0; a<tottrans; a++, tv++) {
1162 if(tv->flag & SELECT) {
1163 centroid[0]+= tv->oldloc[0];
1164 centroid[1]+= tv->oldloc[1];
1165 centroid[2]+= tv->oldloc[2];
1167 DO_MINMAX(tv->oldloc, min, max);
1171 centroid[0]/= total;
1172 centroid[1]/= total;
1173 centroid[2]/= total;
1176 center[0]= (min[0]+max[0])/2.0;
1177 center[1]= (min[1]+max[1])/2.0;
1178 center[2]= (min[2]+max[2])/2.0;
1182 void snap_sel_to_grid()
1184 extern float originmat[3][3]; /* object.c */
1188 float gridf, imat[3][3], bmat[3][3], vec[3];
1191 gridf= G.vd->gridview;
1197 if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
1198 make_trans_verts(bmat[0], bmat[1], 0);
1199 if(tottrans==0) return;
1201 Mat3CpyMat4(bmat, G.obedit->obmat);
1202 Mat3Inv(imat, bmat);
1205 for(a=0; a<tottrans; a++, tv++) {
1207 VECCOPY(vec, tv->loc);
1208 Mat3MulVecfl(bmat, vec);
1209 VecAddf(vec, vec, G.obedit->obmat[3]);
1210 vec[0]= G.vd->gridview*floor(.5+ vec[0]/gridf);
1211 vec[1]= G.vd->gridview*floor(.5+ vec[1]/gridf);
1212 vec[2]= G.vd->gridview*floor(.5+ vec[2]/gridf);
1213 VecSubf(vec, vec, G.obedit->obmat[3]);
1215 Mat3MulVecfl(imat, vec);
1216 VECCOPY(tv->loc, vec);
1220 special_transvert_update();
1222 MEM_freeN(transvmain);
1225 allqueue(REDRAWVIEW3D, 0);
1229 base= (G.scene->base.first);
1231 if( ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) && ((base)->object->id.lib==0))) {
1233 if(ob->flag & OB_POSEMODE) {
1234 bPoseChannel *pchan;
1235 bArmature *arm= ob->data;
1237 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1238 if(pchan->bone->flag & BONE_SELECTED) {
1239 if(pchan->bone->layer & arm->layer) {
1240 if((pchan->bone->flag & BONE_CONNECTED)==0) {
1241 float vecN[3], nLoc[3];
1243 /* get nearest grid point to snap to */
1244 VECCOPY(nLoc, pchan->pose_mat[3]);
1245 vec[0]= gridf * (float)(floor(.5+ nLoc[0]/gridf));
1246 vec[1]= gridf * (float)(floor(.5+ nLoc[1]/gridf));
1247 vec[2]= gridf * (float)(floor(.5+ nLoc[2]/gridf));
1249 /* get bone-space location of grid point */
1250 armature_loc_pose_to_bone(pchan, vec, vecN);
1252 /* adjust location */
1253 VECCOPY(pchan->loc, vecN);
1255 /* if the bone has a parent and is connected to the parent,
1256 * don't do anything - will break chain unless we do auto-ik.
1261 ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
1263 /* auto-keyframing */
1264 autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
1265 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1268 ob->recalc |= OB_RECALC_OB;
1270 vec[0]= -ob->obmat[3][0]+G.vd->gridview*floor(.5+ ob->obmat[3][0]/gridf);
1271 vec[1]= -ob->obmat[3][1]+G.vd->gridview*floor(.5+ ob->obmat[3][1]/gridf);
1272 vec[2]= -ob->obmat[3][2]+G.vd->gridview*floor(.5+ ob->obmat[3][2]/gridf);
1275 where_is_object(ob);
1277 Mat3Inv(imat, originmat);
1278 Mat3MulVecfl(imat, vec);
1279 ob->loc[0]+= vec[0];
1280 ob->loc[1]+= vec[1];
1281 ob->loc[2]+= vec[2];
1284 ob->loc[0]+= vec[0];
1285 ob->loc[1]+= vec[1];
1286 ob->loc[2]+= vec[2];
1289 if(ob->vnode) b_verse_send_transformation(ob);
1292 /* auto-keyframing */
1293 autokeyframe_ob_cb_func(ob, TFM_TRANSLATION);
1299 DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0);
1300 allqueue(REDRAWVIEW3D, 0);
1303 void snap_sel_to_curs()
1305 extern float originmat[3][3]; /* object.c */
1309 float *curs, imat[3][3], bmat[3][3], vec[3];
1312 curs= give_cursor();
1317 if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
1318 make_trans_verts(bmat[0], bmat[1], 0);
1319 if(tottrans==0) return;
1321 Mat3CpyMat4(bmat, G.obedit->obmat);
1322 Mat3Inv(imat, bmat);
1325 for(a=0; a<tottrans; a++, tv++) {
1326 vec[0]= curs[0]-G.obedit->obmat[3][0];
1327 vec[1]= curs[1]-G.obedit->obmat[3][1];
1328 vec[2]= curs[2]-G.obedit->obmat[3][2];
1330 Mat3MulVecfl(imat, vec);
1331 VECCOPY(tv->loc, vec);
1334 special_transvert_update();
1336 MEM_freeN(transvmain);
1339 allqueue(REDRAWVIEW3D, 0);
1343 base= (G.scene->base.first);
1345 if( ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) && ((base)->object->id.lib==0))) {
1347 if(ob->flag & OB_POSEMODE) {
1348 bPoseChannel *pchan;
1349 bArmature *arm= ob->data;
1352 Mat4Invert(ob->imat, ob->obmat);
1353 VECCOPY(cursp, curs);
1354 Mat4MulVecfl(ob->imat, cursp);
1356 for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
1357 if(pchan->bone->flag & BONE_SELECTED) {
1358 if(pchan->bone->layer & arm->layer) {
1359 if((pchan->bone->flag & BONE_CONNECTED)==0) {
1362 /* get location of cursor in bone-space */
1363 armature_loc_pose_to_bone(pchan, cursp, curspn);
1365 /* calculate new position */
1366 VECCOPY(pchan->loc, curspn);
1368 /* if the bone has a parent and is connected to the parent,
1369 * don't do anything - will break chain unless we do auto-ik.
1374 ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
1376 /* auto-keyframing */
1377 autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
1378 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1381 ob->recalc |= OB_RECALC_OB;
1383 vec[0]= -ob->obmat[3][0] + curs[0];
1384 vec[1]= -ob->obmat[3][1] + curs[1];
1385 vec[2]= -ob->obmat[3][2] + curs[2];
1388 where_is_object(ob);
1390 Mat3Inv(imat, originmat);
1391 Mat3MulVecfl(imat, vec);
1392 ob->loc[0]+= vec[0];
1393 ob->loc[1]+= vec[1];
1394 ob->loc[2]+= vec[2];
1397 ob->loc[0]+= vec[0];
1398 ob->loc[1]+= vec[1];
1399 ob->loc[2]+= vec[2];
1402 if(ob->vnode) b_verse_send_transformation(ob);
1405 /* auto-keyframing */
1406 autokeyframe_ob_cb_func(ob, TFM_TRANSLATION);
1412 DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0);
1413 allqueue(REDRAWVIEW3D, 0);
1416 void snap_curs_to_grid()
1420 gridf= G.vd->gridview;
1421 curs= give_cursor();
1423 curs[0]= G.vd->gridview*floor(.5+curs[0]/gridf);
1424 curs[1]= G.vd->gridview*floor(.5+curs[1]/gridf);
1425 curs[2]= G.vd->gridview*floor(.5+curs[2]/gridf);
1427 allqueue(REDRAWVIEW3D, 0);
1430 void snap_curs_to_sel()
1434 float *curs, bmat[3][3], vec[3], min[3], max[3], centroid[3];
1437 curs= give_cursor();
1440 INIT_MINMAX(min, max);
1441 centroid[0]= centroid[1]= centroid[2]= 0.0;
1446 if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
1447 make_trans_verts(bmat[0], bmat[1], 2);
1448 if(tottrans==0) return;
1450 Mat3CpyMat4(bmat, G.obedit->obmat);
1453 for(a=0; a<tottrans; a++, tv++) {
1454 VECCOPY(vec, tv->loc);
1455 Mat3MulVecfl(bmat, vec);
1456 VecAddf(vec, vec, G.obedit->obmat[3]);
1457 VecAddf(centroid, centroid, vec);
1458 DO_MINMAX(vec, min, max);
1461 if(G.vd->around==V3D_CENTROID) {
1462 VecMulf(centroid, 1.0/(float)tottrans);
1463 VECCOPY(curs, centroid);
1466 curs[0]= (min[0]+max[0])/2;
1467 curs[1]= (min[1]+max[1])/2;
1468 curs[2]= (min[2]+max[2])/2;
1470 MEM_freeN(transvmain);
1476 if(ob && (ob->flag & OB_POSEMODE)) {
1477 bArmature *arm= ob->data;
1478 bPoseChannel *pchan;
1479 for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
1480 if(arm->layer & pchan->bone->layer) {
1481 if(pchan->bone->flag & BONE_SELECTED) {
1482 VECCOPY(vec, pchan->pose_head);
1483 Mat4MulVecfl(ob->obmat, vec);
1484 VecAddf(centroid, centroid, vec);
1485 DO_MINMAX(vec, min, max);
1492 for(base= G.scene->base.first; base; base= base->next) {
1493 if(((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
1494 VECCOPY(vec, base->object->obmat[3]);
1495 VecAddf(centroid, centroid, vec);
1496 DO_MINMAX(vec, min, max);
1502 if(G.vd->around==V3D_CENTROID) {
1503 VecMulf(centroid, 1.0/(float)count);
1504 VECCOPY(curs, centroid);
1507 curs[0]= (min[0]+max[0])/2;
1508 curs[1]= (min[1]+max[1])/2;
1509 curs[2]= (min[2]+max[2])/2;
1513 allqueue(REDRAWVIEW3D, 0);
1516 void snap_curs_to_active()
1519 curs = give_cursor();
1523 if (G.obedit->type == OB_MESH)
1527 if (EM_get_actSelection(&ese)) {
1528 EM_editselection_center(curs, &ese);
1531 Mat4MulVecfl(G.obedit->obmat, curs);
1538 VECCOPY(curs, BASACT->object->obmat[3]);
1541 allqueue(REDRAWVIEW3D, 0);
1545 void snap_to_center()
1547 extern float originmat[3][3];
1551 float snaploc[3], imat[3][3], bmat[3][3], vec[3], min[3], max[3], centroid[3];
1554 /*calculate the snaplocation (centerpoint) */
1556 INIT_MINMAX(min, max);
1557 centroid[0]= centroid[1]= centroid[2]= 0.0f;
1558 snaploc[0]= snaploc[1]= snaploc[2]= 0.0f;
1563 if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
1564 make_trans_verts(bmat[0], bmat[1], 0);
1565 if(tottrans==0) return;
1567 Mat3CpyMat4(bmat, G.obedit->obmat);
1568 Mat3Inv(imat, bmat);
1571 for(a=0; a<tottrans; a++, tv++) {
1572 VECCOPY(vec, tv->loc);
1573 Mat3MulVecfl(bmat, vec);
1574 VecAddf(vec, vec, G.obedit->obmat[3]);
1575 VecAddf(centroid, centroid, vec);
1576 DO_MINMAX(vec, min, max);
1579 if(G.vd->around==V3D_CENTROID) {
1580 VecMulf(centroid, 1.0/(float)tottrans);
1581 VECCOPY(snaploc, centroid);
1584 snaploc[0]= (min[0]+max[0])/2;
1585 snaploc[1]= (min[1]+max[1])/2;
1586 snaploc[2]= (min[2]+max[2])/2;
1589 MEM_freeN(transvmain);
1593 base= (G.scene->base.first);
1595 if(((base)->flag & SELECT) && ((base)->lay & G.vd->lay) ) {
1597 if(ob->flag & OB_POSEMODE) {
1598 bPoseChannel *pchan;
1599 bArmature *arm= ob->data;
1601 for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
1602 if(pchan->bone->flag & BONE_SELECTED) {
1603 if(pchan->bone->layer & arm->layer) {
1604 VECCOPY(vec, pchan->pose_mat[3]);
1605 VecAddf(centroid, centroid, vec);
1606 DO_MINMAX(vec, min, max);
1613 /* not armature bones (i.e. objects) */
1614 VECCOPY(vec, base->object->obmat[3]);
1615 VecAddf(centroid, centroid, vec);
1616 DO_MINMAX(vec, min, max);
1623 if(G.vd->around==V3D_CENTROID) {
1624 VecMulf(centroid, 1.0/(float)count);
1625 VECCOPY(snaploc, centroid);
1628 snaploc[0]= (min[0]+max[0])/2;
1629 snaploc[1]= (min[1]+max[1])/2;
1630 snaploc[2]= (min[2]+max[2])/2;
1635 /* Snap the selection to the snaplocation (duh!) */
1639 if ELEM6(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
1640 make_trans_verts(bmat[0], bmat[1], 0);
1641 if(tottrans==0) return;
1643 Mat3CpyMat4(bmat, G.obedit->obmat);
1644 Mat3Inv(imat, bmat);
1647 for(a=0; a<tottrans; a++, tv++) {
1648 vec[0]= snaploc[0]-G.obedit->obmat[3][0];
1649 vec[1]= snaploc[1]-G.obedit->obmat[3][1];
1650 vec[2]= snaploc[2]-G.obedit->obmat[3][2];
1652 Mat3MulVecfl(imat, vec);
1653 VECCOPY(tv->loc, vec);
1656 special_transvert_update();
1658 MEM_freeN(transvmain);
1661 allqueue(REDRAWVIEW3D, 0);
1665 base= (G.scene->base.first);
1667 if( ( ((base)->flag & SELECT) && ((base)->lay & G.vd->lay) && ((base)->object->id.lib==0))) {
1669 if(ob->flag & OB_POSEMODE) {
1670 bPoseChannel *pchan;
1671 bArmature *arm= ob->data;
1673 for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
1674 if(pchan->bone->flag & BONE_SELECTED) {
1675 if(pchan->bone->layer & arm->layer) {
1676 if((pchan->bone->flag & BONE_CONNECTED)==0) {
1677 /* get location of cursor in bone-space */
1678 armature_loc_pose_to_bone(pchan, snaploc, vec);
1680 /* calculate new position */
1681 VECCOPY(pchan->loc, vec);
1683 /* if the bone has a parent and is connected to the parent,
1684 * don't do anything - will break chain unless we do auto-ik.
1690 /* auto-keyframing */
1691 ob->pose->flag |= POSE_DO_UNLOCK;
1692 autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
1693 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1696 ob->recalc |= OB_RECALC_OB;
1698 vec[0]= -ob->obmat[3][0] + snaploc[0];
1699 vec[1]= -ob->obmat[3][1] + snaploc[1];
1700 vec[2]= -ob->obmat[3][2] + snaploc[2];
1703 where_is_object(ob);
1705 Mat3Inv(imat, originmat);
1706 Mat3MulVecfl(imat, vec);
1707 ob->loc[0]+= vec[0];
1708 ob->loc[1]+= vec[1];
1709 ob->loc[2]+= vec[2];
1712 ob->loc[0]+= vec[0];
1713 ob->loc[1]+= vec[1];
1714 ob->loc[2]+= vec[2];
1717 if(ob->vnode) b_verse_send_transformation(ob);
1720 /* auto-keyframing */
1721 autokeyframe_ob_cb_func(ob, TFM_TRANSLATION);
1727 DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0);
1728 allqueue(REDRAWVIEW3D, 0);
1736 event = pupmenu("Snap %t|Selection -> Grid%x1|Selection -> Cursor%x2|Selection -> Center%x3|%l|Cursor -> Selection%x4|Cursor -> Grid%x5|Cursor -> Active%x6");
1739 case 1: /*Selection to grid*/
1741 BIF_undo_push("Snap selection to grid");
1743 case 2: /*Selection to cursor*/
1745 BIF_undo_push("Snap selection to cursor");
1747 case 3: /*Selection to center of selection*/
1749 BIF_undo_push("Snap selection to center");
1751 case 4: /*Cursor to selection*/
1754 case 5: /*Cursor to grid*/
1755 snap_curs_to_grid();
1757 case 6: /*Cursor to Active*/
1758 snap_curs_to_active();
1759 BIF_undo_push("Snap selection to center");
1767 char *str_menu = BIF_menustringTransformOrientation("Align");
1768 val= pupmenu(str_menu);
1769 MEM_freeN(str_menu);
1773 short old_val = G.vd->twmode;
1775 initTransform(TFM_ALIGN, CTX_NO_PET|CTX_AUTOCONFIRM);
1777 G.vd->twmode = old_val;
1781 #define MERGELIMIT 0.001
1782 void mergemenu(void)
1788 if(G.scene->selectmode & SCE_SELECT_VERTEX)
1789 if(G.editMesh->selected.first && G.editMesh->selected.last &&
1790 ((EditSelection*)G.editMesh->selected.first)->type == EDITVERT && ((EditSelection*)G.editMesh->selected.last)->type == EDITVERT)
1791 event = pupmenu("Merge %t|At First %x6|At Last%x1|At Center%x3|At Cursor%x4|Collapse%x2");
1792 else if (G.editMesh->selected.first && ((EditSelection*)G.editMesh->selected.first)->type == EDITVERT)
1793 event = pupmenu("Merge %t|At First %x6|At Center%x3|At Cursor%x4|Collapse%x2");
1794 else if (G.editMesh->selected.last && ((EditSelection*)G.editMesh->selected.last)->type == EDITVERT)
1795 event = pupmenu("Merge %t|At Last %x1|At Center%x3|At Cursor%x4|Collapse%x2");
1796 else event = pupmenu("Merge %t|At Center%x3|At Cursor%x4|Collapse%x2");
1797 else event = pupmenu("Merge %t|At Center%x3|At Cursor%x4|Collapse%x2");
1803 if(G.qual & LR_CTRLKEY) remCount = merge_target(0,1);
1804 else remCount = merge_target(0,0);
1805 BIF_undo_push("Merge at center");
1808 if(G.qual & LR_CTRLKEY) remCount = merge_target(1,1);
1809 else remCount = merge_target(1,0);
1810 BIF_undo_push("Merge at cursor");
1813 if(G.qual & LR_CTRLKEY) remCount = merge_firstlast(0,1);
1814 else remCount = merge_firstlast(0,0);
1815 BIF_undo_push("Merge at last selected");
1818 if(G.qual & LR_CTRLKEY) remCount = merge_firstlast(1,1);
1819 else remCount = merge_firstlast(1,0);
1820 BIF_undo_push("Merge at first selected");
1823 remCount = collapseEdges();
1824 BIF_undo_push("Collapse");
1827 notice("Removed %d Vertices", remCount);
1828 allqueue(REDRAWVIEW3D, 0);
1834 void delete_context_selected(void)
1836 if(BIF_fullSketchMode())
1841 if(G.obedit->type==OB_MESH) delete_mesh();
1842 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) delNurb();
1843 else if(G.obedit->type==OB_MBALL) delete_mball();
1844 else if (G.obedit->type==OB_ARMATURE) delete_armature();
1846 else if(G.f & G_PARTICLEEDIT){
1847 PE_delete_particle();
1852 void duplicate_context_selected(void)
1855 if(G.obedit->type==OB_MESH) adduplicate_mesh();
1856 else if(G.obedit->type==OB_ARMATURE) adduplicate_armature();
1857 else if(G.obedit->type==OB_MBALL) adduplicate_mball();
1858 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) adduplicate_nurb();
1860 else if(G.f & G_PARTICLEEDIT);
1862 adduplicate(0, U.dupflag);
1865 void toggle_shading(void)
1867 if(G.qual & LR_SHIFTKEY) {
1868 if(G.qual & LR_ALTKEY) {
1869 reshadeall_displist();
1870 G.vd->drawtype= OB_SHADED;
1873 if(G.vd->drawtype== OB_SHADED) G.vd->drawtype= OB_WIRE;
1874 else G.vd->drawtype= OB_SHADED;
1877 else if(G.qual & LR_ALTKEY) {
1878 if(G.vd->drawtype== OB_TEXTURE) G.vd->drawtype= OB_SOLID;
1879 else G.vd->drawtype= OB_TEXTURE;
1882 if(G.vd->drawtype==OB_SOLID || G.vd->drawtype==OB_SHADED) G.vd->drawtype= OB_WIRE;
1883 else G.vd->drawtype= OB_SOLID;
1886 if(G.vd->drawtype != OB_WIRE && G.vd->depths) {
1887 G.vd->depths->damaged= 1;
1891 int minmax_verts(float *min, float *max)
1894 float centroid[3], vec[3], bmat[3][3];
1898 if ELEM5(G.obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE)
1899 make_trans_verts(bmat[0], bmat[1], 2);
1900 if(tottrans==0) return 0;
1902 Mat3CpyMat4(bmat, G.obedit->obmat);
1905 for(a=0; a<tottrans; a++, tv++) {
1906 VECCOPY(vec, tv->loc);
1907 Mat3MulVecfl(bmat, vec);
1908 VecAddf(vec, vec, G.obedit->obmat[3]);
1909 VecAddf(centroid, centroid, vec);
1910 DO_MINMAX(vec, min, max);
1913 MEM_freeN(transvmain);