4 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
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
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.
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.
23 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): none yet.
30 * ***** END GPL/BL DUAL LICENSE BLOCK *****
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
51 #include "MEM_guardedalloc.h"
57 #include "IMB_imbuf_types.h"
59 #include "DNA_action_types.h"
60 #include "DNA_armature_types.h"
61 #include "DNA_camera_types.h"
62 #include "DNA_constraint_types.h"
63 #include "DNA_curve_types.h"
64 #include "DNA_effect_types.h"
65 #include "DNA_image_types.h"
66 #include "DNA_ipo_types.h"
67 #include "DNA_key_types.h"
68 #include "DNA_lamp_types.h"
69 #include "DNA_lattice_types.h"
70 #include "DNA_material_types.h"
71 #include "DNA_mesh_types.h"
72 #include "DNA_meshdata_types.h"
73 #include "DNA_meta_types.h"
74 #include "DNA_object_types.h"
75 #include "DNA_object_force.h"
76 #include "DNA_scene_types.h"
77 #include "DNA_screen_types.h"
78 #include "DNA_texture_types.h"
79 #include "DNA_property_types.h"
80 #include "DNA_userdef_types.h"
81 #include "DNA_view3d_types.h"
82 #include "DNA_vfont_types.h"
83 #include "DNA_world_types.h"
84 #include "DNA_modifier_types.h"
86 #include "BLI_blenlib.h"
87 #include "BLI_arithb.h"
88 #include "BLI_editVert.h"
89 #include "BLI_ghash.h"
91 #include "BKE_action.h"
93 #include "BKE_armature.h"
94 #include "BKE_constraint.h"
95 #include "BKE_blender.h"
96 #include "BKE_booleanops.h"
97 #include "BKE_curve.h"
98 #include "BKE_displist.h"
99 #include "BKE_depsgraph.h"
100 #include "BKE_DerivedMesh.h"
101 #include "BKE_effect.h"
102 #include "BKE_font.h"
103 #include "BKE_global.h"
106 #include "BKE_lattice.h"
107 #include "BKE_library.h"
108 #include "BKE_main.h"
109 #include "BKE_material.h"
110 #include "BKE_mball.h"
111 #include "BKE_mesh.h"
113 #include "BKE_object.h"
114 #include "BKE_property.h"
116 #include "BKE_scene.h"
117 #include "BKE_softbody.h"
118 #include "BKE_subsurf.h"
119 #include "BKE_texture.h"
120 #include "BKE_utildefines.h"
121 #include "BKE_modifier.h"
124 #include "BIF_graphics.h"
125 #include "BIF_interface.h"
126 #include "BIF_mywindow.h"
127 #include "BIF_toolbox.h"
128 #include "BIF_screen.h"
129 #include "BIF_space.h"
130 #include "BIF_toets.h"
131 #include "BIF_butspace.h"
132 #include "BIF_editconstraint.h"
133 #include "BIF_editdeform.h"
134 #include "BIF_editfont.h"
135 #include "BIF_editlattice.h"
136 #include "BIF_editmesh.h"
137 #include "BIF_editoops.h"
138 #include "BIF_editview.h"
139 #include "BIF_editarmature.h"
140 #include "BIF_resources.h"
142 #include "BSE_edit.h"
143 #include "BSE_editipo.h"
144 #include "BSE_filesel.h" /* For activate_databrowse() */
145 #include "BSE_view.h"
146 #include "BSE_drawview.h"
147 #include "BSE_trans_types.h"
148 #include "BSE_editipo_types.h"
150 #include "BDR_vpaint.h"
151 #include "BDR_editmball.h"
152 #include "BDR_editobject.h"
153 #include "BDR_drawobject.h"
154 #include "BDR_editcurve.h"
155 #include "BDR_unwrapper.h"
158 #include "mydevice.h"
163 #include "BIF_transform.h"
165 #include "BIF_poseobject.h"
167 /* used in editipo, editcurve and here */
168 #define BEZSELECTED(bezt) (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
170 /* local prototypes -------------*/
172 /* --------------------------------- */
174 void add_object_draw(int type) /* for toolbox or menus, only non-editmode stuff */
178 G.f &= ~(G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT);
179 setcursor_space(SPACE_VIEW3D, CURSOR_STD);
181 if ELEM3(curarea->spacetype, SPACE_VIEW3D, SPACE_BUTS, SPACE_INFO) {
182 if (G.obedit) exit_editmode(2); // freedata, and undo
183 ob= add_object(type);
184 base_init_from_view3d(BASACT, G.vd);
186 /* only undo pushes on objects without editmode... */
187 if(type==OB_EMPTY) BIF_undo_push("Add Empty");
188 else if(type==OB_LAMP) {
189 BIF_undo_push("Add Lamp");
190 if(G.vd->drawtype == OB_SHADED) reshadeall_displist();
192 else if(type==OB_LATTICE) BIF_undo_push("Add Lattice");
193 else if(type==OB_CAMERA) BIF_undo_push("Add Camera");
195 allqueue(REDRAWVIEW3D, 0);
198 redraw_test_buttons(OBACT);
200 allqueue(REDRAWALL, 0);
202 deselect_all_area_oops();
203 set_select_flag_oops();
205 DAG_scene_sort(G.scene);
206 allqueue(REDRAWINFO, 1); /* 1, because header->win==0! */
209 void add_objectLamp(short type)
213 /* this function also comes from an info window */
214 if ELEM(curarea->spacetype, SPACE_VIEW3D, SPACE_INFO); else return;
217 add_object_draw(OB_LAMP);
218 base_init_from_view3d(BASACT, G.vd);
221 la = BASACT->object->data;
224 allqueue(REDRAWALL, 0);
227 /* note: now unlinks constraints as well */
228 void free_and_unlink_base(Base *base)
233 BLI_remlink(&G.scene->base, base);
234 free_libblock_us(&G.main->object, base->object);
238 void delete_obj(int ok)
244 if(G.scene->id.lib) return;
248 Base *nbase= base->next;
251 if(ok==0 && (ok=okee("Erase selected Object(s)"))==0) return;
252 if(base->object->type==OB_LAMP) islamp= 1;
254 free_and_unlink_base(base);
261 G.f &= ~(G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT);
262 setcursor_space(SPACE_VIEW3D, CURSOR_STD);
264 if(islamp && G.vd->drawtype==OB_SHADED) reshadeall_displist();
266 redraw_test_buttons(OBACT);
267 allqueue(REDRAWVIEW3D, 0);
268 allqueue (REDRAWACTION, 0);
269 allqueue(REDRAWIPO, 0);
270 allqueue(REDRAWDATASELECT, 0);
271 allqueue(REDRAWOOPS, 0);
272 allqueue(REDRAWACTION, 0);
273 allqueue(REDRAWNLA, 0);
275 DAG_scene_sort(G.scene);
277 BIF_undo_push("Delete object(s)");
280 static int return_editmesh_indexar(int **indexar, float *cent)
282 EditMesh *em = G.editMesh;
284 int *index, nr, totvert=0;
286 for(eve= em->verts.first; eve; eve= eve->next) {
287 if(eve->f & SELECT) totvert++;
289 if(totvert==0) return 0;
291 *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
293 cent[0]= cent[1]= cent[2]= 0.0;
295 for(eve= em->verts.first; eve; eve= eve->next) {
296 if(eve->f & SELECT) {
298 VecAddf(cent, cent, eve->co);
303 VecMulf(cent, 1.0f/(float)totvert);
308 static void select_editmesh_hook(HookModifierData *hmd)
310 EditMesh *em = G.editMesh;
314 for(eve= em->verts.first; eve; eve= eve->next, nr++) {
315 if(nr==hmd->indexar[index]) {
317 if(index < hmd->totindex-1) index++;
323 static int return_editlattice_indexar(int **indexar, float *cent)
326 int *index, nr, totvert=0, a;
329 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
332 if(bp->f1 & SELECT) {
333 if(bp->hide==0) totvert++;
338 if(totvert==0) return 0;
340 *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
342 cent[0]= cent[1]= cent[2]= 0.0;
344 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
347 if(bp->f1 & SELECT) {
350 VecAddf(cent, cent, bp->vec);
357 VecMulf(cent, 1.0f/(float)totvert);
362 static void select_editlattice_hook(HookModifierData *hmd)
365 int index=0, nr=0, a;
368 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
371 if(hmd->indexar[index]==nr) {
373 if(index < hmd->totindex-1) index++;
380 static int return_editcurve_indexar(int **indexar, float *cent)
382 extern ListBase editNurb;
386 int *index, a, nr, totvert=0;
388 for(nu= editNurb.first; nu; nu= nu->next) {
389 if((nu->type & 7)==CU_BEZIER) {
393 if(bezt->f1 & SELECT) totvert++;
394 if(bezt->f2 & SELECT) totvert++;
395 if(bezt->f3 & SELECT) totvert++;
401 a= nu->pntsu*nu->pntsv;
403 if(bp->f1 & SELECT) totvert++;
408 if(totvert==0) return 0;
410 *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
412 cent[0]= cent[1]= cent[2]= 0.0;
414 for(nu= editNurb.first; nu; nu= nu->next) {
415 if((nu->type & 7)==CU_BEZIER) {
419 if(bezt->f1 & SELECT) {
421 VecAddf(cent, cent, bezt->vec[0]);
424 if(bezt->f2 & SELECT) {
426 VecAddf(cent, cent, bezt->vec[1]);
429 if(bezt->f3 & SELECT) {
431 VecAddf(cent, cent, bezt->vec[2]);
439 a= nu->pntsu*nu->pntsv;
441 if(bp->f1 & SELECT) {
443 VecAddf(cent, cent, bp->vec);
451 VecMulf(cent, 1.0f/(float)totvert);
456 static void select_editcurve_hook(HookModifierData *hmd)
458 extern ListBase editNurb;
462 int index=0, a, nr=0;
464 for(nu= editNurb.first; nu; nu= nu->next) {
465 if((nu->type & 7)==CU_BEZIER) {
469 if(nr == hmd->indexar[index]) {
471 if(index<hmd->totindex-1) index++;
474 if(nr == hmd->indexar[index]) {
476 if(index<hmd->totindex-1) index++;
479 if(nr == hmd->indexar[index]) {
481 if(index<hmd->totindex-1) index++;
490 a= nu->pntsu*nu->pntsv;
492 if(nr == hmd->indexar[index]) {
494 if(index<hmd->totindex-1) index++;
503 void hook_select(HookModifierData *hmd)
505 if(G.obedit->type==OB_MESH) select_editmesh_hook(hmd);
506 else if(G.obedit->type==OB_LATTICE) select_editlattice_hook(hmd);
507 else if(G.obedit->type==OB_CURVE) select_editcurve_hook(hmd);
508 else if(G.obedit->type==OB_SURF) select_editcurve_hook(hmd);
510 int hook_getIndexArray(int **indexar, float *cent_r)
512 switch(G.obedit->type) {
514 return return_editmesh_indexar(indexar, cent_r);
517 return return_editcurve_indexar(indexar, cent_r);
519 return return_editlattice_indexar(indexar, cent_r);
527 ModifierData *md = NULL;
528 HookModifierData *hmd = NULL;
531 int tot=0, *indexar, mode;
533 if(G.obedit==NULL) return;
535 if(modifiers_findByType(G.obedit, eModifierType_Hook))
536 mode= pupmenu("Hooks %t|Add Hook, To New Empty %x1|Add Hook, To Selected Object %x2|Remove... %x3|Reassign... %x4|Select... %x5|Clear Offset...%x6");
538 mode= pupmenu("Hooks %t|Add, New Empty %x1|Add, To Selected Object %x2");
544 if(mode==2) { // selected object
545 Base *base= FIRSTBASE;
547 if TESTBASELIB(base) {
556 error("Requires selected Object");
564 // make pupmenu with hooks
565 for(md=G.obedit->modifiers.first; md; md= md->next) {
566 if (md->type==eModifierType_Hook)
571 error("Object has no hooks yet");
575 cp= MEM_callocN(maxlen+32, "temp string");
576 if(mode==3) strcpy(cp, "Remove %t|");
577 else if(mode==4) strcpy(cp, "Reassign %t|");
578 else if(mode==5) strcpy(cp, "Select %t|");
579 else if(mode==6) strcpy(cp, "Clear Offset %t|");
581 for(md=G.obedit->modifiers.first; md; md= md->next) {
582 if (md->type==eModifierType_Hook) {
583 strcat(cp, md->name);
594 for(md=G.obedit->modifiers.first; md; md=md->next) {
595 if (md->type==eModifierType_Hook) {
601 hmd = (HookModifierData*) md;
605 /* do it, new hooks or reassign */
606 if(mode==1 || mode==2 || mode==4) {
607 tot = hook_getIndexArray(&indexar, cent);
610 error("Requires selected vertices");
615 Base *base= BASACT, *newbase;
617 ob= add_object(OB_EMPTY);
620 newbase->lay= base->lay;
621 ob->lay= newbase->lay;
623 /* transform cent to global coords for loc */
624 VecMat4MulVecfl(ob->loc, G.obedit->obmat, cent);
626 /* restore, add_object sets active */
629 /* if mode is 2 or 4, ob has been set */
632 if(mode==1 || mode==2) {
633 ModifierData *md = G.obedit->modifiers.first;
635 while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
639 hmd = (HookModifierData*) modifier_new(eModifierType_Hook);
640 BLI_insertlinkbefore(&G.obedit->modifiers, md, hmd);
641 sprintf(hmd->modifier.name, "Hook-%s", ob->id.name+2);
643 else if (hmd->indexar) MEM_freeN(hmd->indexar); // reassign, hook was set
646 hmd->indexar= indexar;
647 VECCOPY(hmd->cent, cent);
650 if(mode==1 || mode==2) {
651 /* matrix calculus */
652 /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
657 Mat4Invert(ob->imat, ob->obmat);
658 /* apparently this call goes from right to left... */
659 Mat4MulSerie(hmd->parentinv, ob->imat, G.obedit->obmat, NULL,
660 NULL, NULL, NULL, NULL, NULL);
664 else if(mode==3) { // remove
665 BLI_remlink(&G.obedit->modifiers, md);
668 else if(mode==5) { // select
671 else if(mode==6) { // clear offset
672 where_is_object(ob); // ob is hook->parent
674 Mat4Invert(ob->imat, ob->obmat);
675 /* this call goes from right to left... */
676 Mat4MulSerie(hmd->parentinv, ob->imat, G.obedit->obmat, NULL,
677 NULL, NULL, NULL, NULL, NULL);
680 allqueue(REDRAWVIEW3D, 0);
681 allqueue(REDRAWBUTSOBJECT, 0);
682 DAG_scene_sort(G.scene);
684 BIF_undo_push("Add hook");
687 void make_track(void)
692 if(G.scene->id.lib) return;
696 if(BASACT==0) return;
698 mode= pupmenu("Make Track %t|TrackTo Constraint %x1|LockTrack Constraint %x2|Old Track %x3");
704 bTrackToConstraint *data;
708 if TESTBASELIB(base) {
710 con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
711 strcpy (con->name, "AutoTrack");
714 data->tar = BASACT->object;
715 base->object->recalc |= OB_RECALC;
717 /* Lamp and Camera track differently by default */
718 if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
719 data->reserved1 = TRACK_nZ;
720 data->reserved2 = UP_Y;
723 add_constraint_to_object(con, base->object);
732 bLockTrackConstraint *data;
736 if TESTBASELIB(base) {
738 con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
739 strcpy (con->name, "AutoTrack");
742 data->tar = BASACT->object;
743 base->object->recalc |= OB_RECALC;
745 /* Lamp and Camera track differently by default */
746 if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
747 data->trackflag = TRACK_nZ;
748 data->lockflag = LOCK_Y;
751 add_constraint_to_object(con, base->object);
761 if TESTBASELIB(base) {
763 base->object->track= BASACT->object;
764 base->object->recalc |= OB_RECALC;
771 allqueue(REDRAWOOPS, 0);
772 allqueue(REDRAWVIEW3D, 0);
773 DAG_scene_sort(G.scene);
775 BIF_undo_push("Make Track");
778 void apply_obmat(Object *ob)
780 float mat[3][3], imat[3][3], tmat[3][3];
782 /* from obmat to loc rot size */
785 Mat3CpyMat4(mat, ob->obmat);
787 VECCOPY(ob->loc, ob->obmat[3]);
789 if(ob->transflag & OB_QUAT) {
790 Mat3ToQuat(mat, ob->quat);
791 QuatToMat3(ob->quat, tmat);
794 Mat3ToEul(mat, ob->rot);
795 EulToMat3(ob->rot, tmat);
799 Mat3MulMat3(tmat, imat, mat);
801 ob->size[0]= tmat[0][0];
802 ob->size[1]= tmat[1][1];
803 ob->size[2]= tmat[2][2];
807 void clear_parent(void)
814 if(G.scene->id.lib) return;
816 mode= pupmenu("OK? %t|Clear Parent %x1|Clear and Keep Transformation (Clear Track) %x2|Clear Parent Inverse %x3");
822 if TESTBASELIB(base) {
824 if(mode==1 || mode==2) {
825 par= base->object->parent;
826 base->object->parent= NULL;
827 base->object->recalc |= OB_RECALC;
830 base->object->track= NULL;
831 apply_obmat(base->object);
835 Mat4One(base->object->parentinv);
836 base->object->recalc |= OB_RECALC;
842 DAG_scene_sort(G.scene);
843 DAG_scene_flush_update(G.scene);
844 allqueue(REDRAWVIEW3D, 0);
845 allqueue(REDRAWOOPS, 0);
847 BIF_undo_push("Clear Parent");
850 void clear_track(void)
856 if(G.scene->id.lib) return;
858 mode= pupmenu("OK? %t|Clear Track %x1| Clear Track and Keep Transform %x2");
864 if TESTBASELIB(base) {
865 base->object->track= NULL;
866 base->object->recalc |= OB_RECALC;
869 apply_obmat(base->object);
875 DAG_scene_sort(G.scene);
876 allqueue(REDRAWVIEW3D, 0);
877 allqueue(REDRAWOOPS, 0);
879 BIF_undo_push("Clear Track");
882 void clear_object(char mode)
886 float *v1, *v3, mat[3][3];
890 if(G.scene->id.lib) return;
892 if(mode=='r') str= "Clear rotation";
893 else if(mode=='g') str= "Clear location";
894 else if(mode=='s') str= "Clear size";
895 else if(mode=='o') str= "Clear origin";
900 if TESTBASELIB(base) {
903 if(ob->flag & OB_POSEMODE) {
904 // no test if we got armature; could be in future...
905 clear_armature(ob, mode);
910 memset(ob->rot, 0, 3*sizeof(float));
911 memset(ob->drot, 0, 3*sizeof(float));
916 memset(ob->loc, 0, 3*sizeof(float));
917 memset(ob->dloc, 0, 3*sizeof(float));
920 memset(ob->dsize, 0, 3*sizeof(float));
928 v3= ob->parentinv[3];
930 Mat3CpyMat4(mat, ob->parentinv);
935 Mat3MulVecfl(mat, v3);
939 ob->recalc |= OB_RECALC_OB;
945 allqueue(REDRAWVIEW3D, 0);
946 DAG_scene_flush_update(G.scene);
950 void reset_slowparents(void)
952 /* back to original locations */
957 if(base->object->parent) {
958 if(base->object->partype & PARSLOW) {
959 base->object->partype -= PARSLOW;
960 where_is_object(base->object);
961 base->object->partype |= PARSLOW;
968 void set_slowparent(void)
972 if( okee("Set slow parent")==0 ) return;
976 if TESTBASELIB(base) {
977 if(base->object->parent) base->object->partype |= PARSLOW;
981 BIF_undo_push("Slow parent");
984 void make_vertex_parent(void)
986 EditMesh *em = G.editMesh;
993 int a, v1=0, v2=0, v3=0, nr=1;
995 /* we need 1 to 3 selected vertices */
997 if(G.obedit->type==OB_MESH) {
998 eve= em->verts.first;
1002 else if(v2==0) v2= nr;
1003 else if(v3==0) v3= nr;
1010 else if ELEM(G.obedit->type, OB_SURF, OB_CURVE) {
1011 extern ListBase editNurb;
1014 if((nu->type & 7)==CU_BEZIER) {
1018 if(BEZSELECTED(bezt)) {
1020 else if(v2==0) v2= nr;
1021 else if(v3==0) v3= nr;
1030 a= nu->pntsu*nu->pntsv;
1032 if(bp->f1 & SELECT) {
1034 else if(v2==0) v2= nr;
1035 else if(v3==0) v3= nr;
1047 if( !(v1 && v2==0 && v3==0) && !(v1 && v2 && v3) ) {
1048 error("Select either 1 or 3 vertices to parent to");
1052 if(okee("Make vertex parent")==0) return;
1056 if TESTBASELIB(base) {
1060 ob->recalc |= OB_RECALC;
1061 par= BASACT->object->parent;
1068 error("Loop in parents");
1071 ob->parent= BASACT->object;
1073 ob->partype= PARVERT3;
1078 /* inverse parent matrix */
1079 what_does_parent(ob);
1080 Mat4Invert(ob->parentinv, workob.obmat);
1084 ob->partype= PARVERT1;
1087 /* inverse parent matrix */
1088 what_does_parent(ob);
1089 Mat4Invert(ob->parentinv, workob.obmat);
1097 allqueue(REDRAWVIEW3D, 0);
1099 DAG_scene_sort(G.scene);
1100 // BIF_undo_push(str); not, conflicts with editmode undo...
1103 int test_parent_loop(Object *par, Object *ob)
1105 /* test if 'ob' is a parent somewhere in par's parents */
1107 if(par==0) return 0;
1108 if(ob == par) return 1;
1110 return test_parent_loop(par->parent, ob);
1114 static char *make_bone_menu (Object *ob)
1117 bPoseChannel *pchan;
1122 for(size=0, pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next, size++);
1124 size = size*48 + 256;
1125 menustr = MEM_callocN(size, "bonemenu");
1127 sprintf (menustr, "Select Bone%%t");
1129 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next, index++) {
1130 sprintf (menustr, "%s|%s%%x%d", menustr, pchan->bone->name, index);
1137 void make_parent(void)
1144 if(G.scene->id.lib) return;
1146 if ELEM3(G.obedit->type, OB_MESH, OB_CURVE, OB_SURF) make_vertex_parent();
1147 else if (G.obedit->type==OB_ARMATURE) make_bone_parent();
1150 if(BASACT==0) return;
1153 par= BASACT->object;
1155 if(par->type == OB_LATTICE){
1156 mode= pupmenu("Make Parent %t|Normal Parent %x1|Lattice Deform %x2");
1167 else if(par->type == OB_CURVE){
1169 bFollowPathConstraint *data;
1171 mode= pupmenu("Make Parent %t|Normal Parent %x1|Follow Path %x2|Curve Deform %x3|Path Constraint %x4");
1179 Curve *cu= par->data;
1182 if((cu->flag & CU_PATH)==0) {
1183 cu->flag |= CU_PATH|CU_FOLLOW;
1184 makeDispListCurveTypes(par, 0); // force creation of path data
1186 else cu->flag |= CU_FOLLOW;
1195 if TESTBASELIB(base) {
1197 float cmat[4][4], vec[3], size[3];
1199 con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
1200 strcpy (con->name, "AutoPath");
1203 data->tar = BASACT->object;
1205 add_constraint_to_object(con, base->object);
1207 get_constraint_target_matrix(con, TARGET_OBJECT, NULL, cmat, size, G.scene->r.cfra - base->object->sf);
1208 VecSubf(vec, base->object->obmat[3], cmat[3]);
1210 base->object->loc[0] = vec[0];
1211 base->object->loc[1] = vec[1];
1212 base->object->loc[2] = vec[2];
1218 allqueue(REDRAWVIEW3D, 0);
1219 DAG_scene_sort(G.scene);
1220 BIF_undo_push("make Parent");
1224 else if(par->type == OB_ARMATURE){
1230 if TESTBASELIB(base) {
1232 if(base->object->type==OB_MESH) {
1233 mode= pupmenu("Make Parent To%t|Bone %x1|Armature %x2|Object %x3");
1237 mode= pupmenu("Make Parent To %t|Bone %x1|Object %x3");
1248 /* Make bone popup menu */
1250 bonestr = make_bone_menu(par);
1252 bonenr= pupmenu_col(bonestr, 20);
1254 MEM_freeN (bonestr);
1257 allqueue(REDRAWVIEW3D, 0);
1261 bone= get_indexed_bone(par, bonenr<<16); // function uses selection codes
1263 allqueue(REDRAWVIEW3D, 0);
1279 if(qual & LR_SHIFTKEY) {
1280 if(okee("Make parent without inverse")==0) return;
1283 if(qual & LR_ALTKEY) {
1284 if(okee("Make vertex parent")==0) return;
1286 else if(okee("Make parent")==0) return;
1288 /* now we'll clearparentandkeeptransform all objects */
1291 if TESTBASELIB(base) {
1292 if(base!=BASACT && base->object->parent) {
1293 base->object->parent= NULL;
1294 apply_obmat(base->object);
1302 par->recalc |= OB_RECALC_OB;
1306 if TESTBASELIB(base) {
1309 if( test_parent_loop(par, base->object) ) {
1310 error("Loop in parents");
1314 base->object->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
1316 /* the ifs below are horrible code (ton) */
1318 if (par->type==OB_ARMATURE) {
1319 base->object->partype= mode;
1321 strcpy (base->object->parsubstr, bone->name);
1323 base->object->parsubstr[0]=0;
1326 if(qual & LR_ALTKEY) {
1327 base->object->partype= PARVERT1;
1329 else if(ELEM(par->type, OB_CURVE, OB_LATTICE)) {
1330 base->object->partype= mode;
1333 base->object->partype= PAROBJECT;
1337 base->object->parent= par;
1339 /* calculate inverse parent matrix? */
1340 if( (qual & LR_SHIFTKEY) ) {
1342 Mat4One(base->object->parentinv);
1343 memset(base->object->loc, 0, 3*sizeof(float));
1346 if(mode==PARSKEL && par->type == OB_ARMATURE) {
1347 /* Prompt the user as to whether he wants to
1348 * add some vertex groups based on the bones
1349 * in the parent armature.
1351 create_vgroups_from_armature(base->object,
1354 base->object->partype= PAROBJECT;
1355 what_does_parent(base->object);
1356 Mat4One (base->object->parentinv);
1357 base->object->partype= mode;
1360 what_does_parent(base->object);
1361 Mat4Invert(base->object->parentinv, workob.obmat);
1364 if(par->type==OB_ARMATURE && mode == PARSKEL){
1365 verify_defgroups(base->object);
1372 allqueue(REDRAWVIEW3D, 0);
1373 allqueue(REDRAWOOPS, 0);
1375 DAG_scene_sort(G.scene);
1376 DAG_scene_flush_update(G.scene);
1378 BIF_undo_push("make Parent");
1382 void enter_editmode(void)
1391 if(G.scene->id.lib) return;
1394 if((G.vd==NULL || (base->lay & G.vd->lay))==0) return;
1396 strcpy(G.editModeTitleExtra, "");
1399 if(ob->data==0) return;
1403 error("Can't edit library data");
1407 if(ob->type==OB_MESH) {
1411 error("Can't edit library data");
1417 allqueue(REDRAWBUTSLOGIC, 0);
1418 if(G.f & G_FACESELECT) allqueue(REDRAWIMAGE, 0);
1420 if (ob->type==OB_ARMATURE){
1421 arm=base->object->data;
1424 error("Can't edit library data");
1429 make_editArmature();
1430 allqueue (REDRAWVIEW3D,0);
1432 else if(ob->type==OB_FONT) {
1437 else if(ob->type==OB_MBALL) {
1442 else if(ob->type==OB_LATTICE) {
1447 else if(ob->type==OB_SURF || ob->type==OB_CURVE) {
1452 allqueue(REDRAWBUTSEDIT, 0);
1453 allqueue(REDRAWOOPS, 0);
1457 setcursor_space(SPACE_VIEW3D, CURSOR_EDIT);
1459 allqueue(REDRAWVIEW3D, 1);
1460 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1463 else G.obedit= NULL;
1465 scrarea_queue_headredraw(curarea);
1468 void exit_editmode(int freedata) /* freedata==0 at render, 1= freedata, 2= do undo buffer too */
1472 if(G.obedit==NULL) return;
1474 if(G.obedit->type==OB_MESH) {
1479 if(G.totvert>MESH_MAX_VERTS) {
1480 error("Too many vertices");
1485 if(freedata) free_editMesh(G.editMesh);
1487 if(G.f & G_FACESELECT) {
1489 allqueue(REDRAWIMAGE, 0);
1492 else if (G.obedit->type==OB_ARMATURE){
1493 load_editArmature();
1494 if (freedata) free_editArmature();
1496 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
1497 extern ListBase editNurb;
1499 if(freedata) freeNurblist(&editNurb);
1501 else if(G.obedit->type==OB_FONT && freedata) {
1504 else if(G.obedit->type==OB_LATTICE) {
1506 if(freedata) free_editLatt();
1508 else if(G.obedit->type==OB_MBALL) {
1509 extern ListBase editelems;
1511 if(freedata) BLI_freelistN(&editelems);
1516 /* for example; displist make is different in editmode */
1517 if(freedata) G.obedit= NULL;
1519 /* total remake of softbody data */
1520 if(modifiers_isSoftbodyEnabled(ob)) {
1521 if (ob->soft && ob->soft->keys) {
1522 notice("Erased Baked SoftBody");
1525 sbObjectToSoftbody(ob);
1527 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1530 setcursor_space(SPACE_VIEW3D, CURSOR_STD);
1533 allqueue(REDRAWVIEW3D, 1);
1534 allqueue(REDRAWBUTSEDIT, 0);
1535 allqueue(REDRAWBUTSLOGIC, 0);
1536 allqueue(REDRAWOOPS, 0);
1538 scrarea_queue_headredraw(curarea);
1540 if(G.obedit==NULL && freedata==2)
1541 BIF_undo_push("Editmode");
1544 void check_editmode(int type)
1547 if (G.obedit==0 || G.obedit->type==type) return;
1549 exit_editmode(2); // freedata, and undo
1552 /* 0 == do centre, 1 == centre new, 2 == centre cursor */
1554 void docentre(int centremode)
1556 EditMesh *em = G.editMesh;
1565 float cent[3], centn[3], min[3], max[3], omat[3][3];
1569 if(G.scene->id.lib) return;
1571 cent[0]= cent[1]= cent[2]= 0.0;
1575 INIT_MINMAX(min, max);
1577 if(G.obedit->type==OB_MESH) {
1578 for(eve= em->verts.first; eve; eve= eve->next) {
1579 if(G.vd->around==V3D_CENTROID) {
1581 VECADD(cent, cent, eve->co);
1584 DO_MINMAX(eve->co, min, max);
1588 if(G.vd->around==V3D_CENTROID) {
1589 VecMulf(cent, 1.0f/(float)total);
1592 cent[0]= (min[0]+max[0])/2.0f;
1593 cent[1]= (min[1]+max[1])/2.0f;
1594 cent[2]= (min[2]+max[2])/2.0f;
1597 for(eve= em->verts.first; eve; eve= eve->next) {
1598 VecSubf(eve->co, eve->co, cent);
1601 recalc_editnormals();
1608 if TESTBASELIB(base) {
1609 base->object->flag &= ~OB_DONE;
1613 me= G.main->mesh.first;
1615 me->flag &= ~ME_ISDONE;
1622 if TESTBASELIB(base) {
1623 if((base->object->flag & OB_DONE)==0) {
1625 base->object->flag |= OB_DONE;
1627 if(G.obedit==0 && (me=get_mesh(base->object)) ) {
1630 error("Can't change the center of a mesh with vertex keys");
1635 VECCOPY(cent, give_cursor());
1636 Mat4Invert(base->object->imat, base->object->obmat);
1637 Mat4MulVecfl(base->object->imat, cent);
1639 INIT_MINMAX(min, max);
1642 for(a=0; a<me->totvert; a++, mvert++) {
1643 DO_MINMAX(mvert->co, min, max);
1646 cent[0]= (min[0]+max[0])/2.0f;
1647 cent[1]= (min[1]+max[1])/2.0f;
1648 cent[2]= (min[2]+max[2])/2.0f;
1652 for(a=0; a<me->totvert; a++, mvert++) {
1653 VecSubf(mvert->co, mvert->co, cent);
1655 me->flag |= ME_ISDONE;
1658 Mat3CpyMat4(omat, base->object->obmat);
1660 VECCOPY(centn, cent);
1661 Mat3MulVecfl(omat, centn);
1662 base->object->loc[0]+= centn[0];
1663 base->object->loc[1]+= centn[1];
1664 base->object->loc[2]+= centn[2];
1667 ob= G.main->object.first;
1669 if((ob->flag & OB_DONE)==0) {
1674 ob->flag |= OB_DONE;
1676 Mat3CpyMat4(omat, ob->obmat);
1677 VECCOPY(centn, cent);
1678 Mat3MulVecfl(omat, centn);
1679 ob->loc[0]+= centn[0];
1680 ob->loc[1]+= centn[1];
1681 ob->loc[2]+= centn[2];
1683 if(tme && (tme->flag & ME_ISDONE)==0) {
1685 for(a=0; a<tme->totvert; a++, mvert++) {
1686 VecSubf(mvert->co, mvert->co, cent);
1688 tme->flag |= ME_ISDONE;
1697 else if ELEM(base->object->type, OB_CURVE, OB_SURF) {
1700 extern ListBase editNurb;
1701 nu1= editNurb.first;
1704 cu= base->object->data;
1705 nu1= cu->nurb.first;
1709 VECCOPY(cent, give_cursor());
1710 Mat4Invert(base->object->imat, base->object->obmat);
1711 Mat4MulVecfl(base->object->imat, cent);
1713 /* Curves need to be 2d, never offset in
1714 * Z. Is a somewhat arbitrary restriction,
1715 * would probably be nice to remove.
1719 INIT_MINMAX(min, max);
1723 minmaxNurb(nu, min, max);
1727 cent[0]= (min[0]+max[0])/2.0f;
1728 cent[1]= (min[1]+max[1])/2.0f;
1729 cent[2]= (min[2]+max[2])/2.0f;
1734 if( (nu->type & 7)==1) {
1737 VecSubf(nu->bezt[a].vec[0], nu->bezt[a].vec[0], cent);
1738 VecSubf(nu->bezt[a].vec[1], nu->bezt[a].vec[1], cent);
1739 VecSubf(nu->bezt[a].vec[2], nu->bezt[a].vec[2], cent);
1743 a= nu->pntsu*nu->pntsv;
1745 VecSubf(nu->bp[a].vec, nu->bp[a].vec, cent);
1750 if(centremode && G.obedit==0) {
1751 Mat3CpyMat4(omat, base->object->obmat);
1753 Mat3MulVecfl(omat, cent);
1754 base->object->loc[0]+= cent[0];
1755 base->object->loc[1]+= cent[1];
1756 base->object->loc[2]+= cent[2];
1764 else if(base->object->type==OB_FONT) {
1767 cu= base->object->data;
1768 if(cu->bb==0) return;
1770 cu->xof= -0.5f*( cu->bb->vec[4][0] - cu->bb->vec[0][0]);
1771 cu->yof= -0.5f -0.5f*( cu->bb->vec[0][1] - cu->bb->vec[2][1]); /* extra 0.5 is the height of above line */
1773 /* not really ok, do this better once! */
1774 cu->xof /= cu->fsize;
1775 cu->yof /= cu->fsize;
1777 allqueue(REDRAWBUTSEDIT, 0);
1779 base->object->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
1785 allqueue(REDRAWVIEW3D, 0);
1786 DAG_scene_flush_update(G.scene);
1787 BIF_undo_push("Do Centre");
1790 void docentre_new(void)
1792 if(G.scene->id.lib) return;
1795 error("Unable to center new in Edit Mode");
1802 void docentre_cursor(void)
1804 if(G.scene->id.lib) return;
1807 error("Unable to center cursor in Edit Mode");
1814 void movetolayer(void)
1817 unsigned int lay= 0, local;
1820 if(G.scene->id.lib) return;
1824 if TESTBASE(base) lay |= base->lay;
1830 if( movetolayer_buts(&lay)==0 ) return;
1836 /* upper byte is used for local view */
1837 local= base->lay & 0xFF000000;
1838 base->lay= lay + local;
1839 base->object->lay= lay;
1840 if(base->object->type==OB_LAMP) islamp= 1;
1845 if(islamp && G.vd->drawtype == OB_SHADED) reshadeall_displist();
1848 allqueue(REDRAWBUTSEDIT, 0);
1849 allqueue(REDRAWVIEW3D, 0);
1850 allqueue(REDRAWOOPS, 0);
1851 allqueue(REDRAWINFO, 0);
1853 BIF_undo_push("Move to layer");
1859 Base *oldbase = BASACT;
1860 Curve *cu= ob->data;
1862 int slen= strlen(p);
1865 for (i = 0; i<=slen; p++, i++) {
1869 text_to_curve(OBACT, 0); // pass 1: only one letter, adapt position
1870 text_to_curve(OBACT, 0); // pass 2: remake
1871 freedisplist(&OBACT->disp);
1872 makeDispListCurveTypes(OBACT, 0);
1874 OBACT->flag &= ~SELECT;
1875 BASACT->flag &= ~SELECT;
1876 oldbase->flag |= SELECT;
1877 oldbase->object->flag |= SELECT;
1878 set_active_base(oldbase);
1882 void special_editmenu(void)
1885 extern short editbutflag;
1886 extern float doublimit;
1889 short randfac,numcuts;
1891 if(ob==NULL) return;
1893 if(G.obedit==NULL) {
1895 if(ob->flag & OB_POSEMODE) {
1896 pose_special_editmenu();
1898 else if(G.f & G_FACESELECT) {
1899 Mesh *me= get_mesh(ob);
1903 if(me==0 || me->tface==0) return;
1905 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");
1907 for(a=me->totface, tface= me->tface; a>0; a--, tface++) {
1908 if(tface->flag & SELECT) {
1911 tface->mode |= TF_TEX; break;
1913 tface->mode |= TF_SHAREDCOL; break;
1915 tface->mode |= TF_LIGHT; break;
1917 tface->mode |= TF_INVISIBLE; break;
1919 tface->mode |= TF_DYNAMIC; break;
1921 tface->mode &= ~TF_TEX;
1925 tface->mode &= ~TF_SHAREDCOL; break;
1927 tface->mode &= ~TF_LIGHT; break;
1929 tface->mode &= ~TF_INVISIBLE; break;
1931 tface->mode &= ~TF_DYNAMIC; break;
1935 allqueue(REDRAWVIEW3D, 0);
1936 allqueue(REDRAWBUTSEDIT, 0);
1937 BIF_undo_push("Change texture face");
1939 else if(G.f & G_VERTEXPAINT) {
1940 Mesh *me= get_mesh(ob);
1942 if(me==0 || (me->mcol==NULL && me->tface==NULL) ) return;
1944 nr= pupmenu("Specials%t|Shared VertexCol%x1");
1947 if(me->tface) tface_to_mcol(me);
1949 copy_vpaint_undo( (unsigned int *)me->mcol, me->totface);
1950 do_shared_vertexcol(me);
1952 if(me->tface) mcol_to_tface(me, 1);
1953 BIF_undo_push("Shared VertexCol");
1955 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1958 else if(G.f & G_WEIGHTPAINT) {
1959 if(ob->parent && (ob->parent->flag & OB_POSEMODE)) {
1960 nr= pupmenu("Specials%t|Apply Bone Envelopes to VertexGroups %x1");
1963 copy_wpaint_undo(me->dvert, me->totvert);
1964 pose_adds_vgroups(ob);
1969 Base *base, *base_select= NULL;
1971 // Get the active object mesh.
1972 Mesh *me= get_mesh(ob);
1974 // Booleans, if the active object is a mesh...
1975 if (me && ob->id.lib==NULL) {
1977 // Bring up a little menu with the boolean operation choices on.
1978 nr= pupmenu("Boolean %t|Intersect%x1|Union%x2|Difference%x3");
1980 // user has made a choice of a menu element.
1981 // All of the boolean functions require 2 mesh objects
1982 // we search through the object list to find the other
1983 // selected item and make sure it is distinct and a mesh.
1985 for(base= FIRSTBASE; base; base= base->next) {
1986 if TESTBASELIB(base) {
1987 if(base->object != ob) base_select= base;
1992 if (get_mesh(base_select->object)) {
1994 ret = NewBooleanMesh(BASACT,base_select,nr);
1996 error("An internal error occurred -- sorry!");
1997 } else if(ret==-1) {
1998 error("Selected meshes must have faces to perform boolean operations");
2000 else BIF_undo_push("Boolean");
2004 error("Please select 2 meshes");
2007 error("Please select 2 meshes");
2011 allqueue(REDRAWVIEW3D, 0);
2013 else if (ob->type == OB_FONT) {
2014 nr= pupmenu("Split %t|Characters%x1");
2017 case 1: split_font();
2023 else if(G.obedit->type==OB_MESH) {
2025 nr= pupmenu("Specials%t|Subdivide%x1|Subdivide Multi%x2|Subdivide Multi Fractal%x3|Subdivide Multi Smooth - WIP%x12|Subdivide Smooth Old%x13|Merge%x4|Remove Doubles%x5|Hide%x6|Reveal%x7|Select Swap%x8|Flip Normals %x9|Smooth %x10|Bevel %x11");
2031 esubdivideflag(1, 0.0, editbutflag,numcuts,0);
2033 BIF_undo_push("ESubdivide Single");
2037 if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
2039 esubdivideflag(1, 0.0, editbutflag,numcuts,0);
2040 BIF_undo_push("ESubdivide");
2044 if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
2047 if(button(&randfac, 1, 100, "Rand fac:")==0) return;
2048 fac= -( (float)randfac )/100;
2049 esubdivideflag(1, fac, editbutflag,numcuts,0);
2050 BIF_undo_push("Subdivide Fractal");
2057 notice("Removed %d Vertices", removedoublesflag(1, doublimit));
2058 BIF_undo_push("Remove Doubles");
2071 BIF_undo_push("Flip Normals");
2081 if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
2083 esubdivideflag(1, 0.0, editbutflag | B_SMOOTH,numcuts,0);
2084 BIF_undo_push("Subdivide Smooth");
2088 subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
2089 BIF_undo_push("Subdivide Smooth");
2093 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2095 if(nr>0) waitcursor(0);
2098 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
2100 nr= pupmenu("Specials%t|Subdivide%x1|Switch Direction%x2");
2107 switchdirectionNurb2();
2111 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2113 else if(G.obedit->type==OB_ARMATURE) {
2114 nr= pupmenu("Specials%t|Flip Left-Right Names%x1");
2116 armature_flip_names();
2121 allqueue(REDRAWVIEW3D, 0);
2125 void convertmenu(void)
2127 Base *base, *basen, *basact, *basedel=NULL;
2133 int ok=0, nr = 0, a;
2135 if(G.scene->id.lib) return;
2139 if(G.obedit) return;
2141 basact= BASACT; /* will be restored */
2143 if(ob->type==OB_FONT) {
2144 nr= pupmenu("Convert Font to%t|Curve");
2147 else if(ob->type==OB_MBALL) {
2148 nr= pupmenu("Convert Metaball to%t|Mesh (keep original)%x1|Mesh (Delete Original)%x2");
2151 else if(ob->type==OB_CURVE) {
2152 nr= pupmenu("Convert Curve to%t|Mesh");
2155 else if(ob->type==OB_SURF) {
2156 nr= pupmenu("Convert Nurbs Surface to%t|Mesh");
2159 else if(ob->type==OB_MESH) {
2160 nr= pupmenu("Convert Modifiers to%t|Mesh (Keep Original)%x1|Mesh (Delete Original)%x2");
2165 /* don't forget multiple users! */
2170 if TESTBASELIB(base) {
2171 base->object->flag &= ~OB_DONE;
2178 if TESTBASELIB(base) {
2182 if(ob->flag & OB_DONE);
2183 else if(ob->type==OB_MESH) {
2184 Mesh *oldme= ob->data;
2190 ob->flag |= OB_DONE;
2192 ob1= copy_object(ob);
2193 ob1->recalc |= OB_RECALC;
2194 object_free_modifiers(ob1);
2196 basen= MEM_mallocN(sizeof(Base), "duplibase");
2198 BLI_addhead(&G.scene->base, basen); /* addhead: otherwise eternal loop */
2200 basen->flag &= ~SELECT;
2205 ob1->data= add_mesh();
2210 me->totcol= oldme->totcol;
2212 me->mat= MEM_dupallocN(oldme->mat);
2213 for(a=0; a<ob1->totcol; a++) id_us_plus((ID *)me->mat[a]);
2216 dm= mesh_create_derived_no_deform(ob, NULL);
2217 dlm= dm->convertToDispListMesh(dm, 0);
2218 displistmesh_to_mesh(dlm, ob1->data);
2221 else if(ob->type==OB_FONT) {
2224 ob->flag |= OB_DONE;
2234 cu->vfontb->id.us--;
2238 cu->vfonti->id.us--;
2242 cu->vfontbi->id.us--;
2247 ob1= G.main->object.first;
2250 ob1->type= OB_CURVE;
2251 ob1->recalc |= OB_RECALC;
2258 else if ELEM(ob->type, OB_CURVE, OB_SURF) {
2261 ob->flag |= OB_DONE;
2265 if(dl==0) makeDispListCurveTypes(ob, 0); // force creation
2267 nurbs_to_mesh(ob); /* also does users */
2269 /* texspace and normals */
2272 exit_editmode(1); // freedata, but no undo
2276 else if(ob->type==OB_MBALL) {
2278 if(nr==1 || nr == 2) {
2279 ob= find_basis_mball(ob);
2281 if(ob->disp.first && !(ob->flag&OB_DONE)) {
2284 ob->flag |= OB_DONE;
2286 ob1= copy_object(ob);
2287 ob1->recalc |= OB_RECALC;
2289 basen= MEM_mallocN(sizeof(Base), "duplibase");
2291 BLI_addhead(&G.scene->base, basen); /* addhead: othwise eternal loop */
2293 basen->flag &= ~SELECT;
2298 ob1->data= add_mesh();
2303 me->totcol= mb->totcol;
2305 me->mat= MEM_dupallocN(mb->mat);
2306 for(a=0; a<ob1->totcol; a++) id_us_plus((ID *)me->mat[a]);
2309 mball_to_mesh(&ob->disp, ob1->data);
2315 if(basedel != NULL && nr == 2)
2316 free_and_unlink_base(basedel);
2321 allqueue(REDRAWVIEW3D, 0);
2322 allqueue(REDRAWOOPS, 0);
2323 allqueue(REDRAWBUTSEDIT, 0);
2324 BIF_undo_push("Convert Object");
2326 DAG_scene_sort(G.scene);
2329 /* Change subdivision properties of mesh object ob, if
2330 * level==-1 then toggle subsurf, else set to level.
2332 void flip_subdivison(Object *ob, int level)
2334 ModifierData *md = modifiers_findByType(ob, eModifierType_Subsurf);
2337 SubsurfModifierData *smd = (SubsurfModifierData*) md;
2340 if (smd->modifier.mode&(eModifierMode_Render|eModifierMode_Realtime)) {
2341 smd->modifier.mode &= ~(eModifierMode_Render|eModifierMode_Realtime);
2343 smd->modifier.mode |= (eModifierMode_Render|eModifierMode_Realtime);
2346 smd->levels = level;
2349 SubsurfModifierData *smd = (SubsurfModifierData*) modifier_new(eModifierType_Subsurf);
2351 BLI_addtail(&ob->modifiers, smd);
2354 smd->levels = level;
2358 allqueue(REDRAWVIEW3D, 0);
2359 allqueue(REDRAWOOPS, 0);
2360 allqueue(REDRAWBUTSEDIT, 0);
2361 allqueue(REDRAWBUTSOBJECT, 0);
2362 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2364 BIF_undo_push("Switch subsurf on/off");
2367 static void copymenu_properties(Object *ob)
2369 bProperty *prop, *propn, *propc;
2374 prop= ob->prop.first;
2381 error("No properties in the active object to copy");
2385 str= MEM_callocN(24+32*tot, "copymenu prop");
2387 strcpy(str, "Copy Property %t");
2390 prop= ob->prop.first;
2394 strcat(str, prop->name);
2401 prop= ob->prop.first;
2412 if(base != BASACT) {
2413 if(TESTBASELIB(base)) {
2414 prop= get_property(base->object, propc->name);
2416 free_property(prop);
2417 BLI_remlink(&base->object->prop, prop);
2419 propn= copy_property(propc);
2420 BLI_addtail(&base->object->prop, propn);
2428 allqueue(REDRAWVIEW3D, 0);
2430 BIF_undo_push("Copy properties");
2433 static void copymenu_logicbricks(Object *ob)
2439 if(base->object != ob) {
2440 if(TESTBASELIB(base)) {
2442 /* first: free all logic */
2443 free_sensors(&base->object->sensors);
2444 unlink_controllers(&base->object->controllers);
2445 free_controllers(&base->object->controllers);
2446 unlink_actuators(&base->object->actuators);
2447 free_actuators(&base->object->actuators);
2449 /* now copy it, this also works without logicbricks! */
2450 clear_sca_new_poins_ob(ob);
2451 copy_sensors(&base->object->sensors, &ob->sensors);
2452 copy_controllers(&base->object->controllers, &ob->controllers);
2453 copy_actuators(&base->object->actuators, &ob->actuators);
2454 set_sca_new_poins_ob(base->object);
2456 /* some menu settings */
2457 base->object->scavisflag= ob->scavisflag;
2458 base->object->scaflag= ob->scaflag;
2464 BIF_undo_push("Copy logic");
2467 static void copymenu_modifiers(Object *ob)
2473 strcpy(str, "Copy Modifiers %t");
2475 sprintf(str+strlen(str), "|All%%x%d|%%l", NUM_MODIFIER_TYPES);
2477 for (i=eModifierType_None+1; i<NUM_MODIFIER_TYPES; i++) {
2478 ModifierTypeInfo *mti = modifierType_getInfo(i);
2480 if (ELEM(i, eModifierType_Hook, eModifierType_Softbody)) continue;
2482 if ( (mti->flags&eModifierTypeFlag_AcceptsCVs) ||
2483 (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
2484 sprintf(str+strlen(str), "|%s%%x%d", mti->name, i);
2488 event = pupmenu(str);
2489 if(event<=0) return;
2491 for (base= FIRSTBASE; base; base= base->next) {
2492 if(base->object != ob) {
2493 if(TESTBASELIB(base)) {
2496 base->object->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
2498 if (base->object->type==OB_MESH) {
2499 if (event==NUM_MODIFIER_TYPES) {
2500 object_free_modifiers(base->object);
2502 for (md=ob->modifiers.first; md; md=md->next) {
2503 if (md->type!=eModifierType_Hook) {
2504 ModifierData *nmd = modifier_new(md->type);
2505 modifier_copyData(md, nmd);
2506 BLI_addtail(&base->object->modifiers, nmd);
2510 ModifierData *md = modifiers_findByType(ob, event);
2513 ModifierData *tmd = modifiers_findByType(base->object, event);
2516 tmd = modifier_new(event);
2517 BLI_addtail(&base->object->modifiers, tmd);
2520 modifier_copyData(md, tmd);
2528 allqueue(REDRAWVIEW3D, 0);
2529 allqueue(REDRAWBUTSOBJECT, 0);
2530 DAG_scene_sort(G.scene);
2532 BIF_undo_push("Copy modifiers");
2535 void copy_attr_menu()
2541 /* If you change this menu, don't forget to update the menu in header_view3d.c
2542 * view3d_edit_object_copyattrmenu() and in toolbox.c
2544 strcpy(str, "Copy Attributes %t|Location%x1|Rotation%x2|Size%x3|Drawtype%x4|Time Offset%x5|Dupli%x6|%l|Mass%x7|Damping%x8|Properties%x9|Logic Bricks%x10|%l");
2546 if(!(ob=OBACT)) return;
2548 strcat (str, "|Object Constraints%x22");
2550 if ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) {
2551 strcat(str, "|Texture Space%x17");
2554 if(ob->type == OB_FONT) strcat(str, "|Font Settings%x18|Bevel Settings%x19");
2555 if(ob->type == OB_CURVE) strcat(str, "|Bevel Settings%x19");
2557 if(ob->type==OB_MESH){
2558 strcat(str, "|Subdiv%x21");
2561 if( give_parteff(ob) ) strcat(str, "|Particle Settings%x20");
2563 if(ob->soft) strcat(str, "|Soft Body Settings%x23");
2565 if(ob->type==OB_MESH){
2566 strcat(str, "|Modifiers ...%x24");
2569 event= pupmenu(str);
2570 if(event<= 0) return;
2575 void copy_attr(short event)
2580 void *poin1, *poin2=0;
2582 if(G.scene->id.lib) return;
2584 if(!(ob=OBACT)) return;
2587 /* obedit_copymenu(); */
2591 if ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) {
2592 if(ob->type==OB_MESH) poin2= &(((Mesh *)ob->data)->texflag);
2593 else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) poin2= &(((Curve *)ob->data)->texflag);
2594 else if(ob->type==OB_MBALL) poin2= &(((MetaBall *)ob->data)->texflag);
2598 copymenu_properties(ob);
2601 else if(event==10) {
2602 copymenu_logicbricks(ob);
2605 else if(event==24) {
2606 copymenu_modifiers(ob);
2612 if(base != BASACT) {
2613 if(TESTBASELIB(base)) {
2614 base->object->recalc |= OB_RECALC_OB;
2616 if(event==1) { /* loc */
2617 VECCOPY(base->object->loc, ob->loc);
2618 VECCOPY(base->object->dloc, ob->dloc);
2620 else if(event==2) { /* rot */
2621 VECCOPY(base->object->rot, ob->rot);
2622 VECCOPY(base->object->drot, ob->drot);
2623 VECCOPY(base->object->quat, ob->quat);
2624 VECCOPY(base->object->dquat, ob->dquat);
2626 else if(event==3) { /* size */
2627 VECCOPY(base->object->size, ob->size);
2628 VECCOPY(base->object->dsize, ob->dsize);
2630 else if(event==4) { /* drawtype */
2631 base->object->dt= ob->dt;
2632 base->object->dtx= ob->dtx;
2634 else if(event==5) { /* time offs */
2635 base->object->sf= ob->sf;
2637 else if(event==6) { /* dupli */
2638 base->object->dupon= ob->dupon;
2639 base->object->dupoff= ob->dupoff;
2640 base->object->dupsta= ob->dupsta;
2641 base->object->dupend= ob->dupend;
2643 base->object->transflag &= ~OB_DUPLI;
2644 base->object->transflag |= (ob->transflag & OB_DUPLI);
2646 else if(event==7) { /* mass */
2647 base->object->mass= ob->mass;
2649 else if(event==8) { /* damping */
2650 base->object->damping= ob->damping;
2651 base->object->rdamping= ob->rdamping;
2653 else if(event==17) { /* tex space */
2656 if(obt->type==OB_MESH) poin1= &(((Mesh *)obt->data)->texflag);
2657 else if ELEM3(obt->type, OB_CURVE, OB_SURF, OB_FONT) poin1= &(((Curve *)obt->data)->texflag);
2658 else if(obt->type==OB_MBALL) poin1= &(((MetaBall *)obt->data)->texflag);
2661 memcpy(poin1, poin2, 4+12+12+12);
2663 if(obt->type==OB_MESH) ;
2664 else if(obt->type==OB_MBALL) tex_space_mball(obt);
2665 else tex_space_curve(obt->data);
2668 else if(event==18) { /* font settings */
2670 if(base->object->type==ob->type) {
2672 cu1= base->object->data;
2674 cu1->spacemode= cu->spacemode;
2675 cu1->spacing= cu->spacing;
2676 cu1->linedist= cu->linedist;
2677 cu1->shear= cu->shear;
2678 cu1->fsize= cu->fsize;
2681 cu1->textoncurve= cu->textoncurve;
2682 if(cu1->vfont) cu1->vfont->id.us--;
2683 cu1->vfont= cu->vfont;
2684 id_us_plus((ID *)cu1->vfont);
2685 if(cu1->vfontb) cu1->vfontb->id.us--;
2686 cu1->vfontb= cu->vfontb;
2687 id_us_plus((ID *)cu1->vfontb);
2688 if(cu1->vfonti) cu1->vfonti->id.us--;
2689 cu1->vfonti= cu->vfonti;
2690 id_us_plus((ID *)cu1->vfonti);
2691 if(cu1->vfontbi) cu1->vfontbi->id.us--;
2692 cu1->vfontbi= cu->vfontbi;
2693 id_us_plus((ID *)cu1->vfontbi);
2695 text_to_curve(base->object, 0); // needed?
2698 strcpy(cu1->family, cu->family);
2700 base->object->recalc |= OB_RECALC_DATA;
2703 else if(event==19) { /* bevel settings */
2705 if ELEM(base->object->type, OB_CURVE, OB_FONT) {
2707 cu1= base->object->data;
2709 cu1->bevobj= cu->bevobj;
2710 cu1->taperobj= cu->taperobj;
2711 cu1->width= cu->width;
2712 cu1->bevresol= cu->bevresol;
2713 cu1->ext1= cu->ext1;
2714 cu1->ext2= cu->ext2;
2716 base->object->recalc |= OB_RECALC_DATA;
2719 else if(event==20) { /* particle settings */
2723 pa1= give_parteff(ob);
2724 pa2= give_parteff(base->object);
2727 BLI_remlink( &(base->object->effect), pa2);
2728 free_effect( (Effect *) pa2);
2730 else if(pa1 && pa2==0) {
2731 free_effects(&(base->object->effect));
2732 copy_effects(&(base->object->effect), &ob->effect);
2733 build_particle_system(base->object);
2735 else if(pa1 && pa2) {
2736 if(pa2->keys) MEM_freeN(pa2->keys);
2738 p1= (char *)pa1; p2= (char *)pa2;
2739 memcpy( p2+8, p1+8, sizeof(PartEff) - 8);
2742 build_particle_system(base->object);
2746 if (base->object->type==OB_MESH) {
2747 ModifierData *md = modifiers_findByType(ob, eModifierType_Subsurf);
2750 ModifierData *tmd = modifiers_findByType(base->object, eModifierType_Subsurf);
2753 tmd = modifier_new(eModifierType_Subsurf);
2754 BLI_addtail(&base->object->modifiers, tmd);
2757 modifier_copyData(md, tmd);
2758 base->object->recalc |= OB_RECALC_DATA;
2762 else if(event==22) {
2763 /* Clear the constraints on the target */
2764 free_constraints(&base->object->constraints);
2765 free_constraint_channels(&base->object->constraintChannels);
2767 /* Copy the constraint channels over */
2768 copy_constraints(&base->object->constraints, &ob->constraints);
2769 if (U.dupflag& USER_DUP_IPO)
2770 copy_constraint_channels(&base->object->constraintChannels, &ob->constraintChannels);
2772 clone_constraint_channels (&base->object->constraintChannels, &ob->constraintChannels, NULL);
2774 base->object->activecon = NULL;
2776 else if(event==23) {
2777 base->object->softflag= ob->softflag;
2778 if(base->object->soft) sbFree(base->object->soft);
2780 base->object->soft= copy_softbody(ob->soft);
2782 if (!modifiers_findByType(base->object, eModifierType_Softbody)) {
2783 BLI_addhead(&base->object->modifiers, modifier_new(eModifierType_Softbody));
2791 allqueue(REDRAWVIEW3D, 0);
2792 DAG_scene_flush_update(G.scene);
2795 allqueue(REDRAWBUTSOBJECT, 0);
2798 BIF_undo_push("Copy attributes");
2801 void link_to_scene(unsigned short nr)
2803 Scene *sce= (Scene*) BLI_findlink(&G.main->scene, G.curscreen->scenenr-1);
2807 if(sce->id.lib) return;
2811 if(TESTBASE(base)) {
2813 nbase= MEM_mallocN( sizeof(Base), "newbase");
2815 BLI_addhead( &(sce->base), nbase);
2816 id_us_plus((ID *)base->object);
2822 void make_links_menu()
2828 if(!(ob=OBACT)) return;
2830 strcpy(str, "Make Links %t|To Scene...%x1|%l|Object Ipo%x4");
2832 if(ob->type==OB_MESH)
2833 strcat(str, "|Mesh Data%x2|Materials%x3");
2834 else if(ob->type==OB_CURVE)
2835 strcat(str, "|Curve Data%x2|Materials%x3");
2836 else if(ob->type==OB_FONT)
2837 strcat(str, "|Text Data%x2|Materials%x3");
2838 else if(ob->type==OB_SURF)
2839 strcat(str, "|Surface Data%x2|Materials%x3");
2840 else if(ob->type==OB_MBALL)
2841 strcat(str, "|Materials%x3");
2842 else if(ob->type==OB_CAMERA)
2843 strcat(str, "|Camera Data%x2");
2844 else if(ob->type==OB_LAMP)
2845 strcat(str, "|Lamp Data%x2");
2846 else if(ob->type==OB_LATTICE)
2847 strcat(str, "|Lattice Data%x2");
2848 else if(ob->type==OB_ARMATURE)
2849 strcat(str, "|Armature Data%x2");
2851 event= pupmenu(str);
2853 if(event<= 0) return;
2858 void make_links(short event)
2861 Base *base, *nbase, *sbase;
2864 Material ***matarar, ***obmatarar, **matar1, **matar2;
2869 if(!(ob=OBACT)) return;
2872 IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->scene), 0, &nr);
2874 if(strncmp(strp, "DataBrow", 8)==0) {
2877 activate_databrowse((ID *)G.scene, ID_SCE, 0, B_INFOSCE, &(G.curscreen->scenenr), link_to_scene );
2882 event= pupmenu(strp);
2885 if(event<= 0) return;
2888 sce= G.main->scene.first;
2890 if(nr==event) break;
2895 error("This is the current scene");
2898 if(sce==0 || sce->id.lib) return;
2900 /* remember: is needed below */
2907 if(event==1 || base != BASACT) {
2911 if(TESTBASE(base)) {
2913 if(event==1) { /* to scene */
2915 /* test if already linked */
2916 sbase= sce->base.first;
2918 if(sbase->object==base->object) break;
2921 if(sbase) { /* remove */