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