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