Fix for #1839
[blender.git] / source / blender / src / editobject.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 /** 
34  * Theorie: (matrices) A x B x C == A x ( B x C x Binv) x B
35  * ofwel: OB x PAR x EDIT = OB x (PAR x EDIT x PARinv) x PAR
36  */
37
38 #include <stdlib.h>
39 #include <string.h>
40 #include <math.h>
41
42 #ifdef HAVE_CONFIG_H
43 #include <config.h>
44 #endif
45
46 #ifndef WIN32
47 #include <unistd.h>
48 #else
49 #include <io.h>
50 #include "BLI_winstuff.h"
51 #endif
52 #include "MEM_guardedalloc.h"
53 #include "PIL_time.h"
54
55 #include "BMF_Api.h"
56
57
58 #include "IMB_imbuf_types.h"
59
60 #include "DNA_action_types.h"
61 #include "DNA_armature_types.h"
62 #include "DNA_camera_types.h"
63 #include "DNA_curve_types.h"
64 #include "DNA_effect_types.h"
65 #include "DNA_ika_types.h"
66 #include "DNA_image_types.h"
67 #include "DNA_ipo_types.h"
68 #include "DNA_key_types.h"
69 #include "DNA_lamp_types.h"
70 #include "DNA_lattice_types.h"
71 #include "DNA_mesh_types.h"
72 #include "DNA_meshdata_types.h"
73 #include "DNA_meta_types.h"
74 #include "DNA_object_types.h"
75 #include "DNA_scene_types.h"
76 #include "DNA_screen_types.h"
77 #include "DNA_texture_types.h"
78 #include "DNA_view3d_types.h"
79 #include "DNA_world_types.h"
80 #include "DNA_userdef_types.h"
81 #include "DNA_property_types.h"
82 #include "DNA_vfont_types.h"
83 #include "DNA_constraint_types.h"
84
85 #include "BLI_blenlib.h"
86 #include "BLI_arithb.h"
87 #include "BLI_editVert.h"
88 #include "BLI_ghash.h"
89
90 #include "BKE_constraint.h"
91 #include "BKE_action.h"
92 #include "BKE_armature.h"
93 #include "BKE_utildefines.h"
94 #include "BKE_anim.h"
95 #include "BKE_blender.h"
96 #include "BKE_booleanops.h"
97 #include "BKE_curve.h"
98 #include "BKE_displist.h"
99 #include "BKE_effect.h"
100 #include "BKE_font.h"
101 #include "BKE_global.h"
102 #include "BKE_ika.h"
103 #include "BKE_ipo.h"
104 #include "BKE_key.h"
105 #include "BKE_lattice.h"
106 #include "BKE_library.h"
107 #include "BKE_main.h"
108 #include "BKE_material.h"
109 #include "BKE_mball.h"
110 #include "BKE_mesh.h"
111 #include "BKE_nla.h"
112 #include "BKE_object.h"
113 #include "BKE_property.h"
114 #include "BKE_sca.h"
115 #include "BKE_scene.h"
116 #include "BKE_softbody.h"
117 #include "BKE_subsurf.h"
118 #include "BKE_texture.h"
119 #include "BKE_utildefines.h"
120
121 #include "BIF_gl.h"
122 #include "BIF_graphics.h"
123 #include "BIF_interface.h"
124 #include "BIF_mywindow.h"
125 #include "BIF_toolbox.h"
126 #include "BIF_screen.h"
127 #include "BIF_space.h"
128 #include "BIF_toets.h"
129 #include "BIF_butspace.h"
130 #include "BIF_editconstraint.h"
131 #include "BIF_editdeform.h"
132 #include "BIF_editfont.h"
133 #include "BIF_editika.h"
134 #include "BIF_editlattice.h"
135 #include "BIF_editmesh.h"
136 #include "BIF_editoops.h"
137 #include "BIF_editview.h"
138 #include "BIF_editarmature.h"
139 #include "BIF_resources.h"
140
141 #include "BSE_edit.h"
142 #include "BSE_editaction.h"
143 #include "BSE_editipo.h"
144 #include "BSE_filesel.h"        /* For activate_databrowse() */
145 #include "BSE_view.h"
146 #include "BSE_trans_types.h"
147 #include "BSE_editipo_types.h"
148
149 #include "BDR_vpaint.h"
150 #include "BDR_editmball.h"
151 #include "BDR_editobject.h"
152 #include "BDR_drawobject.h"
153 #include "BDR_editcurve.h"
154 #include "BDR_unwrapper.h"
155
156 #include "render.h"
157 #include <time.h>
158 #include "mydevice.h"
159 #include "nla.h"
160
161 #include "blendef.h"
162
163 #include "BIF_poseobject.h"
164
165 /*  extern Lattice *copy_lattice(Lattice *lt); */
166 extern ListBase editNurb;
167 extern ListBase editelems;
168
169 TransOb *transmain= 0;
170 TransVert *transvmain= 0;
171 int tottrans=0, transmode=0;    /* 1: texspace */
172
173 float prop_size= 1.0;
174 int prop_mode= 0;
175 float prop_cent[3];
176
177 /* used in editipo, editcurve and here */
178 #define BEZSELECTED(bezt)   (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
179
180 #define TRANS_TEX       1
181
182 #define KEYFLAG_ROT             0x00000001
183 #define KEYFLAG_LOC             0x00000002
184 #define KEYFLAG_SIZE    0x00000004
185
186 float centre[3], centroid[3];
187
188 void mirrormenu(void);
189
190 void add_object_draw(int type)  /* for toolbox or menus, only non-editmode stuff */
191 {
192         Object *ob;
193         
194         G.f &= ~(G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT);
195         setcursor_space(SPACE_VIEW3D, CURSOR_STD);
196
197         if ELEM3(curarea->spacetype, SPACE_VIEW3D, SPACE_BUTS, SPACE_INFO) {
198                 if (G.obedit) exit_editmode(2); // freedata, and undo
199                 ob= add_object(type);
200                 base_init_from_view3d(BASACT, G.vd);
201                 
202                 if(type==OB_EMPTY) BIF_undo_push("Add Empty");
203                 else if(type==OB_LAMP) BIF_undo_push("Add Lamp");
204                 else if(type==OB_LATTICE) BIF_undo_push("Add Lattice");
205                 else BIF_undo_push("Add Camera");
206                 
207                 allqueue(REDRAWVIEW3D, 0);
208         }
209
210         redraw_test_buttons(OBACT);
211
212         allqueue(REDRAWALL, 0);
213
214         deselect_all_area_oops();
215         set_select_flag_oops();
216         allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
217 }
218
219 void add_objectLamp(short type)
220 {
221         Lamp *la;
222
223         /* this function also comes from an info window */
224         if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return;
225         
226         if(G.obedit==0) {
227                 add_object_draw(OB_LAMP);
228                 base_init_from_view3d(BASACT, G.vd);
229         }
230         
231         la = BASACT->object->data;
232         la->type = type;        
233
234         allqueue(REDRAWALL, 0);
235 }
236
237 void free_and_unlink_base(Base *base)
238 {
239         if (base==BASACT)
240                 BASACT= NULL;
241         
242         BLI_remlink(&G.scene->base, base);
243         free_libblock_us(&G.main->object, base->object);
244         MEM_freeN(base);
245 }
246
247 void delete_obj(int ok)
248 {
249         Base *base;
250         
251         if(G.obpose) return;
252         if(G.obedit) return;
253         if(G.scene->id.lib) return;
254         
255         base= FIRSTBASE;
256         while(base) {
257                 Base *nbase= base->next;
258
259                 if TESTBASE(base) {
260                         if(ok==0 &&  (ok=okee("Erase selected"))==0) return;
261                         
262                         free_and_unlink_base(base);
263                 }
264                 
265                 base= nbase;
266         }
267         countall();
268
269         G.f &= ~(G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT);
270         setcursor_space(SPACE_VIEW3D, CURSOR_STD);
271         
272         test_scene_constraints();
273         allqueue(REDRAWVIEW3D, 0);
274         redraw_test_buttons(OBACT);
275         allqueue (REDRAWACTION, 0);
276         allqueue(REDRAWIPO, 0);
277         allqueue(REDRAWDATASELECT, 0);
278         allqueue(REDRAWOOPS, 0);
279         allqueue(REDRAWACTION, 0);
280         allqueue(REDRAWNLA, 0);
281         
282         BIF_undo_push("Delete object(s)");
283 }
284
285 int return_editmesh_indexar(int **indexar, float *cent)
286 {
287         EditMesh *em = G.editMesh;
288         EditVert *eve;
289         int *index, nr, totvert=0;
290         
291         for(eve= em->verts.first; eve; eve= eve->next) {
292                 if(eve->f & SELECT) totvert++;
293         }
294         if(totvert==0) return 0;
295         
296         *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
297         nr= 0;
298         cent[0]= cent[1]= cent[2]= 0.0;
299         
300         for(eve= em->verts.first; eve; eve= eve->next) {
301                 if(eve->f & SELECT) {
302                         *index= nr; index++;
303                         VecAddf(cent, cent, eve->co);
304                 }
305                 nr++;
306         }
307         
308         VecMulf(cent, 1.0/(float)totvert);
309         
310         return totvert;
311 }
312
313 static void select_editmesh_hook(ObHook *hook)
314 {
315         EditMesh *em = G.editMesh;
316         EditVert *eve;
317         int index=0, nr=0;
318         
319         for(eve= em->verts.first; eve; eve= eve->next, nr++) {
320                 if(nr==hook->indexar[index]) {
321                         eve->f |= SELECT;
322                         if(index < hook->totindex-1) index++;
323                 }
324         }
325 }
326
327 int return_editlattice_indexar(int **indexar, float *cent)
328 {
329         BPoint *bp;
330         int *index, nr, totvert=0, a;
331         
332         // count
333         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
334         bp= editLatt->def;
335         while(a--) {
336                 if(bp->f1 & SELECT) {
337                         if(bp->hide==0) totvert++;
338                 }
339                 bp++;
340         }
341
342         if(totvert==0) return 0;
343         
344         *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
345         nr= 0;
346         cent[0]= cent[1]= cent[2]= 0.0;
347         
348         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
349         bp= editLatt->def;
350         while(a--) {
351                 if(bp->f1 & SELECT) {
352                         if(bp->hide==0) {
353                                 *index= nr; index++;
354                                 VecAddf(cent, cent, bp->vec);
355                         }
356                 }
357                 bp++;
358                 nr++;
359         }
360         
361         VecMulf(cent, 1.0/(float)totvert);
362         
363         return totvert;
364 }
365
366 static void select_editlattice_hook(ObHook *hook)
367 {
368         BPoint *bp;
369         int index=0, nr=0, a;
370         
371         // count
372         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
373         bp= editLatt->def;
374         while(a--) {
375                 if(hook->indexar[index]==nr) {
376                         bp->f1 |= SELECT;
377                         if(index < hook->totindex-1) index++;
378                 }
379                 nr++;
380                 bp++;
381         }
382 }
383
384 int return_editcurve_indexar(int **indexar, float *cent)
385 {
386         extern ListBase editNurb;
387         Nurb *nu;
388         BPoint *bp;
389         BezTriple *bezt;
390         int *index, a, nr, totvert=0;
391         
392         for(nu= editNurb.first; nu; nu= nu->next) {
393                 if((nu->type & 7)==CU_BEZIER) {
394                         bezt= nu->bezt;
395                         a= nu->pntsu;
396                         while(a--) {
397                                 if(bezt->f1 & SELECT) totvert++;
398                                 if(bezt->f2 & SELECT) totvert++;
399                                 if(bezt->f3 & SELECT) totvert++;
400                                 bezt++;
401                         }
402                 }
403                 else {
404                         bp= nu->bp;
405                         a= nu->pntsu*nu->pntsv;
406                         while(a--) {
407                                 if(bp->f1 & SELECT) totvert++;
408                                 bp++;
409                         }
410                 }
411         }
412         if(totvert==0) return 0;
413         
414         *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
415         nr= 0;
416         cent[0]= cent[1]= cent[2]= 0.0;
417         
418         for(nu= editNurb.first; nu; nu= nu->next) {
419                 if((nu->type & 7)==CU_BEZIER) {
420                         bezt= nu->bezt;
421                         a= nu->pntsu;
422                         while(a--) {
423                                 if(bezt->f1 & SELECT) {
424                                         *index= nr; index++;
425                                         VecAddf(cent, cent, bezt->vec[0]);
426                                 }
427                                 nr++;
428                                 if(bezt->f2 & SELECT) {
429                                         *index= nr; index++;
430                                         VecAddf(cent, cent, bezt->vec[1]);
431                                 }
432                                 nr++;
433                                 if(bezt->f3 & SELECT) {
434                                         *index= nr; index++;
435                                         VecAddf(cent, cent, bezt->vec[2]);
436                                 }
437                                 nr++;
438                                 bezt++;
439                         }
440                 }
441                 else {
442                         bp= nu->bp;
443                         a= nu->pntsu*nu->pntsv;
444                         while(a--) {
445                                 if(bp->f1 & SELECT) {
446                                         *index= nr; index++;
447                                         VecAddf(cent, cent, bp->vec);
448                                 }
449                                 nr++;
450                                 bp++;
451                         }
452                 }
453         }
454         
455         VecMulf(cent, 1.0/(float)totvert);
456         
457         return totvert;
458 }
459
460 static void select_editcurve_hook(ObHook *hook)
461 {
462         extern ListBase editNurb;
463         Nurb *nu;
464         BPoint *bp;
465         BezTriple *bezt;
466         int index=0, a, nr=0;
467         
468         for(nu= editNurb.first; nu; nu= nu->next) {
469                 if((nu->type & 7)==CU_BEZIER) {
470                         bezt= nu->bezt;
471                         a= nu->pntsu;
472                         while(a--) {
473                                 if(nr == hook->indexar[index]) {
474                                         bezt->f1 |= SELECT;
475                                         if(index<hook->totindex-1) index++;
476                                 }
477                                 nr++;
478                                 if(nr == hook->indexar[index]) {
479                                         bezt->f2 |= SELECT;
480                                         if(index<hook->totindex-1) index++;
481                                 }
482                                 nr++;
483                                 if(nr == hook->indexar[index]) {
484                                         bezt->f3 |= SELECT;
485                                         if(index<hook->totindex-1) index++;
486                                 }
487                                 nr++;
488
489                                 bezt++;
490                         }
491                 }
492                 else {
493                         bp= nu->bp;
494                         a= nu->pntsu*nu->pntsv;
495                         while(a--) {
496                                 if(nr == hook->indexar[index]) {
497                                         bp->f1 |= SELECT;
498                                         if(index<hook->totindex-1) index++;
499                                 }
500                                 nr++;
501                                 bp++;
502                         }
503                 }
504         }
505 }
506
507 void add_hook(void)
508 {
509         Object *ob=NULL;
510         ObHook *hook=NULL;
511         float cent[3];
512         int tot=0, *indexar, mode;
513
514         if(G.obedit==NULL) return;
515         
516         if(G.obedit->hooks.first)
517                 mode= pupmenu("Hooks %t|Add Hook, To New Empty %x1|Add Hook, To Selected Object %x2|Remove... %x3|Reassign... %x4|Select... %x5|Clear Offset...%x6");
518         else
519                 mode= pupmenu("Hooks %t|Add, New Empty %x1|Add, To Selected Object %x2");
520
521         if(mode<1) return;
522         
523         /* preconditions */
524
525         if(mode==2) { // selected object
526                 Base *base= FIRSTBASE;
527                 while(base) {
528                         if TESTBASELIB(base) {
529                                 if(base!=BASACT) {
530                                         ob= base->object;
531                                         break;
532                                 }
533                         }
534                         base= base->next;
535                 }
536                 if(ob==NULL) {
537                         error("Requires selected Object");
538                         return;
539                 }
540         }
541         else if(mode!=1) {
542                 int maxlen=0, a, nr;
543                 char *cp;
544                 
545                 // make pupmenu with hooks
546                 for(hook= G.obedit->hooks.first; hook; hook= hook->next) maxlen+=32;
547                 
548                 if(maxlen==0) {
549                         error("Object has no hooks yet");
550                         return;
551                 }
552                 
553                 cp= MEM_callocN(maxlen+32, "temp string");
554                 if(mode==3) strcpy(cp, "Remove %t|");
555                 else if(mode==4) strcpy(cp, "Reassign %t|");
556                 else if(mode==5) strcpy(cp, "Select %t|");
557                 else if(mode==6) strcpy(cp, "Clear Offset %t|");
558                 
559                 for(hook= G.obedit->hooks.first; hook; hook= hook->next) {
560                         strcat(cp, hook->name);
561                         strcat(cp, " |");
562                 }
563         
564                 nr= pupmenu(cp);
565                 MEM_freeN(cp);
566                 
567                 if(nr<1) return;
568                 
569                 a= 1;
570                 for(hook= G.obedit->hooks.first; hook; hook= hook->next, a++) {
571                         if(a==nr) break;
572                 }
573                 ob= hook->parent;
574         }
575
576         /* do it, new hooks or reassign */
577         if(mode==1 || mode==2 || mode==4) {
578         
579                 switch(G.obedit->type) {
580                 case OB_MESH:
581                         tot= return_editmesh_indexar(&indexar, cent);
582                         break;
583                 case OB_CURVE:
584                 case OB_SURF:
585                         tot= return_editcurve_indexar(&indexar, cent);
586                         break;
587                 case OB_LATTICE:
588                         tot= return_editlattice_indexar(&indexar, cent);
589                         break;
590                 }
591                 
592                 if(tot==0) {
593                         error("Requires selected vertices");
594                 }
595                 else {
596                         
597                         if(mode==1) {
598                                 Base *base= BASACT;
599
600                                 ob= add_object(OB_EMPTY);
601                                 /* transform cent to global coords for loc */
602                                 VecMat4MulVecfl(ob->loc, G.obedit->obmat, cent);
603                                 
604                                 /* restore, add_object sets active */
605                                 BASACT= base;
606                         }
607                         /* if mode is 2 or 4, ob has been set */
608                                                                         
609                         /* new hook */
610                         if(mode==1 || mode==2) {
611                                 hook= MEM_callocN(sizeof(ObHook), "new hook");
612                                 BLI_addtail(&G.obedit->hooks, hook);
613                                 strncpy(hook->name, ob->id.name+2, 30);
614                                 hook->force= 1.0;
615                         }
616                         else MEM_freeN(hook->indexar); // reassign, hook was set
617
618                         hook->parent= ob;
619                         hook->indexar= indexar;
620                         VECCOPY(hook->cent, cent);
621                         hook->totindex= tot;
622                         
623                         if(mode==1 || mode==2) {
624                                 /* matrix calculus */
625                                 /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
626                                 /*        (parentinv         )                          */
627                                 
628                                 where_is_object(ob);
629                 
630                                 Mat4Invert(ob->imat, ob->obmat);
631                                 /* apparently this call goes from right to left... */
632                                 Mat4MulSerie(hook->parentinv, ob->imat, G.obedit->obmat, NULL, 
633                                                         NULL, NULL, NULL, NULL, NULL);
634                         }
635                 }
636         }
637         else if(mode==3) { // remove
638                 BLI_remlink(&G.obedit->hooks, hook);
639                 MEM_freeN(hook->indexar);
640                 MEM_freeN(hook);
641         }
642         else if(mode==5) { // select
643                 if(G.obedit->type==OB_MESH) select_editmesh_hook(hook);
644                 else if(G.obedit->type==OB_LATTICE) select_editlattice_hook(hook);
645                 else if(G.obedit->type==OB_CURVE) select_editcurve_hook(hook);
646                 else if(G.obedit->type==OB_SURF) select_editcurve_hook(hook);
647         }
648         else if(mode==6) { // clear offset
649                 where_is_object(ob);    // ob is hook->parent
650
651                 Mat4Invert(ob->imat, ob->obmat);
652                 /* this call goes from right to left... */
653                 Mat4MulSerie(hook->parentinv, ob->imat, G.obedit->obmat, NULL, 
654                                         NULL, NULL, NULL, NULL, NULL);
655         }
656
657         allqueue(REDRAWVIEW3D, 0);
658         allqueue(REDRAWBUTSOBJECT, 0);
659         BIF_undo_push("Add hook");
660 }
661
662 void make_track(void)
663 {
664         Base *base;
665         short mode=0;
666         
667         if(G.scene->id.lib) return;
668         if(G.obedit) {
669                 return;
670         }
671         if(BASACT==0) return;
672
673         mode= pupmenu("Make Track %t|TrackTo Constraint %x1|LockTrack Constraint %x2|Old Track %x3");
674         if (mode == 0){
675                 return;
676         }
677         else if (mode == 1){
678                 bConstraint *con;
679                 bTrackToConstraint *data;
680
681                 base= FIRSTBASE;
682                 while(base) {
683                         if TESTBASELIB(base) {
684                                 if(base!=BASACT) {
685                                         con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
686                                         strcpy (con->name, "AutoTrack");
687
688                                         data = con->data;
689                                         data->tar = BASACT->object;
690
691                                         /* Lamp and Camera track differently by default */
692                                         if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
693                                                 data->reserved1 = TRACK_nZ;
694                                                 data->reserved2 = UP_Y;
695                                         }
696
697                                         add_constraint_to_object(con, base->object);
698                                 }
699                         }
700                         base= base->next;
701                 }
702
703                 test_scene_constraints();
704                 allqueue(REDRAWVIEW3D, 0);
705                 sort_baselist(G.scene);
706         }
707         else if (mode == 2){
708                 bConstraint *con;
709                 bLockTrackConstraint *data;
710
711                 base= FIRSTBASE;
712                 while(base) {
713                         if TESTBASELIB(base) {
714                                 if(base!=BASACT) {
715                                         con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
716                                         strcpy (con->name, "AutoTrack");
717
718                                         data = con->data;
719                                         data->tar = BASACT->object;
720
721                                         /* Lamp and Camera track differently by default */
722                                         if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
723                                                 data->trackflag = TRACK_nZ;
724                                                 data->lockflag = LOCK_Y;
725                                         }
726
727                                         add_constraint_to_object(con, base->object);
728                                 }
729                         }
730                         base= base->next;
731                 }
732
733                 test_scene_constraints();
734                 allqueue(REDRAWVIEW3D, 0);
735                 sort_baselist(G.scene);
736         }
737         else if (mode == 3){
738                 base= FIRSTBASE;
739                 while(base) {
740                         if TESTBASELIB(base) {
741                                 if(base!=BASACT) {
742
743                                         base->object->track= BASACT->object;
744                                 }
745                         }
746                         base= base->next;
747                 }
748
749                 test_scene_constraints();
750                 allqueue(REDRAWVIEW3D, 0);
751                 allqueue(REDRAWOOPS, 0);
752                 sort_baselist(G.scene);
753         }
754         BIF_undo_push("make Track");
755 }
756
757 void apply_obmat(Object *ob)
758 {
759         float mat[3][3], imat[3][3], tmat[3][3];
760         
761         /* from obmat to loc rot size */
762         
763         if(ob==0) return;
764         Mat3CpyMat4(mat, ob->obmat);
765         
766         VECCOPY(ob->loc, ob->obmat[3]);
767         
768         if(ob->transflag & OB_QUAT) {
769                 Mat3ToQuat(mat, ob->quat);
770                 QuatToMat3(ob->quat, tmat);
771         }
772         else {
773                 Mat3ToEul(mat, ob->rot);
774                 EulToMat3(ob->rot, tmat);
775         }
776         Mat3Inv(imat, tmat);
777         
778         Mat3MulMat3(tmat, imat, mat);
779         
780         ob->size[0]= tmat[0][0];
781         ob->size[1]= tmat[1][1];
782         ob->size[2]= tmat[2][2];
783
784 }
785
786 void clear_parent(void)
787 {
788         Object *par;
789         Base *base;
790         int mode;
791         
792         if(G.obedit) return;
793         if(G.scene->id.lib) return;
794
795         mode= pupmenu("OK? %t|Clear Parent %x1|Clear and Keep Transformation (Clear Track) %x2|Clear Parent Inverse %x3");
796         
797         if(mode<1) return;
798
799         base= FIRSTBASE;
800         while(base) {
801                 if TESTBASELIB(base) {
802                         par= 0;
803                         if(mode==1 || mode==2) {
804                                 if(base->object->type==OB_IKA) {
805                                         Ika *ika= base->object->data;
806                                         ika->parent= 0;
807                                 }
808                                 par= base->object->parent;
809                                 base->object->parent= 0;
810                         
811                                 if(mode==2) {
812                                         base->object->track= 0;
813                                         apply_obmat(base->object);
814                                 }
815                         }
816                         else if(mode==3) {
817                                 Mat4One(base->object->parentinv);
818                         }
819                         
820                         if(par) {
821                                 makeDispList(base->object);     // just always..., checks are not available well (ton)
822                         }
823                 }
824                 base= base->next;
825         }
826
827         test_scene_constraints();
828         allqueue(REDRAWVIEW3D, 0);
829         allqueue(REDRAWOOPS, 0);
830         
831         BIF_undo_push("Clear Parent");  
832 }
833
834 void clear_track(void)
835 {
836         Base *base;
837         int mode;
838         
839         if(G.obedit) return;
840         if(G.scene->id.lib) return;
841
842         mode= pupmenu("OK? %t|Clear Track %x1| Clear Track and Keep Transform %x2");
843
844         if(mode<1) return;
845
846         base= FIRSTBASE;
847         while(base) {
848                 if TESTBASELIB(base) {
849                         base->object->track= 0;
850
851                         if(mode==2) {
852                                 apply_obmat(base->object);
853                         }                       
854                 }
855                 base= base->next;
856         }
857         test_scene_constraints();
858         allqueue(REDRAWVIEW3D, 0);
859         allqueue(REDRAWOOPS, 0);
860         
861         BIF_undo_push("Clear Track");   
862 }
863
864 void clear_object(char mode)
865 {
866         Base *base;
867         Object *ob;
868         float *v1, *v3, mat[3][3];
869         char *str=NULL;
870         
871         if(G.obedit) return;
872         if(G.scene->id.lib) return;
873         
874         if(mode=='r') str= "Clear rotation";
875         else if(mode=='g') str= "Clear location";
876         else if(mode=='s') str= "Clear size";
877         else if(mode=='o') str= "Clear origin";
878         else return;
879         
880         if(okee(str)==0) return;
881         
882         if (G.obpose){
883
884                 switch (G.obpose->type){
885                 case OB_ARMATURE:
886                         clear_armature (G.obpose, mode);
887 #if 1
888                         clear_pose_constraint_status(G.obpose);
889                         make_displists_by_armature (G.obpose);
890 #endif
891                         break;
892                 }
893
894                 allqueue(REDRAWVIEW3D, 0);
895                 BIF_undo_push(str);
896                 return;
897         }
898
899         base= FIRSTBASE;
900         while(base) {
901                 if TESTBASELIB(base) {
902                         ob= base->object;
903                         
904                         if(mode=='r') {
905                                 memset(ob->rot, 0, 3*sizeof(float));
906                                 memset(ob->drot, 0, 3*sizeof(float));
907                                 QuatOne(ob->quat);
908                                 QuatOne(ob->dquat);
909                         }
910                         else if(mode=='g') {
911                                 memset(ob->loc, 0, 3*sizeof(float));
912                                 memset(ob->dloc, 0, 3*sizeof(float));
913                         }
914                         else if(mode=='s') {
915                                 memset(ob->dsize, 0, 3*sizeof(float));
916                                 ob->size[0]= 1.0;
917                                 ob->size[1]= 1.0;
918                                 ob->size[2]= 1.0;
919                         }
920                         else if(mode=='o') {
921                                 if(ob->parent) {
922                                         v1= ob->loc;
923                                         v3= ob->parentinv[3];
924                                         
925                                         Mat3CpyMat4(mat, ob->parentinv);
926                                         VECCOPY(v3, v1);
927                                         v3[0]= -v3[0];
928                                         v3[1]= -v3[1];
929                                         v3[2]= -v3[2];
930                                         Mat3MulVecfl(mat, v3);
931                                 }
932                         }
933                         
934                         if(ob->parent && ob->partype==PARSKEL)
935                                 freedisplist(&ob->disp);
936                         else if(ob->hooks.first)
937                                 freedisplist(&ob->disp);
938                 }
939                 base= base->next;
940         }
941         
942         allqueue(REDRAWVIEW3D, 0);
943         BIF_undo_push(str);
944 }
945
946 void reset_slowparents(void)
947 {
948         /* back to original locations */
949         Base *base;
950         
951         base= FIRSTBASE;
952         while(base) {
953                 if(base->object->parent) {
954                         if(base->object->partype & PARSLOW) {
955                                 base->object->partype -= PARSLOW;
956                                 where_is_object(base->object);
957                                 base->object->partype |= PARSLOW;
958                         }
959                 }
960                 base= base->next;
961         }
962 }
963
964 void set_slowparent(void)
965 {
966         Base *base;
967
968         if( okee("Set slow parent")==0 ) return;
969
970         base= FIRSTBASE;
971         while(base) {
972                 if TESTBASELIB(base) {
973                         if(base->object->parent) base->object->partype |= PARSLOW;
974                 }
975                 base= base->next;
976         }
977         BIF_undo_push("Slow parent");
978 }
979
980 void make_vertex_parent(void)
981 {
982         EditMesh *em = G.editMesh;
983         EditVert *eve;
984         Base *base;
985         Nurb *nu;
986         BezTriple *bezt;
987         BPoint *bp;
988         Object *par, *ob;
989         int a, v1=0, v2=0, v3=0, nr=1;
990         
991         /* we need 1 to 3 selected vertices */
992         
993         if(G.obedit->type==OB_MESH) {
994                 eve= em->verts.first;
995                 while(eve) {
996                         if(eve->f & 1) {
997                                 if(v1==0) v1= nr;
998                                 else if(v2==0) v2= nr;
999                                 else if(v3==0) v3= nr;
1000                                 else break;
1001                         }
1002                         nr++;
1003                         eve= eve->next;
1004                 }
1005         }
1006         else if ELEM(G.obedit->type, OB_SURF, OB_CURVE) {
1007                 nu= editNurb.first;
1008                 while(nu) {
1009                         if((nu->type & 7)==CU_BEZIER) {
1010                                 bezt= nu->bezt;
1011                                 a= nu->pntsu;
1012                                 while(a--) {
1013                                         if(BEZSELECTED(bezt)) {
1014                                                 if(v1==0) v1= nr;
1015                                                 else if(v2==0) v2= nr;
1016                                                 else if(v3==0) v3= nr;
1017                                                 else break;
1018                                         }
1019                                         nr++;
1020                                         bezt++;
1021                                 }
1022                         }
1023                         else {
1024                                 bp= nu->bp;
1025                                 a= nu->pntsu*nu->pntsv;
1026                                 while(a--) {
1027                                         if(bp->f1 & SELECT) {
1028                                                 if(v1==0) v1= nr;
1029                                                 else if(v2==0) v2= nr;
1030                                                 else if(v3==0) v3= nr;
1031                                                 else break;
1032                                         }
1033                                         nr++;
1034                                         bp++;
1035                                 }
1036                         }
1037                         nu= nu->next;
1038                 }
1039                 
1040         }
1041         
1042         if( !(v1 && v2==0 && v3==0) && !(v1 && v2 && v3) ) {
1043                 error("Select either 1 or 3 vertices to parent to");
1044                 return;
1045         }
1046         
1047         if(okee("Make vertex parent")==0) return;
1048         
1049         base= FIRSTBASE;
1050         while(base) {
1051                 if TESTBASELIB(base) {
1052                         if(base!=BASACT) {
1053                                 ob= base->object;
1054                                 par= BASACT->object->parent;
1055                                 
1056                                 while(par) {
1057                                         if(par==ob) break;
1058                                         par= par->parent;
1059                                 }
1060                                 if(par) {
1061                                         error("Loop in parents");
1062                                 }
1063                                 else {
1064                                         ob->parent= BASACT->object;
1065                                         if(v3) {
1066                                                 ob->partype= PARVERT3;
1067                                                 ob->par1= v1-1;
1068                                                 ob->par2= v2-1;
1069                                                 ob->par3= v3-1;
1070
1071                                                 /* inverse parent matrix */
1072                                                 what_does_parent(ob);
1073                                                 Mat4Invert(ob->parentinv, workob.obmat);
1074                                                 clear_workob();
1075                                         }
1076                                         else {
1077                                                 ob->partype= PARVERT1;
1078                                                 ob->par1= v1-1;
1079
1080                                                 /* inverse parent matrix */
1081                                                 what_does_parent(ob);
1082                                                 Mat4Invert(ob->parentinv, workob.obmat);
1083                                                 clear_workob();
1084                                         }
1085                                 }
1086                         }
1087                 }
1088                 base= base->next;
1089         }
1090         allqueue(REDRAWVIEW3D, 0);
1091         
1092         // BIF_undo_push(str); not, conflicts with editmode undo...
1093 }
1094
1095 int test_parent_loop(Object *par, Object *ob)
1096 {
1097         /* test if 'ob' is a parent somewhere in par's parents */
1098         
1099         if(par==0) return 0;
1100         if(ob == par) return 1;
1101         
1102         if(par->type==OB_IKA) {
1103                 Ika *ika= par->data;
1104                 
1105                 if( ob == ika->parent ) return 1;
1106                 if( test_parent_loop(ika->parent, ob) ) return 1;
1107         }
1108
1109         return test_parent_loop(par->parent, ob);
1110
1111 }
1112
1113 void make_parent(void)
1114 {
1115         Base *base;
1116         Object *par;
1117         short qual, mode=0, limbnr=0, effchild=0;
1118         char *bonestr=NULL;
1119         Bone    *bone=NULL;
1120         int     bonenr;
1121
1122         if(G.scene->id.lib) return;
1123         if(G.obedit) {
1124                 if ELEM3(G.obedit->type, OB_MESH, OB_CURVE, OB_SURF) make_vertex_parent();
1125                 else if (G.obedit->type==OB_ARMATURE) make_bone_parent();
1126                 return;
1127         }
1128         if(BASACT==0) return;
1129         
1130         qual= G.qual;
1131         par= BASACT->object;
1132
1133         if(par->type == OB_CURVE){
1134                 bConstraint *con;
1135                 bFollowPathConstraint *data;
1136
1137                 mode= pupmenu("Make Parent %t|Normal Parent %x1|Follow Path %x2|Curve Deform %x3");
1138                 if(mode<=0){
1139                         return;
1140                 }
1141                 else if(mode==1) {
1142                         mode= PAROBJECT;
1143                 }
1144                 else if(mode==3) {
1145                         mode= PARSKEL;
1146                 }
1147                 else if(mode==2) {
1148
1149                         base= FIRSTBASE;
1150                         while(base) {
1151                                 if TESTBASELIB(base) {
1152                                         if(base!=BASACT) {
1153                                                 float cmat[4][4], vec[3], size[3];
1154
1155                                                 con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
1156                                                 strcpy (con->name, "AutoPath");
1157
1158                                                 data = con->data;
1159                                                 data->tar = BASACT->object;
1160
1161                                                 add_constraint_to_object(con, base->object);
1162
1163                                                 get_constraint_target_matrix(con, TARGET_OBJECT, NULL, cmat, size, G.scene->r.cfra - base->object->sf);
1164                                                 VecSubf(vec, base->object->obmat[3], cmat[3]);
1165
1166                                                 base->object->loc[0] = vec[0];
1167                                                 base->object->loc[1] = vec[1];
1168                                                 base->object->loc[2] = vec[2];
1169                                         }
1170                                 }
1171                                 base= base->next;
1172                         }
1173
1174                         test_scene_constraints();
1175                         allqueue(REDRAWVIEW3D, 0);
1176                         sort_baselist(G.scene);
1177                         BIF_undo_push("make Parent");
1178                         return;
1179                 }
1180         }
1181         else if(par->type == OB_ARMATURE){
1182
1183                         base= FIRSTBASE;
1184                         while(base) {
1185                                 if TESTBASELIB(base) {
1186                                         if(base!=BASACT) {
1187                                                 if(base->object->type==OB_MESH) {
1188                                                         mode= pupmenu("Make Parent To%t|Bone %x1|Armature %x2|Object %x3");
1189                                                         break;
1190                                                 }
1191                                                 else {
1192                                                         mode= pupmenu("Make Parent To %t|Bone %x1|Object %x3");
1193                                                         break;
1194                                                 }
1195                                         }
1196                                 }
1197                                 base= base->next;
1198                         }
1199                 
1200                         switch (mode){
1201                         case 1:
1202                                 mode=PARBONE;
1203                                 /* Make bone popup menu */
1204
1205                                 bonestr = make_bone_menu(get_armature(par));
1206                 //              if(mbutton(&bone, bonestr, 1, 24, "Bone: ")==0) {
1207
1208                                 bonenr= pupmenu_col(bonestr, 20);
1209                                 if (bonestr)
1210                                         MEM_freeN (bonestr);
1211                                 
1212                                 if (bonenr==-1){
1213                                         allqueue(REDRAWVIEW3D, 0);
1214                                         return;
1215                                 }
1216
1217                                 apply_pose_armature(get_armature(par), par->pose, 0);
1218                                 bone=get_indexed_bone(get_armature(par), bonenr); 
1219                                 if (!bone){
1220                 //                      error ("Invalid bone!");
1221                                         allqueue(REDRAWVIEW3D, 0);
1222                                         return;
1223                                 }
1224
1225                                 break;
1226                         case 2:
1227                                 mode=PARSKEL;
1228                                 break;
1229                         case 3:
1230                                 mode=PAROBJECT;
1231                                 break;
1232                         default:
1233                                 return;
1234                         }
1235         }
1236         else {
1237                 if(qual & LR_SHIFTKEY) {
1238                         if(okee("Make parent without inverse")==0) return;
1239                 }
1240                 else {
1241                         if(qual & LR_ALTKEY) {
1242                                 if(okee("Make vertex parent")==0) return;
1243                         }
1244                         else if(okee("Make parent")==0) return;
1245
1246                         /* test effchild */
1247                         base= FIRSTBASE;
1248                         while(base) {
1249                                 if TESTBASELIB(base) {
1250                                         if(base->object->type==OB_IKA && base->object != par) {
1251                                                 if(effchild==0) {
1252                                                         if(okee("Effector as Child")) effchild= 1;
1253                                                         else effchild= 2;
1254                                                 }
1255                                         }
1256                                 }
1257                                 if(effchild) break;
1258                                 base= base->next;
1259                         }
1260                         
1261                         /* now we'll clearparentandkeeptransform all objects */
1262                         base= FIRSTBASE;
1263                         while(base) {
1264                                 if TESTBASELIB(base) {
1265                                         if(base!=BASACT && base->object->parent) {
1266                                                 if(base->object->type==OB_IKA && effchild==1);
1267                                                 else {
1268                                                         base->object->parent= 0;
1269                                                         apply_obmat(base->object);
1270                                                 }
1271                                         }
1272                                 }
1273                                 base= base->next;
1274                         }
1275                 }
1276         }
1277         
1278         
1279         base= FIRSTBASE;
1280         while(base) {
1281                 if TESTBASELIB(base) {
1282                         if(base!=BASACT) {
1283                                 
1284                                 if( test_parent_loop(par, base->object) ) {
1285                                         error("Loop in parents");
1286                                 }
1287                                 else {
1288                                         
1289                                         /* the ifs below are horrible code (ton) */
1290                                         
1291                                         if(par->type==OB_IKA){
1292                                                 base->object->partype= mode;
1293                                                 base->object->par1= limbnr;
1294                                         }
1295                                         else if (par->type==OB_ARMATURE){
1296                                                 base->object->partype= mode;
1297                                                 if (bone)
1298                                                         strcpy (base->object->parsubstr, bone->name);
1299                                                 else
1300                                                         base->object->parsubstr[0]=0;
1301                                         }
1302                                         else {
1303                                                 if(qual & LR_ALTKEY) {
1304                                                         base->object->partype= PARVERT1;
1305                                                 }
1306                                                 else if(par->type==OB_CURVE) {
1307                                                         base->object->partype= mode;
1308                                                 }
1309                                                 else {
1310                                                         base->object->partype= PAROBJECT;
1311                                                 }
1312                                         }
1313                                         base->object->parent= par;
1314                                         
1315                                         /* calculate inverse parent matrix? */
1316                                         if( (qual & LR_SHIFTKEY) ) {
1317                                                 /* not... */
1318                                                 Mat4One(base->object->parentinv);
1319                                                 memset(base->object->loc, 0, 3*sizeof(float));
1320                                         }
1321                                         else {
1322                                                 if(mode==PARSKEL && par->type == OB_ARMATURE) {
1323                                                         /* Prompt the user as to whether he wants to
1324                                                                 * add some vertex groups based on the bones
1325                                                                 * in the parent armature.
1326                                                                 */
1327                                                         create_vgroups_from_armature(base->object, 
1328                                                                                                                         par);
1329
1330                                                         base->object->partype= PAROBJECT;
1331                                                         what_does_parent(base->object);
1332                                                         Mat4One (base->object->parentinv);
1333                                                         base->object->partype= mode;
1334                                                 }
1335                                                 else
1336                                                         what_does_parent(base->object);
1337                                                 Mat4Invert(base->object->parentinv, workob.obmat);
1338                                         }
1339                                         
1340                                         if(par->type==OB_LATTICE) makeDispList(base->object);
1341                                         if(par->type==OB_CURVE && mode==PARSKEL) makeDispList(base->object);
1342                                         if(par->type==OB_ARMATURE && mode == PARSKEL){
1343                                                 verify_defgroups(base->object);
1344                                                 makeDispList(base->object);
1345                                         }
1346                                 }
1347                         }
1348                 }
1349                 base= base->next;
1350         }
1351         allqueue(REDRAWVIEW3D, 0);
1352         allqueue(REDRAWOOPS, 0);
1353         
1354         test_scene_constraints();
1355         sort_baselist(G.scene);
1356
1357         BIF_undo_push("make Parent");
1358 }
1359
1360
1361 void enter_editmode(void)
1362 {
1363         Base *base;
1364         Object *ob;
1365         Ika *ika;
1366         ID *id;
1367         Mesh *me;
1368         int ok= 0;
1369         bArmature *arm;
1370         
1371         if(G.scene->id.lib) return;
1372         base= BASACT;
1373         if(base==0) return;
1374         if((base->lay & G.vd->lay)==0) return;
1375         
1376         ob= base->object;
1377         if(ob->data==0) return;
1378         
1379         id= ob->data;
1380         if(id->lib) {
1381                 error("Can't edit library data");
1382                 return;
1383         }
1384         
1385         if(ob->type==OB_MESH) {
1386                 me= get_mesh(ob);
1387                 if( me==0 ) return;
1388                 if(me->id.lib) {
1389                         error("Can't edit library data");
1390                         return;
1391                 }
1392                 ok= 1;
1393                 G.obedit= ob;
1394                 make_editMesh();
1395                 allqueue(REDRAWBUTSLOGIC, 0);
1396                 if(G.f & G_FACESELECT) allqueue(REDRAWIMAGE, 0);
1397         }
1398         if (ob->type==OB_ARMATURE){
1399                 arm=base->object->data;
1400                 if (!arm) return;
1401                 if (arm->id.lib){
1402                         error("Can't edit library data");
1403                         return;
1404                 }
1405                 ok=1;
1406                 G.obedit=ob;
1407                 make_editArmature();
1408                 allqueue (REDRAWVIEW3D,0);
1409         }
1410         else if(ob->type==OB_IKA) {     /* grab type */
1411                 base= FIRSTBASE;
1412                 while(base) {
1413                         if TESTBASE(base) {
1414                                 if(base->object->type==OB_IKA) {
1415                                         ika= base->object->data;
1416                                         if(ika->flag & IK_GRABEFF) ika->flag &= ~IK_GRABEFF;
1417                                         else ika->flag |= IK_GRABEFF;
1418                                 }
1419                         }
1420                         base= base->next;
1421                 }
1422                 allqueue(REDRAWVIEW3D, 0);
1423         }
1424         else if(ob->type==OB_FONT) {
1425                 G.obedit= ob;
1426                 ok= 1;
1427                 make_editText();
1428         }
1429         else if(ob->type==OB_MBALL) {
1430                 G.obedit= ob;
1431                 ok= 1;
1432                 make_editMball();
1433         }
1434         else if(ob->type==OB_LATTICE) {
1435                 G.obedit= ob;
1436                 ok= 1;
1437                 make_editLatt();
1438         }
1439         else if(ob->type==OB_SURF || ob->type==OB_CURVE) {
1440                 ok= 1;
1441                 G.obedit= ob;
1442                 make_editNurb();
1443         }
1444         allqueue(REDRAWBUTSEDIT, 0);
1445         allqueue(REDRAWOOPS, 0);
1446         countall();
1447         
1448         if(ok) {
1449                 setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
1450         
1451                 allqueue(REDRAWVIEW3D, 1);
1452         }
1453         else G.obedit= 0;
1454
1455         if (G.obpose)
1456                 exit_posemode (1);
1457         scrarea_queue_headredraw(curarea);
1458 }
1459
1460 void make_displists_by_parent(Object *ob) {
1461         Base *base;
1462         
1463         for (base= FIRSTBASE; base; base= base->next)
1464                 if (ob==base->object->parent)
1465                         makeDispList(base->object);
1466 }
1467
1468 void exit_editmode(int freedata)        /* freedata==0 at render, 1= freedata, 2= do undo buffer too */
1469 {
1470         Base *base;
1471         Object *ob;
1472         Curve *cu;
1473
1474         if(G.obedit==NULL) return;
1475
1476         if(G.obedit->type==OB_MESH) {
1477
1478                 /* temporal */
1479                 countall();
1480
1481                 if(G.totvert>MESH_MAX_VERTS) {
1482                         error("Too many vertices");
1483                         return;
1484                 }
1485                 load_editMesh();        /* makes new displist */
1486
1487                 if(freedata) free_editMesh(G.editMesh);
1488
1489                 if(G.f & G_FACESELECT) {
1490                         set_seamtface();
1491                         allqueue(REDRAWIMAGE, 0);
1492                 }
1493
1494                 build_particle_system(G.obedit);
1495         }
1496         else if (G.obedit->type==OB_ARMATURE){  
1497                 load_editArmature();
1498                 if (freedata) free_editArmature();
1499         }
1500         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
1501                 load_editNurb();
1502                 if(freedata) freeNurblist(&editNurb);
1503         }
1504         else if(G.obedit->type==OB_FONT && freedata) {
1505                 load_editText();
1506         }
1507         else if(G.obedit->type==OB_LATTICE) {
1508                 load_editLatt();
1509                 if(freedata) free_editLatt();
1510         }
1511         else if(G.obedit->type==OB_MBALL) {
1512                 load_editMball();
1513                 if(freedata) BLI_freelistN(&editelems);
1514         }
1515
1516         ob= G.obedit;
1517         
1518         /* displist make is different in editmode */
1519         if(freedata) G.obedit= NULL;
1520         makeDispList(ob);
1521
1522         /* has this influence at other objects? */
1523         if(ob->type==OB_CURVE) {
1524
1525                 /* test if ob is use as bevelcurve r textoncurve */
1526                 base= FIRSTBASE;
1527                 while(base) {
1528                         if ELEM(base->object->type, OB_CURVE, OB_FONT) {
1529                                 cu= base->object->data;
1530                                 
1531                                 if(cu->textoncurve==ob) {
1532                                         text_to_curve(base->object, 0);
1533                                         makeDispList(base->object);
1534                                 }
1535                                 if(cu->bevobj==ob || cu->taperobj==ob) {
1536                                         makeDispList(base->object);
1537                                 }
1538                         }
1539                         base= base->next;
1540                 }
1541                 
1542         }
1543         else if(ob->type==OB_LATTICE) {
1544                 make_displists_by_parent(ob);
1545         }
1546
1547         if(freedata) {
1548                 setcursor_space(SPACE_VIEW3D, CURSOR_STD);
1549         
1550                 countall();
1551                 allqueue(REDRAWVIEW3D, 1);
1552                 allqueue(REDRAWBUTSEDIT, 0);
1553                 allqueue(REDRAWBUTSLOGIC, 0);
1554                 allqueue(REDRAWOOPS, 0);
1555         }
1556         scrarea_queue_headredraw(curarea);
1557
1558         if(ob->softflag) object_to_softbody(ob);
1559         
1560         if(G.obedit==NULL && freedata==2) 
1561                 BIF_undo_push("Editmode");
1562 }
1563
1564 void check_editmode(int type)
1565 {
1566         
1567         if (G.obedit==0 || G.obedit->type==type) return;
1568
1569         exit_editmode(2); // freedata, and undo
1570 }
1571
1572 /* 0 == do centre, 1 == centre new, 2 == centre cursor */
1573
1574 void docentre(int centremode)
1575 {
1576         EditMesh *em = G.editMesh;
1577         Base *base;
1578         Object *ob;
1579         Mesh *me, *tme;
1580         Curve *cu;
1581 //      BezTriple *bezt;
1582 //      BPoint *bp;
1583         Nurb *nu, *nu1;
1584         EditVert *eve;
1585         float cent[3], centn[3], min[3], max[3], omat[3][3];
1586         int a;
1587         MVert *mvert;
1588
1589         if(G.scene->id.lib) return;
1590
1591         if(G.obedit) {
1592
1593                 INIT_MINMAX(min, max);
1594         
1595                 if(G.obedit->type==OB_MESH) {
1596                         eve= em->verts.first;
1597                         while(eve) {
1598                                 DO_MINMAX(eve->co, min, max);
1599                                 eve= eve->next;
1600                         }
1601                         cent[0]= (min[0]+max[0])/2.0f;
1602                         cent[1]= (min[1]+max[1])/2.0f;
1603                         cent[2]= (min[2]+max[2])/2.0f;
1604                         
1605                         eve= em->verts.first;
1606                         while(eve) {
1607                                 VecSubf(eve->co, eve->co, cent);                        
1608                                 eve= eve->next;
1609                         }
1610                 }
1611         }
1612         
1613         /* reset flags */
1614         base= FIRSTBASE;
1615         while(base) {
1616                 if TESTBASELIB(base) {
1617                         base->object->flag &= ~OB_DONE;
1618                 }
1619                 base= base->next;
1620         }
1621         me= G.main->mesh.first;
1622         while(me) {
1623                 me->flag &= ~ME_ISDONE;
1624                 me= me->id.next;
1625         }
1626         
1627         base= FIRSTBASE;
1628         while(base) {
1629                 
1630                 if TESTBASELIB(base) {
1631                         if((base->object->flag & OB_DONE)==0) {
1632                                 
1633                                 base->object->flag |= OB_DONE;
1634                                 
1635                                 if(G.obedit==0 && (me=get_mesh(base->object)) ) {
1636                                         
1637                                         if(me->key) {
1638                                                 error("Can't change the center of a mesh with vertex keys");
1639                                                 return;
1640                                         }
1641                                         
1642                                         if(centremode==2) {
1643                                                 VECCOPY(cent, give_cursor());
1644                                                 Mat4Invert(base->object->imat, base->object->obmat);
1645                                                 Mat4MulVecfl(base->object->imat, cent);
1646                                         } else {
1647                                                 INIT_MINMAX(min, max);
1648                 
1649                                                 mvert= me->mvert;
1650                                                 for(a=0; a<me->totvert; a++, mvert++) {
1651                                                         DO_MINMAX(mvert->co, min, max);
1652                                                 }
1653                                 
1654                                                 cent[0]= (min[0]+max[0])/2.0f;
1655                                                 cent[1]= (min[1]+max[1])/2.0f;
1656                                                 cent[2]= (min[2]+max[2])/2.0f;
1657                                         }
1658                                                 
1659                                         mvert= me->mvert;
1660                                         for(a=0; a<me->totvert; a++, mvert++) {
1661                                                 VecSubf(mvert->co, mvert->co, cent);
1662                                         }
1663                                         me->flag |= ME_ISDONE;
1664                                         
1665                                         if(centremode) {
1666                                                 Mat3CpyMat4(omat, base->object->obmat);
1667                                                 
1668                                                 VECCOPY(centn, cent);
1669                                                 Mat3MulVecfl(omat, centn);
1670                                                 base->object->loc[0]+= centn[0];
1671                                                 base->object->loc[1]+= centn[1];
1672                                                 base->object->loc[2]+= centn[2];
1673                                                 
1674                                                 /* other users? */
1675                                                 ob= G.main->object.first;
1676                                                 while(ob) {
1677                                                         if((ob->flag & OB_DONE)==0) {
1678                                                                 tme= get_mesh(ob);
1679                                                                 
1680                                                                 if(tme==me) {
1681                                                                         
1682                                                                         ob->flag |= OB_DONE;
1683
1684                                                                         Mat3CpyMat4(omat, ob->obmat);
1685                                                                         VECCOPY(centn, cent);
1686                                                                         Mat3MulVecfl(omat, centn);
1687                                                                         ob->loc[0]+= centn[0];
1688                                                                         ob->loc[1]+= centn[1];
1689                                                                         ob->loc[2]+= centn[2];
1690                                                                         
1691                                                                         if(tme && (tme->flag & ME_ISDONE)==0) {
1692                                                                                 mvert= tme->mvert;
1693                                                                                 for(a=0; a<tme->totvert; a++, mvert++) {
1694                                                                                         VecSubf(mvert->co, mvert->co, cent);
1695                                                                                 }
1696                                                                                 tme->flag |= ME_ISDONE;
1697                                                                         }
1698                                                                 }
1699                                                         }
1700                                                         
1701                                                         ob= ob->id.next;
1702                                                 }
1703                                         }
1704                                 
1705                                         /* displist of all users, also this one */
1706                                         makeDispList(base->object);
1707                                         
1708                                         /* DO: check all users... */
1709                                         tex_space_mesh(me);
1710                 
1711                                 }
1712                                 else if ELEM(base->object->type, OB_CURVE, OB_SURF) {
1713                                                                         
1714                                         if(G.obedit) {
1715                                                 nu1= editNurb.first;
1716                                         }
1717                                         else {
1718                                                 cu= base->object->data;
1719                                                 nu1= cu->nurb.first;
1720                                         }
1721                                         
1722                                         if(centremode==2) {
1723                                                 VECCOPY(cent, give_cursor());
1724                                                 Mat4Invert(base->object->imat, base->object->obmat);
1725                                                 Mat4MulVecfl(base->object->imat, cent);
1726                                                         
1727                                                         /* Curves need to be 2d, never offset in
1728                                                          * Z. Is a somewhat arbitrary restriction, 
1729                                                          * would probably be nice to remove.
1730                                                          */
1731                                                 cent[2]= 0.0;
1732                                         } else {
1733                                                 INIT_MINMAX(min, max);
1734         
1735                                                 nu= nu1;
1736                                                 while(nu) {
1737                                                         minmaxNurb(nu, min, max);
1738                                                         nu= nu->next;
1739                                                 }
1740                                                 
1741                                                 cent[0]= (min[0]+max[0])/2.0f;
1742                                                 cent[1]= (min[1]+max[1])/2.0f;
1743                                                 cent[2]= (min[2]+max[2])/2.0f;
1744                                         }
1745                                         
1746                                         nu= nu1;
1747                                         while(nu) {
1748                                                 if( (nu->type & 7)==1) {
1749                                                         a= nu->pntsu;
1750                                                         while (a--) {
1751                                                                 VecSubf(nu->bezt[a].vec[0], nu->bezt[a].vec[0], cent);
1752                                                                 VecSubf(nu->bezt[a].vec[1], nu->bezt[a].vec[1], cent);
1753                                                                 VecSubf(nu->bezt[a].vec[2], nu->bezt[a].vec[2], cent);
1754                                                         }
1755                                                 }
1756                                                 else {
1757                                                         a= nu->pntsu*nu->pntsv;
1758                                                         while (a--)
1759                                                                 VecSubf(nu->bp[a].vec, nu->bp[a].vec, cent);
1760                                                 }
1761                                                 nu= nu->next;
1762                                         }
1763                         
1764                                         if(centremode && G.obedit==0) {
1765                                                 Mat3CpyMat4(omat, base->object->obmat);
1766                                                 
1767                                                 Mat3MulVecfl(omat, cent);
1768                                                 base->object->loc[0]+= cent[0];
1769                                                 base->object->loc[1]+= cent[1];
1770                                                 base->object->loc[2]+= cent[2];
1771                                         }
1772                         
1773                                         if(G.obedit) {
1774                                                 makeDispList(G.obedit);
1775                                                 break;
1776                                         }
1777                                         else makeDispList(base->object);
1778         
1779                                 }
1780                                 else if(base->object->type==OB_FONT) {
1781                                         /* get from bb */
1782                                         
1783                                         cu= base->object->data;
1784                                         if(cu->bb==0) return;
1785                                         
1786                                         cu->xof= -0.5f*( cu->bb->vec[4][0] - cu->bb->vec[0][0]);
1787                                         cu->yof= -0.5f -0.5f*( cu->bb->vec[0][1] - cu->bb->vec[2][1]);  /* extra 0.5 is the height of above line */
1788                                         
1789                                         /* not really ok, do this better once! */
1790                                         cu->xof /= cu->fsize;
1791                                         cu->yof /= cu->fsize;
1792                                         
1793                                         text_to_curve(base->object, 0);
1794                                         makeDispList(base->object);
1795                                         
1796                                         allqueue(REDRAWBUTSEDIT, 0);
1797                                 }
1798                         }
1799                 }
1800                 base= base->next;
1801         }
1802
1803         allqueue(REDRAWVIEW3D, 0);
1804         BIF_undo_push("Do Centre");     
1805 }
1806
1807 void docentre_new(void)
1808 {
1809         if(G.scene->id.lib) return;
1810
1811         if(G.obedit) {
1812                 error("Unable to center new in Edit Mode");
1813         }
1814         else {
1815                 docentre(1);
1816         }
1817 }
1818
1819 void docentre_cursor(void)
1820 {
1821         if(G.scene->id.lib) return;
1822
1823         if(G.obedit) {
1824                 error("Unable to center cursor in Edit Mode");
1825         }
1826         else {
1827                 docentre(2);
1828         }
1829 }
1830
1831 void movetolayer(void)
1832 {
1833         Base *base;
1834         unsigned int lay= 0, local;
1835
1836         if(G.scene->id.lib) return;
1837
1838         base= FIRSTBASE;
1839         while(base) {
1840                 if TESTBASE(base) lay |= base->lay;
1841                 base= base->next;
1842         }
1843         if(lay==0) return;
1844         lay &= 0xFFFFFF;
1845         
1846         if( movetolayer_buts(&lay)==0 ) return;
1847         if(lay==0) return;
1848
1849         base= FIRSTBASE;
1850         while(base) {
1851                 if TESTBASE(base) {
1852                         /* upper byte is used for local view */
1853                         local= base->lay & 0xFF000000;  
1854                         base->lay= lay + local;
1855
1856                         base->object->lay= lay;
1857                 }
1858                 base= base->next;
1859         }
1860         countall();
1861         allqueue(REDRAWBUTSEDIT, 0);
1862         allqueue(REDRAWVIEW3D, 0);
1863         allqueue(REDRAWOOPS, 0);
1864         allqueue(REDRAWINFO, 0);
1865         
1866         BIF_undo_push("Move to layer");
1867 }
1868
1869
1870 void special_editmenu(void)
1871 {
1872         extern short editbutflag;
1873         extern float doublimit;
1874         float fac;
1875         int nr,ret;
1876         short randfac;
1877         
1878         if(G.obedit==0) {
1879                 if(G.f & G_FACESELECT) {
1880                         Mesh *me= get_mesh(OBACT);
1881                         TFace *tface;
1882                         int a;
1883                         
1884                         if(me==0 || me->tface==0) return;
1885                         
1886                         nr= pupmenu("Specials%t|Set     Tex%x1|         Shared%x2|         Light%x3|         Invisible%x4|         Collision%x5|Clr     Tex%x6|         Shared%x7|         Light%x8|         Invisible%x9|         Collision%x10");
1887         
1888                         for(a=me->totface, tface= me->tface; a>0; a--, tface++) {
1889                                 if(tface->flag & SELECT) {
1890                                         switch(nr) {
1891                                         case 1:
1892                                                 tface->mode |= TF_TEX; break;
1893                                         case 2:
1894                                                 tface->mode |= TF_SHAREDCOL; break;
1895                                         case 3:
1896                                                 tface->mode |= TF_LIGHT; break; 
1897                                         case 4:
1898                                                 tface->mode |= TF_INVISIBLE; break;
1899                                         case 5:
1900                                                 tface->mode |= TF_DYNAMIC; break;
1901                                         case 6:
1902                                                 tface->mode &= ~TF_TEX;
1903                                                 tface->tpage= 0;
1904                                                 break;
1905                                         case 7:
1906                                                 tface->mode &= ~TF_SHAREDCOL; break;
1907                                         case 8:
1908                                                 tface->mode &= ~TF_LIGHT; break;
1909                                         case 9:
1910                                                 tface->mode &= ~TF_INVISIBLE; break;
1911                                         case 10:
1912                                                 tface->mode &= ~TF_DYNAMIC; break;
1913                                         }
1914                                 }
1915                         }
1916                         allqueue(REDRAWVIEW3D, 0);
1917                         allqueue(REDRAWBUTSEDIT, 0);
1918                         BIF_undo_push("Change texture face");
1919                 }
1920                 else if(G.f & G_VERTEXPAINT) {
1921                         Mesh *me= get_mesh(OBACT);
1922                         
1923                         if(me==0 || (me->mcol==NULL && me->tface==NULL) ) return;
1924                         
1925                         nr= pupmenu("Specials%t|Shared VertexCol%x1");
1926                         if(nr==1) {
1927                                 
1928                                 if(me->tface) tface_to_mcol(me);
1929                                 
1930                                 copy_vpaint_undo( (unsigned int *)me->mcol, me->totface);
1931                                 do_shared_vertexcol(me);
1932                                 
1933                                 if(me->tface) mcol_to_tface(me, 1);
1934                                 BIF_undo_push("Shared VertexCol");
1935                         }
1936                 }
1937                 else {
1938                         Base *base, *base_select= NULL;
1939
1940                         // Get the active object mesh.
1941                         Mesh *me= get_mesh(OBACT);
1942
1943                         // If the active object is a mesh...
1944                         if (me) {
1945                                 // Bring up a little menu with the boolean operation choices on.
1946                                 nr= pupmenu("Boolean %t|Intersect%x1|Union%x2|Difference%x3");
1947
1948                                 if (nr > 0) {
1949                                         // user has made a choice of a menu element.
1950                                         // All of the boolean functions require 2 mesh objects 
1951                                         // we search through the object list to find the other 
1952                                         // selected item and make sure it is distinct and a mesh.
1953
1954                                         base= FIRSTBASE;
1955                                         while(base) {
1956                                                 if(base->flag & SELECT) {
1957                                                         if(base->object != OBACT) base_select= base;
1958                                                 }
1959
1960                                                 base= base->next;
1961                                         }
1962
1963                                         if (base_select) {
1964                                                 if (get_mesh(base_select->object)) {
1965                                                         waitcursor(1);
1966                                                         ret = NewBooleanMesh(BASACT,base_select,nr);
1967                                                         if (ret==0) {
1968                                                                 error("An internal error occurred -- sorry!");
1969                                                         } else if(ret==-1) {
1970                                                                 error("Selected meshes must have faces to perform boolean operations");
1971                                                         }
1972                                                         else BIF_undo_push("Boolean");
1973
1974                                                         waitcursor(0);
1975                                                 } else {
1976                                                         error("Please select 2 meshes");
1977                                                 }
1978                                         } else {
1979                                                 error("Please select 2 meshes");
1980                                         }
1981                                 }
1982
1983                                 allqueue(REDRAWVIEW3D, 0);
1984                         }
1985                 }
1986         }
1987         else if(G.obedit->type==OB_MESH) {
1988
1989                 nr= pupmenu("Specials%t|Subdivide%x1|Subdivide Fractal%x2|Subdivide Smooth%x3|Merge%x4|Remove Doubles%x5|Hide%x6|Reveal%x7|Select Swap%x8|Flip Normals %x9|Smooth %x10|Bevel %x11");
1990                 if(nr>0) waitcursor(1);
1991                 
1992                 switch(nr) {
1993                 case 1:
1994                         subdivideflag(1, 0.0, editbutflag);
1995                         BIF_undo_push("Subdivide");
1996                         break;
1997                 case 2:
1998                         randfac= 10;
1999                         if(button(&randfac, 1, 100, "Rand fac:")==0) return;
2000                         fac= -( (float)randfac )/100;
2001                         subdivideflag(1, fac, editbutflag);
2002                         BIF_undo_push("Subdivide Fractal");
2003                         break;
2004                 case 3:
2005                         subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
2006                         BIF_undo_push("Subdivide Smooth");
2007                         break;
2008                 case 4:
2009                         mergemenu();
2010                         break;
2011                 case 5:
2012                         notice("Removed %d Vertices", removedoublesflag(1, doublimit));
2013                         BIF_undo_push("Remove Doubles");
2014                         break;
2015                 case 6:
2016                         hide_mesh(0);
2017                         break;
2018                 case 7:
2019                         reveal_mesh();
2020                         break;
2021                 case 8:
2022                         selectswap_mesh();
2023                         break;
2024                 case 9:
2025                         flip_editnormals();
2026                         BIF_undo_push("Flip Normals");
2027                         break;
2028                 case 10:
2029                         vertexsmooth();
2030                         break;
2031                 case 11:
2032                         bevel_menu();
2033                         break;
2034                 }               
2035                 
2036                 makeDispList(G.obedit);
2037                 
2038                 if(nr>0) waitcursor(0);
2039                 
2040         }
2041         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
2042
2043                 nr= pupmenu("Specials%t|Subdivide%x1|Switch Direction%x2");
2044                 
2045                 switch(nr) {
2046                 case 1:
2047                         subdivideNurb();
2048                         break;
2049                 case 2:
2050                         switchdirectionNurb2();
2051                         break;
2052                 }
2053         }
2054
2055         countall();
2056         allqueue(REDRAWVIEW3D, 0);
2057         
2058 }
2059
2060 void convertmenu(void)
2061 {
2062         Base *base, *basen, *basact;
2063         Object *ob, *ob1;
2064         Curve *cu;
2065         MetaBall *mb;
2066         Mesh *me;
2067         DispList *dl;
2068         int ok=0, nr = 0, a;
2069         
2070         if(G.scene->id.lib) return;
2071
2072         ob= OBACT;
2073         if(ob==0) return;
2074         if(G.obedit) return;
2075         
2076         basact= BASACT; /* will be restored */
2077                 
2078         if(ob->type==OB_FONT) {
2079                 nr= pupmenu("Convert Font to%t|Curve");
2080                 if(nr>0) ok= 1;
2081         }
2082         else if(ob->type==OB_MBALL) {
2083                 nr= pupmenu("Convert Metaball to%t|Mesh (keep original)");
2084                 if(nr>0) ok= 1;
2085         }
2086         else if(ob->type==OB_CURVE) {
2087                 nr= pupmenu("Convert Curve to%t|Mesh");
2088                 if(nr>0) ok= 1;
2089         }
2090         else if(ob->type==OB_SURF) {
2091                 nr= pupmenu("Convert Nurbs Surface to%t|Mesh");
2092                 if(nr>0) ok= 1;
2093         }
2094         else if(ob->type==OB_MESH && mesh_uses_displist((Mesh*) ob->data)) {
2095                 nr= pupmenu("Convert SubSurf to%t|Mesh (Keep Original)");
2096                 if(nr>0) ok= 1;
2097         }
2098         if(ok==0) return;
2099
2100         /* don't forget multiple users! */
2101
2102         /* reset flags */
2103         base= FIRSTBASE;
2104         while(base) {
2105                 if TESTBASELIB(base) {
2106                         base->object->flag &= ~OB_DONE;
2107                 }
2108                 base= base->next;
2109         }
2110
2111         base= FIRSTBASE;
2112         while(base) {
2113                 if TESTBASELIB(base) {
2114                         
2115                         ob= base->object;
2116                         
2117                         if(ob->flag & OB_DONE);
2118                         else if(ob->type==OB_MESH) {
2119                                 Mesh *oldme= ob->data;
2120                                 
2121                                 if (mesh_uses_displist(oldme)) {
2122                                         DispListMesh *dlm;
2123
2124                                         ob->flag |= OB_DONE;
2125
2126                                         ob1= copy_object(ob);
2127
2128                                         basen= MEM_mallocN(sizeof(Base), "duplibase");
2129                                         *basen= *base;
2130                                         BLI_addhead(&G.scene->base, basen);     /* addhead: otherwise eternal loop */
2131                                         basen->object= ob1;
2132                                         basen->flag &= ~SELECT;
2133                                                 
2134                                         me= ob1->data;
2135                                         me->id.us--;
2136                                                 
2137                                         ob1->data= add_mesh();
2138                                         G.totmesh++;
2139                                         ob1->type= OB_MESH;
2140
2141                                         me= ob1->data;
2142                                         me->totcol= oldme->totcol;
2143                                         if(ob1->totcol) {
2144                                                 me->mat= MEM_dupallocN(oldme->mat);
2145                                                 for(a=0; a<ob1->totcol; a++) id_us_plus((ID *)me->mat[a]);
2146                                         }
2147                                                 
2148                                         dlm= subsurf_make_dispListMesh_from_mesh(oldme, NULL, oldme->subdiv, oldme->flag);
2149                                         displistmesh_to_mesh(dlm, ob1->data);
2150                                         displistmesh_free(dlm);
2151
2152                                         tex_space_mesh(me);
2153                                 }
2154                         }
2155                         else if(ob->type==OB_FONT) {
2156                                 if(nr==1) {
2157                                 
2158                                         ob->flag |= OB_DONE;
2159                                 
2160                                         ob->type= OB_CURVE;
2161                                         cu= ob->data;
2162                                         
2163                                         if(cu->vfont) {
2164                                                 cu->vfont->id.us--;
2165                                                 cu->vfont= 0;
2166                                         }
2167                                         /* other users */
2168                                         if(cu->id.us>1) {
2169                                                 ob1= G.main->object.first;
2170                                                 while(ob1) {
2171                                                         if(ob1->data==cu) ob1->type= OB_CURVE;
2172                                                         ob1= ob1->id.next;
2173                                                 }
2174                                         }
2175                                 }
2176                         }
2177                         else if ELEM(ob->type, OB_CURVE, OB_SURF) {
2178                                 if(nr==1) {
2179
2180                                         ob->flag |= OB_DONE;
2181                                         cu= ob->data;
2182                                         
2183                                         dl= cu->disp.first;
2184                                         if(dl==0) makeDispList(ob);
2185
2186                                         nurbs_to_mesh(ob); /* also does users */
2187
2188                                         /* texspace and normals */
2189                                         BASACT= base;
2190                                         enter_editmode();
2191                                         exit_editmode(1); // freedata, but no undo
2192                                         BASACT= basact;
2193                                 }
2194                         }
2195                         else if(ob->type==OB_MBALL) {
2196                         
2197                                 if(nr==1) {
2198                                         ob= find_basis_mball(ob);
2199                                         
2200                                         if(ob->disp.first && !(ob->flag&OB_DONE)) {
2201                                         
2202                                                 ob->flag |= OB_DONE;
2203
2204                                                 ob1= copy_object(ob);
2205
2206                                                 basen= MEM_mallocN(sizeof(Base), "duplibase");
2207                                                 *basen= *base;
2208                                                 BLI_addhead(&G.scene->base, basen);     /* addhead: othwise eternal loop */
2209                                                 basen->object= ob1;
2210                                                 basen->flag &= ~SELECT;
2211                                                 
2212                                                 mb= ob1->data;
2213                                                 mb->id.us--;
2214                                                 
2215                                                 ob1->data= add_mesh();
2216                                                 G.totmesh++;
2217                                                 ob1->type= OB_MESH;
2218                                                 
2219                                                 me= ob1->data;
2220                                                 me->totcol= mb->totcol;
2221                                                 if(ob1->totcol) {
2222                                                         me->mat= MEM_dupallocN(mb->mat);
2223                                                         for(a=0; a<ob1->totcol; a++) id_us_plus((ID *)me->mat[a]);
2224                                                 }
2225                                                 
2226                                                 mball_to_mesh(&ob->disp, ob1->data);
2227                                                 tex_space_mesh(me);
2228                                         }
2229                                 }
2230                         }
2231                 }
2232                 base= base->next;
2233         }
2234         
2235         allqueue(REDRAWVIEW3D, 0);
2236         allqueue(REDRAWOOPS, 0);
2237         allqueue(REDRAWBUTSEDIT, 0);
2238         BIF_undo_push("Convert Object");
2239 }
2240
2241         /* Change subdivision properties of mesh object ob, if
2242          * level==-1 then toggle subsurf, else set to level.
2243          */
2244 void flip_subdivison(Object *ob, int level)
2245 {
2246         Mesh *me = ob->data;
2247
2248         if (level == -1) {
2249                 me->flag ^= ME_SUBSURF;
2250         } else {
2251                 me->subdiv = level;
2252         }
2253
2254         allqueue(REDRAWVIEW3D, 0);
2255         allqueue(REDRAWOOPS, 0);
2256         allqueue(REDRAWBUTSEDIT, 0);
2257         makeDispList(ob);
2258         
2259         BIF_undo_push("Switch subsurf on/off");
2260 }
2261  
2262 void copymenu_properties(Object *ob)
2263 {       
2264         bProperty *prop, *propn, *propc;
2265         Base *base;
2266         int nr, tot=0;
2267         char *str;
2268         
2269         prop= ob->prop.first;
2270         while(prop) {
2271                 tot++;
2272                 prop= prop->next;
2273         }
2274         
2275         if(tot==0) {
2276                 error("No properties in the active object to copy");
2277                 return;
2278         }
2279         
2280         str= MEM_callocN(24+32*tot, "copymenu prop");
2281         
2282         strcpy(str, "Copy Property %t");
2283         
2284         tot= 0; 
2285         prop= ob->prop.first;
2286         while(prop) {
2287                 tot++;
2288                 strcat(str, " |");
2289                 strcat(str, prop->name);
2290                 prop= prop->next;
2291         }
2292
2293         nr= pupmenu(str);
2294         if(nr>0) {
2295                 tot= 0;
2296                 prop= ob->prop.first;
2297                 while(prop) {
2298                         tot++;
2299                         if(tot==nr) break;
2300                         prop= prop->next;
2301                 }
2302                 if(prop) {
2303                         propc= prop;
2304                         
2305                         base= FIRSTBASE;
2306                         while(base) {
2307                                 if(base != BASACT) {
2308                                         if(TESTBASELIB(base)) {
2309                                                 prop= get_property(base->object, propc->name);
2310                                                 if(prop) {
2311                                                         free_property(prop);
2312                                                         BLI_remlink(&base->object->prop, prop);
2313                                                 }
2314                                                 propn= copy_property(propc);
2315                                                 BLI_addtail(&base->object->prop, propn);
2316                                         }
2317                                 }
2318                                 base= base->next;
2319                         }
2320                 }
2321         }
2322         MEM_freeN(str);
2323         allqueue(REDRAWVIEW3D, 0);
2324         
2325         BIF_undo_push("Copy properties");
2326 }
2327
2328 void copymenu_logicbricks(Object *ob)
2329 {
2330         Base *base;
2331         
2332         base= FIRSTBASE;
2333         while(base) {
2334                 if(base->object != ob) {
2335                         if(TESTBASELIB(base)) {
2336                                 
2337                                 /* first: free all logic */
2338                                 free_sensors(&base->object->sensors);                           
2339                                 unlink_controllers(&base->object->controllers);
2340                                 free_controllers(&base->object->controllers);
2341                                 unlink_actuators(&base->object->actuators);
2342                                 free_actuators(&base->object->actuators);
2343                                 
2344                                 /* now copy it, this also works without logicbricks! */
2345                                 clear_sca_new_poins_ob(ob);
2346                                 copy_sensors(&base->object->sensors, &ob->sensors);
2347                                 copy_controllers(&base->object->controllers, &ob->controllers);
2348                                 copy_actuators(&base->object->actuators, &ob->actuators);
2349                                 set_sca_new_poins_ob(base->object);
2350                                 
2351                                 /* some menu settings */
2352                                 base->object->scavisflag= ob->scavisflag;
2353                                 base->object->scaflag= ob->scaflag;
2354                                 
2355                         }
2356                 }
2357                 base= base->next;
2358         }
2359         BIF_undo_push("Copy logic");
2360 }
2361
2362 void copy_attr_menu()
2363 {
2364         Object *ob;
2365         short event;
2366         char str[256];
2367
2368         /* If you change this menu, don't forget to update the menu in header_view3d.c
2369          * view3d_edit_object_copyattrmenu() and in toolbox.c
2370          */
2371         strcpy(str, "Copy Attributes %t|Location%x1|Rotation%x2|Size%x3|Drawtype%x4|Time Offset%x5|Dupli%x6|%l|Mass%x7|Damping%x8|Properties%x9|Logic Bricks%x10|%l");
2372
2373         if(!(ob=OBACT)) return;
2374         
2375         strcat (str, "|Object Constraints%x22");
2376         
2377         if ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) {
2378                 strcat(str, "|Texture Space%x17");
2379         }       
2380         
2381         if(ob->type == OB_FONT) strcat(str, "|Font Settings%x18|Bevel Settings%x19");
2382         if(ob->type == OB_CURVE) strcat(str, "|Bevel Settings%x19");
2383
2384         if(ob->type==OB_MESH){
2385                 strcat(str, "|Subdiv%x21");
2386         }
2387
2388         if( give_parteff(ob) ) strcat(str, "|Particle Settings%x20");
2389
2390         event= pupmenu(str);
2391         if(event<= 0) return;
2392         
2393         copy_attr(event);
2394 }
2395
2396 void copy_attr(short event)
2397 {
2398         Object *ob, *obt;
2399         Base *base;
2400         Curve *cu, *cu1;
2401         void *poin1, *poin2=0;
2402         
2403         if(G.scene->id.lib) return;
2404
2405         if(!(ob=OBACT)) return;
2406         
2407         if(G.obedit) {
2408                 /* obedit_copymenu(); */
2409                 return;
2410         }
2411         
2412         if ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) {
2413                 if(ob->type==OB_MESH) poin2= &(((Mesh *)ob->data)->texflag);
2414                 else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) poin2= &(((Curve *)ob->data)->texflag);
2415                 else if(ob->type==OB_MBALL) poin2= &(((MetaBall *)ob->data)->texflag);
2416         }       
2417
2418         if(event==9) {
2419                 copymenu_properties(ob);
2420                 return;
2421         }
2422         else if(event==10) {
2423                 copymenu_logicbricks(ob);
2424                 return;
2425         }
2426
2427         base= FIRSTBASE;
2428         while(base) {
2429                 if(base != BASACT) {
2430                         if(TESTBASELIB(base)) {
2431                                 
2432                                 if(event==1) {  /* loc */
2433                                         VECCOPY(base->object->loc, ob->loc);
2434                                         VECCOPY(base->object->dloc, ob->dloc);
2435                                 }
2436                                 else if(event==2) {  /* rot */
2437                                         VECCOPY(base->object->rot, ob->rot);
2438                                         VECCOPY(base->object->drot, ob->drot);
2439                                         VECCOPY(base->object->quat, ob->quat);
2440                                         VECCOPY(base->object->dquat, ob->dquat);
2441                                 }
2442                                 else if(event==3) {  /* size */
2443                                         VECCOPY(base->object->size, ob->size);
2444                                         VECCOPY(base->object->dsize, ob->dsize);
2445                                 }
2446                                 else if(event==4) {  /* drawtype */
2447                                         base->object->dt= ob->dt;
2448                                         base->object->dtx= ob->dtx;
2449                                         }
2450                                 else if(event==5) {  /* time offs */
2451                                         base->object->sf= ob->sf;
2452                                 }
2453                                 else if(event==6) {  /* dupli */
2454                                         base->object->dupon= ob->dupon;
2455                                         base->object->dupoff= ob->dupoff;
2456                                         base->object->dupsta= ob->dupsta;
2457                                         base->object->dupend= ob->dupend;
2458                                         
2459                                         base->object->transflag &= ~OB_DUPLI;
2460                                         base->object->transflag |= (ob->transflag & OB_DUPLI);
2461                                 }
2462                                 else if(event==7) {     /* mass */
2463                                         base->object->mass= ob->mass;
2464                                 }
2465                                 else if(event==8) {     /* damping */
2466                                         base->object->damping= ob->damping;
2467                                         base->object->rdamping= ob->rdamping;
2468                                 }
2469                                 else if(event==17) {    /* tex space */
2470                                         obt= base->object;
2471                                         poin1= 0;
2472                                         if(obt->type==OB_MESH) poin1= &(((Mesh *)obt->data)->texflag);
2473                                         else if ELEM3(obt->type, OB_CURVE, OB_SURF, OB_FONT) poin1= &(((Curve *)obt->data)->texflag);
2474                                         else if(obt->type==OB_MBALL) poin1= &(((MetaBall *)obt->data)->texflag);                                        
2475                                         
2476                                         if(poin1) {
2477                                                 memcpy(poin1, poin2, 4+12+12+12);
2478                                         
2479                                                 if(obt->type==OB_MESH) tex_space_mesh(obt->data);
2480                                                 else if(obt->type==OB_MBALL) tex_space_mball(obt);
2481                                                 else tex_space_curve(obt->data);
2482                                         }
2483                                 }
2484                                 else if(event==18) {    /* font settings */
2485                                         
2486                                         if(base->object->type==ob->type) {
2487                                                 cu= ob->data;
2488                                                 cu1= base->object->data;
2489                                                 
2490                                                 cu1->spacemode= cu->spacemode;
2491                                                 cu1->spacing= cu->spacing;
2492                                                 cu1->linedist= cu->linedist;
2493                                                 cu1->shear= cu->shear;
2494                                                 cu1->fsize= cu->fsize;
2495                                                 cu1->xof= cu->xof;
2496                                                 cu1->yof= cu->yof;
2497                                                 cu1->textoncurve= cu->textoncurve;
2498                                                 if(cu1->vfont) cu1->vfont->id.us--;
2499                                                 cu1->vfont= cu->vfont;
2500                                                 id_us_plus((ID *)cu1->vfont);
2501                                                 text_to_curve(base->object, 0);
2502                                                 
2503                                                 strcpy(cu1->family, cu->family);
2504                                                 
2505                                                 makeDispList(base->object);
2506                                         }
2507                                 }
2508                                 else if(event==19) {    /* bevel settings */
2509                                         
2510                                         if ELEM(base->object->type, OB_CURVE, OB_FONT) {
2511                                                 cu= ob->data;
2512                                                 cu1= base->object->data;
2513                                                 
2514                                                 cu1->bevobj= cu->bevobj;
2515                                                 cu1->taperobj= cu->taperobj;
2516                                                 cu1->width= cu->width;
2517                                                 cu1->bevresol= cu->bevresol;
2518                                                 cu1->ext1= cu->ext1;
2519                                                 cu1->ext2= cu->ext2;
2520                                                 
2521                                                 makeDispList(base->object);
2522                                         }
2523                                 }
2524                                 else if(event==20) {    /* particle settings */
2525                                         PartEff *pa1, *pa2;
2526                                         char *p1, *p2;
2527                                         
2528                                         pa1= give_parteff(ob);
2529                                         pa2= give_parteff(base->object);
2530
2531                                         if(pa1==0 && pa2) {
2532                                                 BLI_remlink( &(base->object->effect), pa2);
2533                                                 free_effect( (Effect *) pa2);
2534                                         }
2535                                         else if(pa1 && pa2==0) {
2536                                                 free_effects(&(base->object->effect));
2537                                                 copy_effects(&(base->object->effect), &ob->effect);
2538                                                 build_particle_system(base->object);
2539                                         }
2540                                         else if(pa1 && pa2) {
2541                                                 if(pa2->keys) MEM_freeN(pa2->keys);
2542                                                 
2543                                                 p1= (char *)pa1; p2= (char *)pa2;
2544                                                 memcpy( p2+8, p1+8, sizeof(PartEff) - 8);
2545                                                 pa2->keys= 0;
2546                                                 
2547                                                 build_particle_system(base->object);
2548                                         }
2549                                 }
2550                                 else if(event==21){
2551                                         if (base->object->type==OB_MESH) {
2552                                                 Mesh *targetme= base->object->data;
2553                                                 Mesh *sourceme= ob->data;
2554
2555                                                 targetme->flag= (targetme->flag&~ME_SUBSURF) | (sourceme->flag&ME_SUBSURF);
2556                                                 targetme->subsurftype = sourceme->subsurftype;
2557                                                 targetme->subdiv= sourceme->subdiv;
2558                                                 targetme->subdivr= sourceme->subdivr;
2559                                                 makeDispList(base->object);
2560                                         }
2561                                 }
2562                                 else if(event==22){
2563                                         /* Clear the constraints on the target */
2564                                         free_constraints(&base->object->constraints);
2565                                         free_constraint_channels(&base->object->constraintChannels);
2566
2567                                         /* Copy the constraint channels over */
2568                                         copy_constraints(&base->object->constraints, &ob->constraints);
2569                                         if (U.dupflag& USER_DUP_IPO)
2570                                                 copy_constraint_channels(&base->object->constraintChannels, &ob->constraintChannels);
2571                                         else
2572                                                 clone_constraint_channels (&base->object->constraintChannels, &ob->constraintChannels, NULL);
2573
2574                                         base->object->activecon = NULL;
2575                                 }
2576                         }
2577                 }
2578                 base= base->next;
2579         }
2580         
2581         allqueue(REDRAWVIEW3D, 0);
2582         if(event==20) {
2583                 allqueue(REDRAWBUTSOBJECT, 0);
2584         }
2585         
2586         BIF_undo_push("Copy attributes");
2587 }
2588
2589 void link_to_scene(unsigned short nr)
2590 {       
2591         Scene *sce= (Scene*) BLI_findlink(&G.main->scene, G.curscreen->scenenr-1);
2592         Base *base, *nbase;
2593         
2594         if(sce==0) return;
2595         if(sce->id.lib) return;
2596         
2597         base= FIRSTBASE;
2598         while(base) {
2599                 if(TESTBASE(base)) {
2600                         
2601                         nbase= MEM_mallocN( sizeof(Base), "newbase");
2602                         *nbase= *base;
2603                         BLI_addhead( &(sce->base), nbase);
2604                         id_us_plus((ID *)base->object);
2605                 }
2606                 base= base->next;
2607         }
2608 }
2609
2610 void make_links_menu()
2611 {
2612         Object *ob;
2613         short event=0;
2614         char str[140];
2615         
2616         if(!(ob=OBACT)) return;
2617         
2618         strcpy(str, "Make Links %t|To Scene...%x1|%l|Object Ipo%x4");
2619         
2620         if(ob->type==OB_MESH)
2621                 strcat(str, "|Mesh Data%x2|Materials%x3");
2622         else if(ob->type==OB_CURVE)
2623                 strcat(str, "|Curve Data%x2|Materials%x3");
2624         else if(ob->type==OB_FONT)
2625                 strcat(str, "|Text Data%x2|Materials%x3");
2626         else if(ob->type==OB_SURF)
2627                 strcat(str, "|Surface Data%x2|Materials%x3");
2628         else if(ob->type==OB_MBALL)
2629                 strcat(str, "|Materials%x3");
2630         else if(ob->type==OB_CAMERA)
2631                 strcat(str, "|Camera Data%x2");
2632         else if(ob->type==OB_LAMP)
2633                 strcat(str, "|Lamp Data%x2");
2634         else if(ob->type==OB_LATTICE)
2635                 strcat(str, "|Lattice Data%x2");
2636         else if(ob->type==OB_ARMATURE)
2637                 strcat(str, "|Armature Data%x2");
2638
2639         event= pupmenu(str);
2640
2641         if(event<= 0) return;
2642         
2643         make_links(event);
2644 }
2645
2646 void make_links(short event)
2647 {
2648         Object *ob, *obt;
2649         Base *base, *nbase, *sbase;
2650         Scene *sce = NULL;
2651         ID *id;
2652         Material ***matarar, ***obmatarar, **matar1, **matar2;
2653         int a;
2654         short *totcolp, nr;
2655         char *strp;
2656
2657         if(!(ob=OBACT)) return;
2658
2659         if(event==1) {
2660                 IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->scene), 0, &nr);
2661                 
2662                 if(strncmp(strp, "DataBrow", 8)==0) {
2663                         MEM_freeN(strp);
2664
2665                         activate_databrowse((ID *)G.scene, ID_SCE, 0, B_INFOSCE, &(G.curscreen->scenenr), link_to_scene );
2666                         
2667                         return;                 
2668                 }
2669                 else {
2670                         event= pupmenu(strp);
2671                         MEM_freeN(strp);
2672                 
2673                         if(event<= 0) return;
2674                 
2675                         nr= 1;
2676                         sce= G.main->scene.first;
2677                         while(sce) {
2678                                 if(nr==event) break;
2679                                 nr++;
2680                                 sce= sce->id.next;
2681                         }
2682                         if(sce==G.scene) {
2683                                 error("This is the current scene");
2684                                 return;
2685                         }
2686                         if(sce==0 || sce->id.lib) return;
2687                         
2688                         /* remember: is needed below */
2689                         event= 1;
2690                 }
2691         }
2692
2693         base= FIRSTBASE;
2694         while(base) {
2695                 if(event==1 || base != BASACT) {
2696                         
2697                         obt= base->object;
2698
2699                         if(TESTBASE(base)) {
2700                                 
2701                                 if(event==1) {          /* to scene */
2702                                         
2703                                         /* test if already linked */
2704                                         sbase= sce->base.first;
2705                                         while(sbase) {
2706                                                 if(sbase->object==base->object) break;
2707                                                 sbase= sbase->next;
2708                                         }
2709                                         if(sbase) {     /* remove */
2710                                                 base= base->next;
2711                                                 continue;
2712                                         }
2713                                         
2714                                         nbase= MEM_mallocN( sizeof(Base), "newbase");
2715                                         *nbase= *base;
2716                                         BLI_addhead( &(sce->base), nbase);
2717                                         id_us_plus((ID *)base->object);
2718                                 }
2719                         }
2720                         if(TESTBASELIB(base)) {
2721                                 if(event==2 || event==5) {  /* obdata */
2722                                         if(ob->type==obt->type) {
2723                                                 
2724                                                         id= obt->data;
2725                                                         id->us--;
2726                                                         
2727                                                         id= ob->data;
2728                                                         id_us_plus(id);
2729                                                         obt->data= id;
2730                                                         
2731                                                         /* if amount of material indices changed: */
2732                                                         test_object_materials(obt->data);
2733                                                 }
2734                                         }
2735                                 else if(event==4) {  /* ob ipo */
2736                                         if(obt->ipo) obt->ipo->id.us--;
2737                                         obt->ipo= ob->ipo;
2738                                         if(obt->ipo) {
2739                                                 id_us_plus((ID *)obt->ipo);
2740                                                 do_ob_ipo(obt);
2741                                         }
2742                                 }
2743                                 else if(event==3) {  /* materials */
2744                                         
2745                                         /* only if obt has no material: make arrays */
2746                                         /* from ob to obt! */
2747                                         
2748                                         obmatarar= give_matarar(ob);
2749                                         matarar= give_matarar(obt);
2750                                         totcolp= give_totcolp(obt);
2751
2752                                         /* if one of the two is zero: no render-able object */                                          
2753                                         if( matarar && obmatarar) {
2754                                                 
2755                                                 /* take care of users! so first a copy of original: */
2756
2757                                                 if(ob->totcol) {
2758                                                         matar1= MEM_dupallocN(ob->mat);
2759                                                         matar2= MEM_dupallocN(*obmatarar);
2760                                                 }
2761                                                 else {
2762                                                         matar1= matar2= 0;
2763                                                 }
2764                                                 
2765                                                 /* remove links from obt */
2766                                                 for(a=0; a<obt->totcol; a++) {
2767                                                         if(obt->mat[a]) obt->mat[a]->id.us--;
2768                                                         if( (*matarar)[a]) (*matarar)[a]->id.us--;
2769                                                 }
2770                                                 
2771                                                 /* free */
2772                                                 if(obt->mat) MEM_freeN(obt->mat);
2773                                                 if(*matarar) MEM_freeN(*matarar);
2774                                                 
2775                                                 /* connect a copy */
2776                                                 obt->mat= matar1;
2777                                                 *matarar= matar2;
2778                                                 obt->totcol= ob->totcol;
2779                                                 *totcolp= ob->totcol;
2780                                         
2781                                                 /* increase users */
2782                                                 for(a=0; a<obt->totcol; a++) {
2783                                                         if(obt->mat[a]) id_us_plus((ID *)obt->mat[a]);
2784                                                         if( (*matarar)[a]) id_us_plus((ID *)(*matarar)[a]);
2785                                                 }
2786
2787                                                 obt->colbits= ob->colbits;
2788                                                 
2789                                                 /* if amount of material indices changed: */
2790                                                 test_object_materials(obt->data);
2791                                         }
2792                                 }
2793                         }
2794                 }
2795                 base= base->next;
2796         }
2797         
2798         allqueue(REDRAWVIEW3D, 0);
2799         allqueue(REDRAWOOPS, 0);
2800         allqueue(REDRAWBUTSHEAD, 0);
2801         
2802         BIF_undo_push("Create links");
2803 }
2804
2805 void make_duplilist_real()
2806 {
2807         Base *base, *basen;
2808         Object *ob;
2809         extern ListBase duplilist;
2810         
2811         if(okee("Make dupli objects real")==0) return;
2812         
2813         base= FIRSTBASE;
2814         while(base) {
2815                 if TESTBASELIB(base) {
2816
2817                         if(base->object->transflag & OB_DUPLI) {
2818                                 
2819                                 make_duplilist(G.scene, base->object);
2820                                 ob= duplilist.first;
2821                                 while(ob) {
2822                                         
2823                                         /* font duplis can have a totcol without material, we get them from parent
2824                                          * should be implemented better...
2825                                          */
2826                                         if(ob->mat==0) ob->totcol= 0;
2827                                         
2828                                         basen= MEM_dupallocN(base);
2829                                         basen->flag &= ~OB_FROMDUPLI;
2830                                         BLI_addhead(&G.scene->base, basen);     /* addhead: othwise eternal loop */
2831                                         ob->ipo= 0;             /* make sure apply works */
2832                                         ob->parent= ob->track= 0;
2833                                         ob->disp.first= ob->disp.last= 0;
2834                                         ob->transflag &= ~OB_DUPLI;
2835                                         basen->object= copy_object(ob);
2836                                         
2837                                         apply_obmat(basen->object);
2838                                         ob= ob->id.next;
2839                                 }
2840                                 
2841                                 free_duplilist();
2842                                 
2843                                 base->object->transflag &= ~OB_DUPLI;   
2844                         }
2845                 }
2846                 base= base->next;
2847         }
2848         
2849         allqueue(REDRAWVIEW3D, 0);
2850         allqueue(REDRAWOOPS, 0);
2851         
2852         BIF_undo_push("Make duplicates real");
2853 }
2854
2855 void apply_object()
2856 {
2857         Base *base, *basact;
2858         Object *ob;
2859         Mesh *me;
2860         Curve *cu;
2861         Nurb *nu;
2862         BPoint *bp;
2863         BezTriple *bezt;
2864         MVert *mvert;
2865         float mat[3][3];
2866         int a;
2867
2868         if(G.scene->id.lib) return;
2869         if(G.obedit) return;
2870         basact= BASACT;
2871         
2872         if(G.qual & LR_SHIFTKEY) {
2873                 ob= OBACT;
2874                 if(ob==0) return;
2875                 
2876                 if(ob->transflag & OB_DUPLI) {
2877                         make_duplilist_real();
2878                 }
2879                 else {
2880                         if(okee("Apply deformation")) {
2881                                 object_apply_deform(ob);
2882                                 BIF_undo_push("Apply deformation");
2883                         }
2884                 }
2885                 allqueue(REDRAWVIEW3D, 0);
2886
2887                 return;
2888         }
2889
2890         if(okee("Apply size and rotation")==0) return;
2891
2892         base= FIRSTBASE;
2893         while(base) {
2894                 if TESTBASELIB(base) {
2895                         ob= base->object;
2896         
2897                         if(ob->type==OB_MESH) {
2898                                 object_to_mat3(ob, mat);
2899                                 me= ob->data;