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