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