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