2.50: svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r19323...
[blender.git] / source / blender / editors / object / object_edit.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL 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.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, 2002-2008 full recode
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27 #include <stdlib.h>
28 #include <string.h>
29 #include <math.h>
30 #include <time.h>
31
32 #include "MEM_guardedalloc.h"
33
34 #include "IMB_imbuf_types.h"
35
36 #include "DNA_action_types.h"
37 #include "DNA_armature_types.h"
38 #include "DNA_camera_types.h"
39 #include "DNA_constraint_types.h"
40 #include "DNA_curve_types.h"
41 #include "DNA_effect_types.h"
42 #include "DNA_group_types.h"
43 #include "DNA_image_types.h"
44 #include "DNA_key_types.h"
45 #include "DNA_lamp_types.h"
46 #include "DNA_lattice_types.h"
47 #include "DNA_material_types.h"
48 #include "DNA_mesh_types.h"
49 #include "DNA_meshdata_types.h"
50 #include "DNA_meta_types.h"
51 #include "DNA_nla_types.h"
52 #include "DNA_object_types.h"
53 #include "DNA_object_fluidsim.h"
54 #include "DNA_object_force.h"
55 #include "DNA_scene_types.h"
56 #include "DNA_space_types.h"
57 #include "DNA_screen_types.h"
58 #include "DNA_texture_types.h"
59 #include "DNA_particle_types.h"
60 #include "DNA_property_types.h"
61 #include "DNA_userdef_types.h"
62 #include "DNA_view3d_types.h"
63 #include "DNA_vfont_types.h"
64 #include "DNA_world_types.h"
65 #include "DNA_modifier_types.h"
66
67 #include "BLI_blenlib.h"
68 #include "BLI_arithb.h"
69 #include "BLI_editVert.h"
70 #include "BLI_ghash.h"
71 #include "BLI_rand.h"
72
73 #include "BKE_action.h"
74 #include "BKE_anim.h"
75 #include "BKE_armature.h"
76 #include "BKE_booleanops.h"
77 #include "BKE_constraint.h"
78 #include "BKE_context.h"
79 #include "BKE_customdata.h"
80 #include "BKE_blender.h"
81 #include "BKE_booleanops.h"
82 #include "BKE_cloth.h"
83 #include "BKE_curve.h"
84 #include "BKE_displist.h"
85 #include "BKE_depsgraph.h"
86 #include "BKE_DerivedMesh.h"
87 #include "BKE_effect.h"
88 #include "BKE_font.h"
89 #include "BKE_global.h"
90 #include "BKE_group.h"
91 #include "BKE_image.h"
92 #include "BKE_key.h"
93 #include "BKE_lattice.h"
94 #include "BKE_library.h"
95 #include "BKE_main.h"
96 #include "BKE_material.h"
97 #include "BKE_mball.h"
98 #include "BKE_mesh.h"
99 #include "BKE_nla.h"
100 #include "BKE_object.h"
101 #include "BKE_particle.h"
102 #include "BKE_property.h"
103 #include "BKE_report.h"
104 #include "BKE_sca.h"
105 #include "BKE_scene.h"
106 #include "BKE_softbody.h"
107 #include "BKE_subsurf.h"
108 #include "BKE_texture.h"
109 #include "BKE_utildefines.h"
110 #include "BKE_modifier.h"
111
112 #include "ED_anim_api.h"
113 #include "ED_armature.h"
114 #include "ED_curve.h"
115 #include "ED_particle.h"
116 #include "ED_mesh.h"
117 #include "ED_object.h"
118 #include "ED_screen.h"
119 #include "ED_types.h"
120 #include "ED_util.h"
121 #include "ED_view3d.h"
122
123 #include "BMF_Api.h"
124
125 #include "BIF_transform.h"
126
127 #include "UI_interface.h"
128
129 #include "RNA_access.h"
130 #include "RNA_define.h"
131
132 /* for menu/popup icons etc etc*/
133 #include "UI_interface.h"
134 #include "UI_resources.h"
135
136 #include "WM_api.h"
137 #include "WM_types.h"
138
139 #include "object_intern.h"      // own include
140
141 /* ************* XXX **************** */
142 static void error() {}
143 static void waitcursor() {}
144 static int pupmenu() {return 0;}
145 static int pupmenu_col() {return 0;}
146 static int okee() {return 0;}
147
148 /* port over here */
149 static bContext *C;
150 static void error_libdata() {}
151
152 /* ********************************** */
153
154 /* --------------------------------- */
155
156 /* simple API for object selection, rather than just using the flag
157  * this takes into account the 'restrict selection in 3d view' flag.
158  * deselect works always, the restriction just prevents selection */
159
160 /* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! */
161
162 void ED_base_object_select(Base *base, short mode)
163 {
164         if (base) {
165                 if (mode==BA_SELECT) {
166                         if (!(base->object->restrictflag & OB_RESTRICT_SELECT))
167                                 if (mode==BA_SELECT) base->flag |= SELECT;
168                 }
169                 else if (mode==BA_DESELECT) {
170                         base->flag &= ~SELECT;
171                 }
172                 base->object->flag= base->flag;
173         }
174 }
175
176 /* also to set active NULL */
177 void ED_base_object_activate(bContext *C, Base *base)
178 {
179         Scene *scene= CTX_data_scene(C);
180         Base *tbase;
181         
182         /* activating a non-mesh, should end a couple of modes... */
183         if(base && base->object->type!=OB_MESH)
184                 ED_view3d_exit_paint_modes(C);
185         
186         /* sets scene->basact */
187         BASACT= base;
188         
189         if(base) {
190                 
191                 /* XXX old signals, remember to handle notifiers now! */
192                 //              select_actionchannel_by_name(base->object->action, "Object", 1);
193                 
194                 /* disable temporal locks */
195                 for(tbase=FIRSTBASE; tbase; tbase= tbase->next) {
196                         if(base!=tbase && (tbase->object->shapeflag & OB_SHAPE_TEMPLOCK)) {
197                                 tbase->object->shapeflag &= ~OB_SHAPE_TEMPLOCK;
198                                 DAG_object_flush_update(scene, tbase->object, OB_RECALC_DATA);
199                         }
200                 }
201                 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
202         }
203         else
204                 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, NULL);
205 }
206
207
208 /*
209  * Returns true if the Object data is a from an external blend file (libdata)
210  */
211 int object_data_is_libdata(Object *ob)
212 {
213         if (!ob) return 0;
214         if (ob->proxy) return 0;
215         if (ob->id.lib) return 1;
216         if (!ob->data) return 0;
217         if (((ID *)ob->data)->lib) return 1;
218         return 0;
219 }
220
221
222
223 /* exported */
224 void ED_object_base_init_from_view(bContext *C, Base *base)
225 {
226         View3D *v3d= CTX_wm_view3d(C);
227         Scene *scene= CTX_data_scene(C);
228         Object *ob= base->object;
229         
230         if (scene==NULL)
231                 return;
232         
233         if (v3d==NULL) {
234                 base->lay = scene->lay;
235                 VECCOPY(ob->loc, scene->cursor);
236         } 
237         else {
238                 if (v3d->localview) {
239                         base->lay= ob->lay= v3d->layact | v3d->lay;
240                         VECCOPY(ob->loc, v3d->cursor);
241                 } 
242                 else {
243                         base->lay= ob->lay= v3d->layact;
244                         VECCOPY(ob->loc, scene->cursor);
245                 }
246                 
247                 if (U.flag & USER_ADD_VIEWALIGNED) {
248                         ARegion *ar= CTX_wm_region(C);
249                         if(ar) {
250                                 RegionView3D *rv3d= ar->regiondata;
251                                 
252                                 rv3d->viewquat[0]= -rv3d->viewquat[0];
253                                 QuatToEul(rv3d->viewquat, ob->rot);
254                                 rv3d->viewquat[0]= -rv3d->viewquat[0];
255                         }
256                 }
257         }
258         where_is_object(scene, ob);
259 }
260
261 /* ******************* add object operator ****************** */
262
263 static EnumPropertyItem prop_object_types[] = {
264         {OB_EMPTY, "EMPTY", "Empty", ""},
265         {OB_MESH, "MESH", "Mesh", ""},
266         {OB_CURVE, "CURVE", "Curve", ""},
267         {OB_SURF, "SURFACE", "Surface", ""},
268         {OB_FONT, "TEXT", "Text", ""},
269         {OB_MBALL, "META", "Meta", ""},
270         {OB_LAMP, "LAMP", "Lamp", ""},
271         {OB_CAMERA, "CAMERA", "Camera", ""},
272         {OB_ARMATURE, "ARMATURE", "Armature", ""},
273         {OB_LATTICE, "LATTICE", "Lattice", ""},
274         {0, NULL, NULL, NULL}
275 };
276
277
278
279 void add_object_draw(Scene *scene, View3D *v3d, int type)       /* for toolbox or menus, only non-editmode stuff */
280 {
281         /* keep here to get things compile, remove later */
282 }
283
284 /* for object add primitive operators */
285 static Object *object_add_type(bContext *C, int type)
286 {
287         Scene *scene= CTX_data_scene(C);
288         Object *ob;
289         
290         /* XXX hrms, this is editor level operator, remove? */
291         ED_view3d_exit_paint_modes(C);
292         
293         /* for as long scene has editmode... */
294         if (CTX_data_edit_object(C)) 
295                 ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* freedata, and undo */
296         
297         /* deselects all, sets scene->basact */
298         ob= add_object(scene, type);
299         /* editor level activate, notifiers */
300         ED_base_object_activate(C, BASACT);
301         
302         /* more editor stuff */
303         ED_object_base_init_from_view(C, BASACT);
304         
305         DAG_scene_sort(scene);
306         
307         return ob;
308 }
309
310 /* for object add operator */
311 static int object_add_exec(bContext *C, wmOperator *op)
312 {
313         object_add_type(C, RNA_int_get(op->ptr, "type"));
314         
315         return OPERATOR_FINISHED;
316 }
317
318 void OBJECT_OT_object_add(wmOperatorType *ot)
319 {
320         /* identifiers */
321         ot->name= "Add Object";
322         ot->description = "Add an object to the scene.";
323         ot->idname= "OBJECT_OT_object_add";
324         
325         /* api callbacks */
326         ot->invoke= WM_menu_invoke;
327         ot->exec= object_add_exec;
328         
329         ot->poll= ED_operator_scene_editable;
330         
331         /* flags */
332         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
333         
334         RNA_def_enum(ot->srna, "type", prop_object_types, 0, "Type", "");
335 }
336
337 /* ***************** add primitives *************** */
338 /* ******  work both in and outside editmode ****** */
339
340 static EnumPropertyItem prop_mesh_types[] = {
341         {0, "PLANE", "Plane", ""},
342         {1, "CUBE", "Cube", ""},
343         {2, "CIRCLE", "Circle", ""},
344         {3, "UVSPHERE", "UVsphere", ""},
345         {4, "ICOSPHERE", "Icosphere", ""},
346         {5, "CYLINDER", "Cylinder", ""},
347         {6, "CONE", "Cone", ""},
348         {7, "GRID", "Grid", ""},
349         {8, "MONKEY", "Monkey", ""},
350         {0, NULL, NULL, NULL}
351 };
352
353 static int object_add_mesh_exec(bContext *C, wmOperator *op)
354 {
355         Object *obedit= CTX_data_edit_object(C);
356         int newob= 0;
357         
358         if(obedit==NULL || obedit->type!=OB_MESH) {
359                 object_add_type(C, OB_MESH);
360                 ED_object_enter_editmode(C, 0);
361                 newob = 1;
362         }
363         else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
364
365         switch(RNA_enum_get(op->ptr, "type")) {
366                 case 0:
367                         WM_operator_name_call(C, "MESH_OT_primitive_plane_add", WM_OP_INVOKE_REGION_WIN, NULL);
368                         break;
369                 case 1:
370                         WM_operator_name_call(C, "MESH_OT_primitive_cube_add", WM_OP_INVOKE_REGION_WIN, NULL);
371                         break;
372                 case 2:
373                         WM_operator_name_call(C, "MESH_OT_primitive_circle_add", WM_OP_INVOKE_REGION_WIN, NULL);
374                         break;
375                 case 3:
376                         WM_operator_name_call(C, "MESH_OT_primitive_uv_sphere_add", WM_OP_INVOKE_REGION_WIN, NULL);
377                         break;
378                 case 4:
379                         WM_operator_name_call(C, "MESH_OT_primitive_ico_sphere_add", WM_OP_INVOKE_REGION_WIN, NULL);
380                         break;
381                 case 5:
382                         WM_operator_name_call(C, "MESH_OT_primitive_cylinder_add", WM_OP_INVOKE_REGION_WIN, NULL);
383                         break;
384                 case 6:
385                         WM_operator_name_call(C, "MESH_OT_primitive_cone_add", WM_OP_INVOKE_REGION_WIN, NULL);
386                         break;
387                 case 7:
388                         WM_operator_name_call(C, "MESH_OT_primitive_grid_add", WM_OP_INVOKE_REGION_WIN, NULL);
389                         break;
390                 case 8:
391                         WM_operator_name_call(C, "MESH_OT_primitive_monkey_add", WM_OP_INVOKE_REGION_WIN, NULL);
392                         break;
393         }
394         /* userdef */
395         if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
396                 ED_object_exit_editmode(C, EM_FREEDATA);
397         }
398         
399         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
400         
401         return OPERATOR_FINISHED;
402 }
403
404
405 void OBJECT_OT_mesh_add(wmOperatorType *ot)
406 {
407         /* identifiers */
408         ot->name= "Add Mesh";
409         ot->description = "Add a mesh object to the scene.";
410         ot->idname= "OBJECT_OT_mesh_add";
411         
412         /* api callbacks */
413         ot->invoke= WM_menu_invoke;
414         ot->exec= object_add_mesh_exec;
415         
416         ot->poll= ED_operator_scene_editable;
417         
418         /* flags */
419         ot->flag= 0;
420         
421         RNA_def_enum(ot->srna, "type", prop_mesh_types, 0, "Primitive", "");
422 }
423
424 static EnumPropertyItem prop_curve_types[] = {
425         {CU_BEZIER|CU_2D|CU_PRIM_CURVE, "BEZIER_CURVE", "Bezier Curve", ""},
426         {CU_BEZIER|CU_2D|CU_PRIM_CIRCLE, "BEZIER_CIRCLE", "Bezier Circle", ""},
427         {CU_NURBS|CU_2D|CU_PRIM_CURVE, "NURBS_CURVE", "NURBS Curve", ""},
428         {CU_NURBS|CU_2D|CU_PRIM_CIRCLE, "NURBS_CIRCLE", "NURBS Circle", ""},
429         {CU_NURBS|CU_2D|CU_PRIM_PATH, "PATH", "Path", ""},
430         {0, NULL, NULL, NULL}
431 };
432
433 static int object_add_curve_exec(bContext *C, wmOperator *op)
434 {
435         Object *obedit= CTX_data_edit_object(C);
436         ListBase *editnurb;
437         Nurb *nu;
438         int newob= 0;
439         
440         if(obedit==NULL || obedit->type!=OB_CURVE) {
441                 object_add_type(C, OB_CURVE);
442                 ED_object_enter_editmode(C, 0);
443                 newob = 1;
444         }
445         else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
446         
447         obedit= CTX_data_edit_object(C);
448         nu= add_nurbs_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
449         editnurb= curve_get_editcurve(obedit);
450         BLI_addtail(editnurb, nu);
451         
452         /* userdef */
453         if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
454                 ED_object_exit_editmode(C, EM_FREEDATA);
455         }
456         
457         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
458         
459         return OPERATOR_FINISHED;
460 }
461
462 static int object_add_curve_invoke(bContext *C, wmOperator *op, wmEvent *event)
463 {
464         Object *obedit= CTX_data_edit_object(C);
465         uiMenuItem *head;
466
467         head= uiPupMenuBegin(op->type->name, 0);
468         if(!obedit || obedit->type == OB_CURVE)
469                 uiMenuItemsEnumO(head, op->type->idname, "type");
470         else
471                 uiMenuItemsEnumO(head, "OBJECT_OT_surface_add", "type");
472         uiPupMenuEnd(C, head);
473
474         return OPERATOR_CANCELLED;
475 }
476
477 void OBJECT_OT_curve_add(wmOperatorType *ot)
478 {
479         /* identifiers */
480         ot->name= "Add Curve";
481         ot->description = "Add a curve object to the scene.";
482         ot->idname= "OBJECT_OT_curve_add";
483         
484         /* api callbacks */
485         ot->invoke= object_add_curve_invoke;
486         ot->exec= object_add_curve_exec;
487         
488         ot->poll= ED_operator_scene_editable;
489         
490         /* flags */
491         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
492         
493         RNA_def_enum(ot->srna, "type", prop_curve_types, 0, "Primitive", "");
494 }
495
496 static EnumPropertyItem prop_surface_types[]= {
497         {CU_PRIM_CURVE|CU_NURBS, "NURBS_CURVE", "NURBS Curve", ""},
498         {CU_PRIM_CIRCLE|CU_NURBS, "NURBS_CIRCLE", "NURBS Circle", ""},
499         {CU_PRIM_PATCH|CU_NURBS, "NURBS_SURFACE", "NURBS Surface", ""},
500         {CU_PRIM_TUBE|CU_NURBS, "NURBS_TUBE", "NURBS Tube", ""},
501         {CU_PRIM_SPHERE|CU_NURBS, "NURBS_SPHERE", "NURBS Sphere", ""},
502         {CU_PRIM_DONUT|CU_NURBS, "NURBS_DONUT", "NURBS Donut", ""},
503         {0, NULL, NULL, NULL}
504 };
505
506 static int object_add_surface_exec(bContext *C, wmOperator *op)
507 {
508         Object *obedit= CTX_data_edit_object(C);
509         ListBase *editnurb;
510         Nurb *nu;
511         int newob= 0;
512         
513         if(obedit==NULL || obedit->type!=OB_SURF) {
514                 object_add_type(C, OB_SURF);
515                 ED_object_enter_editmode(C, 0);
516                 newob = 1;
517         }
518         else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
519         
520         obedit= CTX_data_edit_object(C);
521         nu= add_nurbs_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
522         editnurb= curve_get_editcurve(obedit);
523         BLI_addtail(editnurb, nu);
524         
525         /* userdef */
526         if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
527                 ED_object_exit_editmode(C, EM_FREEDATA);
528         }
529         
530         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
531         
532         return OPERATOR_FINISHED;
533 }
534
535 void OBJECT_OT_surface_add(wmOperatorType *ot)
536 {
537         /* identifiers */
538         ot->name= "Add Surface";
539         ot->description = "Add a surface object to the scene.";
540         ot->idname= "OBJECT_OT_surface_add";
541         
542         /* api callbacks */
543         ot->invoke= WM_menu_invoke;
544         ot->exec= object_add_surface_exec;
545         
546         ot->poll= ED_operator_scene_editable;
547         
548         /* flags */
549         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
550         
551         RNA_def_enum(ot->srna, "type", prop_surface_types, 0, "Primitive", "");
552 }
553
554 static int object_add_text_exec(bContext *C, wmOperator *op)
555 {
556         Object *obedit= CTX_data_edit_object(C);
557         
558         if(obedit && obedit->type==OB_FONT)
559                 return OPERATOR_CANCELLED;
560
561         object_add_type(C, OB_FONT);
562         obedit= CTX_data_active_object(C);
563
564         if(U.flag & USER_ADD_EDITMODE)
565                 ED_object_enter_editmode(C, 0);
566         
567         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
568         
569         return OPERATOR_FINISHED;
570 }
571
572 void OBJECT_OT_text_add(wmOperatorType *ot)
573 {
574         /* identifiers */
575         ot->name= "Add Text";
576         ot->description = "Add a text object to the scene";
577         ot->idname= "OBJECT_OT_text_add";
578         
579         /* api callbacks */
580         ot->exec= object_add_text_exec;
581         ot->poll= ED_operator_scene_editable;
582         
583         /* flags */
584         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
585 }
586
587 static int object_armature_add_exec(bContext *C, wmOperator *op)
588 {
589         Object *obedit= CTX_data_edit_object(C);
590         View3D *v3d= CTX_wm_view3d(C);
591         RegionView3D *rv3d= NULL;
592         int newob= 0;
593         
594         if ((obedit==NULL) || (obedit->type != OB_ARMATURE)) {
595                 object_add_type(C, OB_ARMATURE);
596                 ED_object_enter_editmode(C, 0);
597                 newob = 1;
598         }
599         else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
600         
601         if(v3d) 
602                 rv3d= CTX_wm_region(C)->regiondata;
603         
604         /* v3d and rv3d are allowed to be NULL */
605         add_primitive_bone(CTX_data_scene(C), v3d, rv3d);
606
607         /* userdef */
608         if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
609                 ED_object_exit_editmode(C, EM_FREEDATA);
610         }
611         
612         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
613         
614         return OPERATOR_FINISHED;
615 }
616
617 void OBJECT_OT_armature_add(wmOperatorType *ot)
618 {       
619         /* identifiers */
620         ot->name= "Add Armature";
621         ot->description = "Add an armature object to the scene.";
622         ot->idname= "OBJECT_OT_armature_add";
623         
624         /* api callbacks */
625         ot->exec= object_armature_add_exec;
626         ot->poll= ED_operator_scene_editable;
627         
628         /* flags */
629         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
630 }
631
632
633 static int object_primitive_add_invoke(bContext *C, wmOperator *op, wmEvent *event)
634 {
635         uiMenuItem *head= uiPupMenuBegin("Add Object", 0);
636         
637         uiMenuLevelEnumO(head, "OBJECT_OT_mesh_add", "type");
638         uiMenuLevelEnumO(head, "OBJECT_OT_curve_add", "type");
639         uiMenuLevelEnumO(head, "OBJECT_OT_surface_add", "type");
640         uiMenuItemO(head, 0, "OBJECT_OT_text_add");
641         uiMenuItemEnumO(head, "", 0, "OBJECT_OT_object_add", "type", OB_MBALL);
642         uiMenuItemEnumO(head, "", 0, "OBJECT_OT_object_add", "type", OB_CAMERA);
643         uiMenuItemEnumO(head, "", 0, "OBJECT_OT_object_add", "type", OB_LAMP);
644         uiMenuItemEnumO(head, "", 0, "OBJECT_OT_object_add", "type", OB_EMPTY);
645         uiMenuItemO(head, 0, "OBJECT_OT_armature_add");
646         uiMenuItemEnumO(head, "", 0, "OBJECT_OT_object_add", "type", OB_LATTICE);
647         
648         uiPupMenuEnd(C, head);
649         
650         /* this operator is only for a menu, not used further */
651         return OPERATOR_CANCELLED;
652 }
653
654 /* only used as menu */
655 void OBJECT_OT_primitive_add(wmOperatorType *ot)
656 {
657         /* identifiers */
658         ot->name= "Add Primitive";
659         ot->description = "Add a primitive object.";
660         ot->idname= "OBJECT_OT_primitive_add";
661         
662         /* api callbacks */
663         ot->invoke= object_primitive_add_invoke;
664         
665         ot->poll= ED_operator_scene_editable;
666         
667         /* flags */
668         ot->flag= 0;
669 }
670
671
672 /* ******************************* */
673
674 /* remove base from a specific scene */
675 /* note: now unlinks constraints as well */
676 void ED_base_object_free_and_unlink(Scene *scene, Base *base)
677 {
678         BLI_remlink(&scene->base, base);
679         free_libblock_us(&G.main->object, base->object);
680         if(scene->basact==base) scene->basact= NULL;
681         MEM_freeN(base);
682 }
683
684 static int object_delete_exec(bContext *C, wmOperator *op)
685 {
686         Scene *scene= CTX_data_scene(C);
687         int islamp= 0;
688         
689         if(CTX_data_edit_object(C)) 
690                 return OPERATOR_CANCELLED;
691         
692         ED_view3d_exit_paint_modes(C);
693
694         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
695
696                 if(base->object->type==OB_LAMP) islamp= 1;
697                 
698                 /* remove from current scene only */
699                 ED_base_object_free_and_unlink(scene, base);
700         }
701         CTX_DATA_END;
702
703         if(islamp) reshadeall_displist(scene);  /* only frees displist */
704         
705         DAG_scene_sort(scene);
706         ED_anim_dag_flush_update(C);
707         
708         WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, CTX_data_scene(C));
709         
710         return OPERATOR_FINISHED;
711 }
712
713 void OBJECT_OT_delete(wmOperatorType *ot)
714 {
715         
716         /* identifiers */
717         ot->name= "Delete Objects";
718         ot->description = "Delete the object.";
719         ot->idname= "OBJECT_OT_delete";
720         
721         /* api callbacks */
722         ot->invoke= WM_operator_confirm;
723         ot->exec= object_delete_exec;
724         ot->poll= ED_operator_scene_editable;
725         
726         /* flags */
727         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
728         
729 }
730
731
732 static void single_object_users__forwardModifierLinks(void *userData, Object *ob, Object **obpoin)
733 {
734         ID_NEW(*obpoin);
735 }
736
737 static void copy_object__forwardModifierLinks(void *userData, Object *ob,
738                                               ID **idpoin)
739 {
740         /* this is copied from ID_NEW; it might be better to have a macro */
741         if(*idpoin && (*idpoin)->newid) *idpoin = (*idpoin)->newid;
742 }
743
744
745 /* after copying objects, copied data should get new pointers */
746 static void copy_object_set_idnew(Scene *scene, View3D *v3d, int dupflag)
747 {
748         Base *base;
749         Object *ob;
750         Material *ma, *mao;
751         ID *id;
752 #if 0 // XXX old animation system
753         Ipo *ipo;
754         bActionStrip *strip;
755 #endif // XXX old animation system
756         int a;
757         
758         /* XXX check object pointers */
759         for(base= FIRSTBASE; base; base= base->next) {
760                 if(TESTBASELIB(v3d, base)) {
761                         ob= base->object;
762                         relink_constraints(&ob->constraints);
763                         if (ob->pose){
764                                 bPoseChannel *chan;
765                                 for (chan = ob->pose->chanbase.first; chan; chan=chan->next){
766                                         relink_constraints(&chan->constraints);
767                                 }
768                         }
769                         modifiers_foreachIDLink(ob, copy_object__forwardModifierLinks, NULL);
770                         ID_NEW(ob->parent);
771                         ID_NEW(ob->track);
772                         ID_NEW(ob->proxy);
773                         ID_NEW(ob->proxy_group);
774                         
775 #if 0 // XXX old animation system
776                         for(strip= ob->nlastrips.first; strip; strip= strip->next) {
777                                 bActionModifier *amod;
778                                 for(amod= strip->modifiers.first; amod; amod= amod->next)
779                                         ID_NEW(amod->ob);
780                         }
781 #endif // XXX old animation system
782                 }
783         }
784         
785         /* materials */
786         if( dupflag & USER_DUP_MAT) {
787                 mao= G.main->mat.first;
788                 while(mao) {
789                         if(mao->id.newid) {
790                                 
791                                 ma= (Material *)mao->id.newid;
792                                 
793                                 if(dupflag & USER_DUP_TEX) {
794                                         for(a=0; a<MAX_MTEX; a++) {
795                                                 if(ma->mtex[a]) {
796                                                         id= (ID *)ma->mtex[a]->tex;
797                                                         if(id) {
798                                                                 ID_NEW_US(ma->mtex[a]->tex)
799                                                                 else ma->mtex[a]->tex= copy_texture(ma->mtex[a]->tex);
800                                                                 id->us--;
801                                                         }
802                                                 }
803                                         }
804                                 }
805 #if 0 // XXX old animation system
806                                 id= (ID *)ma->ipo;
807                                 if(id) {
808                                         ID_NEW_US(ma->ipo)
809                                         else ma->ipo= copy_ipo(ma->ipo);
810                                         id->us--;
811                                 }
812 #endif // XXX old animation system
813                         }
814                         mao= mao->id.next;
815                 }
816         }
817         
818 #if 0 // XXX old animation system
819         /* lamps */
820         if( dupflag & USER_DUP_IPO) {
821                 Lamp *la= G.main->lamp.first;
822                 while(la) {
823                         if(la->id.newid) {
824                                 Lamp *lan= (Lamp *)la->id.newid;
825                                 id= (ID *)lan->ipo;
826                                 if(id) {
827                                         ID_NEW_US(lan->ipo)
828                                         else lan->ipo= copy_ipo(lan->ipo);
829                                         id->us--;
830                                 }
831                         }
832                         la= la->id.next;
833                 }
834         }
835         
836         /* ipos */
837         ipo= G.main->ipo.first;
838         while(ipo) {
839                 if(ipo->id.lib==NULL && ipo->id.newid) {
840                         Ipo *ipon= (Ipo *)ipo->id.newid;
841                         IpoCurve *icu;
842                         for(icu= ipon->curve.first; icu; icu= icu->next) {
843                                 if(icu->driver) {
844                                         ID_NEW(icu->driver->ob);
845                                 }
846                         }
847                 }
848                 ipo= ipo->id.next;
849         }
850 #endif // XXX old animation system
851         
852         set_sca_new_poins();
853         
854         clear_id_newpoins();
855         
856 }
857
858 static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float *cent)
859 {
860         EditVert *eve;
861         int *index, nr, totvert=0;
862         
863         for(eve= em->verts.first; eve; eve= eve->next) {
864                 if(eve->f & SELECT) totvert++;
865         }
866         if(totvert==0) return 0;
867         
868         *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
869         *tot= totvert;
870         nr= 0;
871         cent[0]= cent[1]= cent[2]= 0.0;
872         
873         for(eve= em->verts.first; eve; eve= eve->next) {
874                 if(eve->f & SELECT) {
875                         *index= nr; index++;
876                         VecAddf(cent, cent, eve->co);
877                 }
878                 nr++;
879         }
880         
881         VecMulf(cent, 1.0f/(float)totvert);
882         
883         return totvert;
884 }
885
886 static int return_editmesh_vgroup(Object *obedit, EditMesh *em, char *name, float *cent)
887 {
888         MDeformVert *dvert;
889         EditVert *eve;
890         int i, totvert=0;
891         
892         cent[0]= cent[1]= cent[2]= 0.0;
893         
894         if(obedit->actdef) {
895                 
896                 /* find the vertices */
897                 for(eve= em->verts.first; eve; eve= eve->next) {
898                         dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
899
900                         if(dvert) {
901                                 for(i=0; i<dvert->totweight; i++){
902                                         if(dvert->dw[i].def_nr == (obedit->actdef-1)) {
903                                                 totvert++;
904                                                 VecAddf(cent, cent, eve->co);
905                                         }
906                                 }
907                         }
908                 }
909                 if(totvert) {
910                         bDeformGroup *defGroup = BLI_findlink(&obedit->defbase, obedit->actdef-1);
911                         strcpy(name, defGroup->name);
912                         VecMulf(cent, 1.0f/(float)totvert);
913                         return 1;
914                 }
915         }
916         
917         return 0;
918 }       
919
920 static void select_editmesh_hook(Object *ob, HookModifierData *hmd)
921 {
922         Mesh *me= ob->data;
923         EditMesh *em= BKE_mesh_get_editmesh(me);
924         EditVert *eve;
925         int index=0, nr=0;
926         
927         for(eve= em->verts.first; eve; eve= eve->next, nr++) {
928                 if(nr==hmd->indexar[index]) {
929                         eve->f |= SELECT;
930                         if(index < hmd->totindex-1) index++;
931                 }
932         }
933         EM_select_flush(em);
934
935         BKE_mesh_end_editmesh(me, em);
936 }
937
938 static int return_editlattice_indexar(Lattice *editlatt, int *tot, int **indexar, float *cent)
939 {
940         BPoint *bp;
941         int *index, nr, totvert=0, a;
942         
943         /* count */
944         a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
945         bp= editlatt->def;
946         while(a--) {
947                 if(bp->f1 & SELECT) {
948                         if(bp->hide==0) totvert++;
949                 }
950                 bp++;
951         }
952
953         if(totvert==0) return 0;
954         
955         *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
956         *tot= totvert;
957         nr= 0;
958         cent[0]= cent[1]= cent[2]= 0.0;
959         
960         a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
961         bp= editlatt->def;
962         while(a--) {
963                 if(bp->f1 & SELECT) {
964                         if(bp->hide==0) {
965                                 *index= nr; index++;
966                                 VecAddf(cent, cent, bp->vec);
967                         }
968                 }
969                 bp++;
970                 nr++;
971         }
972         
973         VecMulf(cent, 1.0f/(float)totvert);
974         
975         return totvert;
976 }
977
978 static void select_editlattice_hook(Object *obedit, HookModifierData *hmd)
979 {
980         Lattice *lt= obedit->data;
981         BPoint *bp;
982         int index=0, nr=0, a;
983         
984         /* count */
985         a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
986         bp= lt->editlatt->def;
987         while(a--) {
988                 if(hmd->indexar[index]==nr) {
989                         bp->f1 |= SELECT;
990                         if(index < hmd->totindex-1) index++;
991                 }
992                 nr++;
993                 bp++;
994         }
995 }
996
997 static int return_editcurve_indexar(Object *obedit, int *tot, int **indexar, float *cent)
998 {
999         ListBase *editnurb= curve_get_editcurve(obedit);
1000         Nurb *nu;
1001         BPoint *bp;
1002         BezTriple *bezt;
1003         int *index, a, nr, totvert=0;
1004         
1005         for(nu= editnurb->first; nu; nu= nu->next) {
1006                 if((nu->type & 7)==CU_BEZIER) {
1007                         bezt= nu->bezt;
1008                         a= nu->pntsu;
1009                         while(a--) {
1010                                 if(bezt->f1 & SELECT) totvert++;
1011                                 if(bezt->f2 & SELECT) totvert++;
1012                                 if(bezt->f3 & SELECT) totvert++;
1013                                 bezt++;
1014                         }
1015                 }
1016                 else {
1017                         bp= nu->bp;
1018                         a= nu->pntsu*nu->pntsv;
1019                         while(a--) {
1020                                 if(bp->f1 & SELECT) totvert++;
1021                                 bp++;
1022                         }
1023                 }
1024         }
1025         if(totvert==0) return 0;
1026         
1027         *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
1028         *tot= totvert;
1029         nr= 0;
1030         cent[0]= cent[1]= cent[2]= 0.0;
1031         
1032         for(nu= editnurb->first; nu; nu= nu->next) {
1033                 if((nu->type & 7)==CU_BEZIER) {
1034                         bezt= nu->bezt;
1035                         a= nu->pntsu;
1036                         while(a--) {
1037                                 if(bezt->f1 & SELECT) {
1038                                         *index= nr; index++;
1039                                         VecAddf(cent, cent, bezt->vec[0]);
1040                                 }
1041                                 nr++;
1042                                 if(bezt->f2 & SELECT) {
1043                                         *index= nr; index++;
1044                                         VecAddf(cent, cent, bezt->vec[1]);
1045                                 }
1046                                 nr++;
1047                                 if(bezt->f3 & SELECT) {
1048                                         *index= nr; index++;
1049                                         VecAddf(cent, cent, bezt->vec[2]);
1050                                 }
1051                                 nr++;
1052                                 bezt++;
1053                         }
1054                 }
1055                 else {
1056                         bp= nu->bp;
1057                         a= nu->pntsu*nu->pntsv;
1058                         while(a--) {
1059                                 if(bp->f1 & SELECT) {
1060                                         *index= nr; index++;
1061                                         VecAddf(cent, cent, bp->vec);
1062                                 }
1063                                 nr++;
1064                                 bp++;
1065                         }
1066                 }
1067         }
1068         
1069         VecMulf(cent, 1.0f/(float)totvert);
1070         
1071         return totvert;
1072 }
1073
1074 void ED_object_apply_obmat(Object *ob)
1075 {
1076         float mat[3][3], imat[3][3], tmat[3][3];
1077         
1078         /* from obmat to loc rot size */
1079         
1080         if(ob==NULL) return;
1081         Mat3CpyMat4(mat, ob->obmat);
1082         
1083         VECCOPY(ob->loc, ob->obmat[3]);
1084
1085         Mat3ToEul(mat, ob->rot);
1086         EulToMat3(ob->rot, tmat);
1087
1088         Mat3Inv(imat, tmat);
1089         
1090         Mat3MulMat3(tmat, imat, mat);
1091         
1092         ob->size[0]= tmat[0][0];
1093         ob->size[1]= tmat[1][1];
1094         ob->size[2]= tmat[2][2];
1095         
1096 }
1097
1098 int hook_getIndexArray(Object *obedit, int *tot, int **indexar, char *name, float *cent_r)
1099 {
1100         *indexar= NULL;
1101         *tot= 0;
1102         name[0]= 0;
1103         
1104         switch(obedit->type) {
1105                 case OB_MESH:
1106                 {
1107                         Mesh *me= obedit->data;
1108                         EditMesh *em = BKE_mesh_get_editmesh(me);
1109
1110                         /* check selected vertices first */
1111                         if( return_editmesh_indexar(em, tot, indexar, cent_r)) {
1112                                 BKE_mesh_end_editmesh(me, em);
1113                                 return 1;
1114                         } else {
1115                                 int ret = return_editmesh_vgroup(obedit, em, name, cent_r);
1116                                 BKE_mesh_end_editmesh(me, em);
1117                                 return ret;
1118                         }
1119                 }
1120                 case OB_CURVE:
1121                 case OB_SURF:
1122                         return return_editcurve_indexar(obedit, tot, indexar, cent_r);
1123                 case OB_LATTICE:
1124                 {
1125                         Lattice *lt= obedit->data;
1126                         return return_editlattice_indexar(lt->editlatt, tot, indexar, cent_r);
1127                 }
1128                 default:
1129                         return 0;
1130         }
1131 }
1132
1133 static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
1134 {
1135         ListBase *editnurb= curve_get_editcurve(obedit);
1136         Nurb *nu;
1137         BPoint *bp;
1138         BezTriple *bezt;
1139         int index=0, a, nr=0;
1140         
1141         for(nu= editnurb->first; nu; nu= nu->next) {
1142                 if((nu->type & 7)==CU_BEZIER) {
1143                         bezt= nu->bezt;
1144                         a= nu->pntsu;
1145                         while(a--) {
1146                                 if(nr == hmd->indexar[index]) {
1147                                         bezt->f1 |= SELECT;
1148                                         if(index<hmd->totindex-1) index++;
1149                                 }
1150                                 nr++;
1151                                 if(nr == hmd->indexar[index]) {
1152                                         bezt->f2 |= SELECT;
1153                                         if(index<hmd->totindex-1) index++;
1154                                 }
1155                                 nr++;
1156                                 if(nr == hmd->indexar[index]) {
1157                                         bezt->f3 |= SELECT;
1158                                         if(index<hmd->totindex-1) index++;
1159                                 }
1160                                 nr++;
1161                                 
1162                                 bezt++;
1163                         }
1164                 }
1165                 else {
1166                         bp= nu->bp;
1167                         a= nu->pntsu*nu->pntsv;
1168                         while(a--) {
1169                                 if(nr == hmd->indexar[index]) {
1170                                         bp->f1 |= SELECT;
1171                                         if(index<hmd->totindex-1) index++;
1172                                 }
1173                                 nr++;
1174                                 bp++;
1175                         }
1176                 }
1177         }
1178 }
1179
1180 void obedit_hook_select(Object *ob, HookModifierData *hmd) 
1181 {
1182         
1183         if(ob->type==OB_MESH) select_editmesh_hook(ob, hmd);
1184         else if(ob->type==OB_LATTICE) select_editlattice_hook(ob, hmd);
1185         else if(ob->type==OB_CURVE) select_editcurve_hook(ob, hmd);
1186         else if(ob->type==OB_SURF) select_editcurve_hook(ob, hmd);
1187 }
1188
1189
1190 void add_hook(Scene *scene, View3D *v3d, int mode)
1191 {
1192         ModifierData *md = NULL;
1193         HookModifierData *hmd = NULL;
1194         Object *ob=NULL;
1195         Object *obedit= scene->obedit;  // XXX get from context
1196         
1197         if(obedit==NULL) return;
1198         
1199         /* preconditions */
1200         if(mode==2) { /* selected object */
1201                 Base *base;
1202                 for(base= FIRSTBASE; base; base= base->next) {
1203                         if(TESTBASELIB(v3d, base)) {
1204                                 if(base!=BASACT) {
1205                                         ob= base->object;
1206                                         break;
1207                                 }
1208                         }
1209                 }
1210                 if(ob==NULL) {
1211                         error("Requires selected Object");
1212                         return;
1213                 }
1214         }
1215         else if(mode!=1) {
1216                 int maxlen=0, a, nr;
1217                 char *cp;
1218                 
1219                 /* make pupmenu with hooks */
1220                 for(md=obedit->modifiers.first; md; md= md->next) {
1221                         if (md->type==eModifierType_Hook) 
1222                                 maxlen+=32;
1223                 }
1224                 
1225                 if(maxlen==0) {
1226                         error("Object has no hooks yet");
1227                         return;
1228                 }
1229                 
1230                 cp= MEM_callocN(maxlen+32, "temp string");
1231                 if(mode==3) strcpy(cp, "Remove %t|");
1232                 else if(mode==4) strcpy(cp, "Reassign %t|");
1233                 else if(mode==5) strcpy(cp, "Select %t|");
1234                 else if(mode==6) strcpy(cp, "Clear Offset %t|");
1235                 
1236                 for(md=obedit->modifiers.first; md; md= md->next) {
1237                         if (md->type==eModifierType_Hook) {
1238                                 strcat(cp, md->name);
1239                                 strcat(cp, " |");
1240                         }
1241                 }
1242                 
1243                 nr= pupmenu(cp);
1244                 MEM_freeN(cp);
1245                 
1246                 if(nr<1) return;
1247                 
1248                 a= 1;
1249                 for(md=obedit->modifiers.first; md; md=md->next) {
1250                         if (md->type==eModifierType_Hook) {
1251                                 if(a==nr) break;
1252                                 a++;
1253                         }
1254                 }
1255                 
1256                 hmd = (HookModifierData*) md;
1257                 ob= hmd->object;
1258         }
1259
1260         /* do it, new hooks or reassign */
1261         if(mode==1 || mode==2 || mode==4) {
1262                 float cent[3];
1263                 int tot, ok, *indexar;
1264                 char name[32];
1265                 
1266                 ok = hook_getIndexArray(obedit, &tot, &indexar, name, cent);
1267                 
1268                 if(ok==0) {
1269                         error("Requires selected vertices or active Vertex Group");
1270                 }
1271                 else {
1272                         
1273                         if(mode==1) {
1274                                 Base *base= BASACT, *newbase;
1275                                 
1276                                 ob= add_object(scene, OB_EMPTY);
1277                                 /* set layers OK */
1278                                 newbase= BASACT;
1279                                 newbase->lay= base->lay;
1280                                 ob->lay= newbase->lay;
1281                                 
1282                                 /* transform cent to global coords for loc */
1283                                 VecMat4MulVecfl(ob->loc, obedit->obmat, cent);
1284                                 
1285                                 /* restore, add_object sets active */
1286                                 BASACT= base;
1287                         }
1288                         /* if mode is 2 or 4, ob has been set */
1289                         
1290                         /* new hook */
1291                         if(mode==1 || mode==2) {
1292                                 ModifierData *md = obedit->modifiers.first;
1293                                 
1294                                 while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
1295                                         md = md->next;
1296                                 }
1297                                 
1298                                 hmd = (HookModifierData*) modifier_new(eModifierType_Hook);
1299                                 BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
1300                                 sprintf(hmd->modifier.name, "Hook-%s", ob->id.name+2);
1301                         }
1302                         else if (hmd->indexar) MEM_freeN(hmd->indexar); /* reassign, hook was set */
1303                 
1304                         hmd->object= ob;
1305                         hmd->indexar= indexar;
1306                         VECCOPY(hmd->cent, cent);
1307                         hmd->totindex= tot;
1308                         BLI_strncpy(hmd->name, name, 32);
1309                         
1310                         if(mode==1 || mode==2) {
1311                                 /* matrix calculus */
1312                                 /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
1313                                 /*        (parentinv         )                          */
1314                                 
1315                                 where_is_object(scene, ob);
1316                                 
1317                                 Mat4Invert(ob->imat, ob->obmat);
1318                                 /* apparently this call goes from right to left... */
1319                                 Mat4MulSerie(hmd->parentinv, ob->imat, obedit->obmat, NULL, 
1320                                                          NULL, NULL, NULL, NULL, NULL);
1321                         }
1322                 }
1323         }
1324         else if(mode==3) { /* remove */
1325                 BLI_remlink(&obedit->modifiers, md);
1326                 modifier_free(md);
1327         }
1328         else if(mode==5) { /* select */
1329                 obedit_hook_select(obedit, hmd);
1330         }
1331         else if(mode==6) { /* clear offset */
1332                 where_is_object(scene, ob);     /* ob is hook->parent */
1333
1334                 Mat4Invert(ob->imat, ob->obmat);
1335                 /* this call goes from right to left... */
1336                 Mat4MulSerie(hmd->parentinv, ob->imat, obedit->obmat, NULL, 
1337                                          NULL, NULL, NULL, NULL, NULL);
1338         }
1339
1340         DAG_scene_sort(scene);
1341 }
1342
1343
1344 /* use this when the loc/size/rot of the parent has changed but the children should stay in the same place
1345  * apply-size-rot or object center for eg */
1346 static void ignore_parent_tx(Scene *scene, Object *ob ) 
1347 {
1348         Object workob;
1349         Object *ob_child;
1350         
1351         /* a change was made, adjust the children to compensate */
1352         for (ob_child=G.main->object.first; ob_child; ob_child=ob_child->id.next) {
1353                 if (ob_child->parent == ob) {
1354                         ED_object_apply_obmat(ob_child);
1355                         what_does_parent(scene, ob_child, &workob);
1356                         Mat4Invert(ob_child->parentinv, workob.obmat);
1357                 }
1358         }
1359 }
1360
1361
1362 void add_hook_menu(Scene *scene, View3D *v3d)
1363 {
1364         Object *obedit= scene->obedit;  // XXX get from context
1365         int mode;
1366         
1367         if(obedit==NULL) return;
1368         
1369         if(modifiers_findByType(obedit, eModifierType_Hook))
1370                 mode= pupmenu("Hooks %t|Add, To New Empty %x1|Add, To Selected Object %x2|Remove... %x3|Reassign... %x4|Select... %x5|Clear Offset...%x6");
1371         else
1372                 mode= pupmenu("Hooks %t|Add, New Empty %x1|Add, To Selected Object %x2");
1373
1374         if(mode<1) return;
1375                 
1376         /* do operations */
1377         add_hook(scene, v3d, mode);
1378 }
1379
1380 /* ******************** clear parent operator ******************* */
1381
1382 static EnumPropertyItem prop_clear_parent_types[] = {
1383         {0, "CLEAR", "Clear Parent", ""},
1384         {1, "CLEAR_KEEP_TRANSFORM", "Clear and Keep Transformation (Clear Track)", ""},
1385         {2, "CLEAR_INVERSE", "Clear Parent Inverse", ""},
1386         {0, NULL, NULL, NULL}
1387 };
1388
1389 /* note, poll should check for editable scene */
1390 static int parent_clear_exec(bContext *C, wmOperator *op)
1391 {
1392         
1393         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1394
1395                 if(RNA_enum_is_equal(op->ptr, "type", "CLEAR")) {
1396                         ob->parent= NULL;
1397                 }                       
1398                 if(RNA_enum_is_equal(op->ptr, "type", "CLEAR_KEEP_TRANSFORM")) {
1399                         ob->parent= NULL;
1400                         ob->track= NULL;
1401                         ED_object_apply_obmat(ob);
1402                 }
1403                 if(RNA_enum_is_equal(op->ptr, "type", "CLEAR_INVERSE")) {
1404                         Mat4One(ob->parentinv);
1405                 }
1406                 ob->recalc |= OB_RECALC;
1407         }
1408         CTX_DATA_END;
1409         
1410         DAG_scene_sort(CTX_data_scene(C));
1411         ED_anim_dag_flush_update(C);
1412         
1413         return OPERATOR_FINISHED;
1414 }
1415
1416 void OBJECT_OT_parent_clear(wmOperatorType *ot)
1417 {
1418         /* identifiers */
1419         ot->name= "Clear parent";
1420         ot->description = "Clear the object's parenting.";
1421         ot->idname= "OBJECT_OT_parent_clear";
1422         
1423         /* api callbacks */
1424         ot->invoke= WM_menu_invoke;
1425         ot->exec= parent_clear_exec;
1426         
1427         ot->poll= ED_operator_object_active;
1428         
1429         /* flags */
1430         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1431         
1432         RNA_def_enum(ot->srna, "type", prop_clear_parent_types, 0, "Type", "");
1433 }
1434
1435 /* ******************** clear track operator ******************* */
1436
1437
1438 static EnumPropertyItem prop_clear_track_types[] = {
1439         {0, "CLEAR", "Clear Track", ""},
1440         {1, "CLEAR_KEEP_TRANSFORM", "Clear and Keep Transformation (Clear Track)", ""},
1441         {0, NULL, NULL, NULL}
1442 };
1443
1444 /* note, poll should check for editable scene */
1445 static int object_track_clear_exec(bContext *C, wmOperator *op)
1446 {
1447         if(CTX_data_edit_object(C)) {
1448                 BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in EditMode");
1449                 return OPERATOR_CANCELLED;
1450         }
1451         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1452                 ob->track= NULL;
1453                 ob->recalc |= OB_RECALC;
1454                 
1455                 if(RNA_enum_is_equal(op->ptr, "type", "CLEAR_KEEP_TRANSFORM")) {
1456                         ED_object_apply_obmat(ob);
1457                 }                       
1458         }
1459         CTX_DATA_END;
1460
1461         DAG_scene_sort(CTX_data_scene(C));
1462         ED_anim_dag_flush_update(C);
1463
1464         return OPERATOR_FINISHED;
1465 }
1466
1467 void OBJECT_OT_track_clear(wmOperatorType *ot)
1468 {
1469         /* identifiers */
1470         ot->name= "Clear track";
1471         ot->description = "Clear tracking constraint or flag from object.";
1472         ot->idname= "OBJECT_OT_track_clear";
1473         
1474         /* api callbacks */
1475         ot->invoke= WM_menu_invoke;
1476         ot->exec= object_track_clear_exec;
1477         
1478         ot->poll= ED_operator_scene_editable;
1479         
1480         /* flags */
1481         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1482         
1483         RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
1484 }
1485
1486 /* *****************Selection Operators******************* */
1487 static EnumPropertyItem prop_select_types[] = {
1488         {0, "EXCLUSIVE", "Exclusive", ""},
1489         {1, "EXTEND", "Extend", ""},
1490         {0, NULL, NULL, NULL}
1491 };
1492
1493 /* ****** Select by Type ****** */
1494
1495 static int object_select_by_type_exec(bContext *C, wmOperator *op)
1496 {
1497         short obtype, seltype;
1498         
1499         obtype = RNA_enum_get(op->ptr, "type");
1500         seltype = RNA_enum_get(op->ptr, "seltype");
1501                 
1502         if (seltype == 0) {
1503                 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1504                         ED_base_object_select(base, BA_DESELECT);
1505                 }
1506                 CTX_DATA_END;
1507         }
1508         
1509         CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1510                 if(base->object->type==obtype) {
1511                         ED_base_object_select(base, BA_SELECT);
1512                 }
1513         }
1514         CTX_DATA_END;
1515         
1516         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
1517         
1518         return OPERATOR_FINISHED;
1519 }
1520
1521 void OBJECT_OT_select_by_type(wmOperatorType *ot)
1522 {
1523         /* identifiers */
1524         ot->name= "Select By Type";
1525         ot->description = "Select all visible objects that are of a type.";
1526         ot->idname= "OBJECT_OT_select_by_type";
1527         
1528         /* api callbacks */
1529         ot->invoke= WM_menu_invoke;
1530         ot->exec= object_select_by_type_exec;
1531         ot->poll= ED_operator_scene_editable;
1532         
1533         /* flags */
1534         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1535         
1536         RNA_def_enum(ot->srna, "seltype", prop_select_types, 0, "Selection", "Extend selection or clear selection then select");
1537         RNA_def_enum(ot->srna, "type", prop_object_types, 1, "Type", "");
1538
1539 }
1540 /* ****** selection by links *******/
1541
1542 static EnumPropertyItem prop_select_linked_types[] = {
1543         {1, "IPO", "Object IPO", ""}, // XXX depreceated animation system stuff...
1544         {2, "OBDATA", "Ob Data", ""},
1545         {3, "MATERIAL", "Material", ""},
1546         {4, "TEXTURE", "Texture", ""},
1547         {5, "DUPGROUP", "Dupligroup", ""},
1548         {6, "PARTICLE", "Particle System", ""},
1549         {0, NULL, NULL, NULL}
1550 };
1551
1552 static int object_select_linked_exec(bContext *C, wmOperator *op)
1553 {
1554         Scene *scene= CTX_data_scene(C);
1555         Object *ob;
1556         void *obdata = NULL;
1557         Material *mat = NULL, *mat1;
1558         Tex *tex=0;
1559         int a, b;
1560         int nr = RNA_enum_get(op->ptr, "type");
1561         short changed = 0, seltype;
1562         /* events (nr):
1563          * Object Ipo: 1
1564          * ObData: 2
1565          * Current Material: 3
1566          * Current Texture: 4
1567          * DupliGroup: 5
1568          * PSys: 6
1569          */
1570
1571         seltype = RNA_enum_get(op->ptr, "seltype");
1572         
1573         if (seltype == 0) {
1574                 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1575                         ED_base_object_select(base, BA_DESELECT);
1576                 }
1577                 CTX_DATA_END;
1578         }
1579         
1580         ob= OBACT;
1581         if(ob==0){ 
1582                 BKE_report(op->reports, RPT_ERROR, "No Active Object");
1583                 return OPERATOR_CANCELLED;
1584         }
1585         
1586         if(nr==1) {     
1587                         // XXX old animation system
1588                 //ipo= ob->ipo;
1589                 //if(ipo==0) return OPERATOR_CANCELLED;
1590                 return OPERATOR_CANCELLED;
1591         }
1592         else if(nr==2) {
1593                 if(ob->data==0) return OPERATOR_CANCELLED;
1594                 obdata= ob->data;
1595         }
1596         else if(nr==3 || nr==4) {
1597                 mat= give_current_material(ob, ob->actcol);
1598                 if(mat==0) return OPERATOR_CANCELLED;
1599                 if(nr==4) {
1600                         if(mat->mtex[ (int)mat->texact ]) tex= mat->mtex[ (int)mat->texact ]->tex;
1601                         if(tex==0) return OPERATOR_CANCELLED;
1602                 }
1603         }
1604         else if(nr==5) {
1605                 if(ob->dup_group==NULL) return OPERATOR_CANCELLED;
1606         }
1607         else if(nr==6) {
1608                 if(ob->particlesystem.first==NULL) return OPERATOR_CANCELLED;
1609         }
1610         else return OPERATOR_CANCELLED;
1611         
1612         CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1613                 if(nr==1) {
1614                                 // XXX old animation system
1615                         //if(base->object->ipo==ipo) base->flag |= SELECT;
1616                         //changed = 1;
1617                 }
1618                 else if(nr==2) {
1619                         if(base->object->data==obdata) base->flag |= SELECT;
1620                         changed = 1;
1621                 }
1622                 else if(nr==3 || nr==4) {
1623                         ob= base->object;
1624                         
1625                         for(a=1; a<=ob->totcol; a++) {
1626                                 mat1= give_current_material(ob, a);
1627                                 if(nr==3) {
1628                                         if(mat1==mat) base->flag |= SELECT;
1629                                         changed = 1;
1630                                 }
1631                                 else if(mat1 && nr==4) {
1632                                         for(b=0; b<MAX_MTEX; b++) {
1633                                                 if(mat1->mtex[b]) {
1634                                                         if(tex==mat1->mtex[b]->tex) {
1635                                                                 base->flag |= SELECT;
1636                                                                 changed = 1;
1637                                                                 break;
1638                                                         }
1639                                                 }
1640                                         }
1641                                 }
1642                         }
1643                 }
1644                 else if(nr==5) {
1645                         if(base->object->dup_group==ob->dup_group) {
1646                                  base->flag |= SELECT;
1647                                  changed = 1;
1648                         }
1649                 }
1650                 else if(nr==6) {
1651                         /* loop through other, then actives particles*/
1652                         ParticleSystem *psys;
1653                         ParticleSystem *psys_act;
1654                         
1655                         for(psys=base->object->particlesystem.first; psys; psys=psys->next) {
1656                                 for(psys_act=ob->particlesystem.first; psys_act; psys_act=psys_act->next) {
1657                                         if (psys->part == psys_act->part) {
1658                                                 base->flag |= SELECT;
1659                                                 changed = 1;
1660                                                 break;
1661                                         }
1662                                 }
1663                                 
1664                                 if (base->flag & SELECT) {
1665                                         break;
1666                                 }
1667                         }
1668                 }
1669                 base->object->flag= base->flag;
1670         }
1671         CTX_DATA_END;
1672         
1673         if (changed) {
1674                 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
1675                 return OPERATOR_FINISHED;
1676         }
1677         
1678         return OPERATOR_CANCELLED;
1679 }
1680
1681 void OBJECT_OT_select_linked(wmOperatorType *ot)
1682 {
1683         /* identifiers */
1684         ot->name= "Select Linked";
1685         ot->description = "Select all visible objects that are linked.";
1686         ot->idname= "OBJECT_OT_select_linked";
1687         
1688         /* api callbacks */
1689         ot->invoke= WM_menu_invoke;
1690         ot->exec= object_select_linked_exec;
1691         ot->poll= ED_operator_scene_editable;
1692         
1693         /* flags */
1694         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1695         
1696         RNA_def_enum(ot->srna, "type", prop_select_linked_types, 0, "Type", "");
1697         RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
1698
1699 }
1700 /* ****** selection by layer *******/
1701
1702 static int object_select_by_layer_exec(bContext *C, wmOperator *op)
1703 {
1704         unsigned int layernum;
1705         short seltype;
1706         
1707         seltype = RNA_enum_get(op->ptr, "seltype");
1708         layernum = RNA_int_get(op->ptr, "layer");
1709         
1710         if (seltype == 0) {
1711                 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1712                         ED_base_object_select(base, BA_DESELECT);
1713                 }
1714                 CTX_DATA_END;
1715         }
1716                 
1717         CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1718                 if(base->lay == (1<< (layernum -1)))
1719                         ED_base_object_select(base, BA_SELECT);
1720         }
1721         CTX_DATA_END;
1722         
1723         /* undo? */
1724         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
1725         
1726         return OPERATOR_FINISHED;
1727 }
1728
1729 void OBJECT_OT_select_by_layer(wmOperatorType *ot)
1730 {
1731         /* identifiers */
1732         ot->name= "select by layer";
1733         ot->description = "Select all visible objects on a layer.";
1734         ot->idname= "OBJECT_OT_select_by_layer";
1735         
1736         /* api callbacks */
1737         /*ot->invoke = XXX - need a int grid popup*/
1738         ot->exec= object_select_by_layer_exec;
1739         ot->poll= ED_operator_scene_editable;
1740         
1741         /* flags */
1742         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1743         
1744         RNA_def_int(ot->srna, "layer", 1, 1, 20, "Layer", "", 1, 20);
1745         RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
1746 }
1747
1748 /* ****** invert selection *******/
1749 static int object_select_invert_exec(bContext *C, wmOperator *op)
1750 {
1751         CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1752                 if (base->flag & SELECT)
1753                         ED_base_object_select(base, BA_DESELECT);
1754                 else
1755                         ED_base_object_select(base, BA_SELECT);
1756         }
1757         CTX_DATA_END;
1758         
1759         /* undo? */
1760         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
1761         
1762         return OPERATOR_FINISHED;
1763 }
1764
1765 void OBJECT_OT_select_invert(wmOperatorType *ot)
1766 {
1767         
1768         /* identifiers */
1769         ot->name= "Invert selection";
1770         ot->description = "Invert th select of all visible objects.";
1771         ot->idname= "OBJECT_OT_select_invert";
1772         
1773         /* api callbacks */
1774         ot->exec= object_select_invert_exec;
1775         ot->poll= ED_operator_scene_editable;
1776         
1777         /* flags */
1778         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1779         
1780 }
1781 /* ****** (de)select All *******/
1782
1783 static int object_select_de_select_all_exec(bContext *C, wmOperator *op)
1784 {
1785         
1786         int a=0, ok=0; 
1787         
1788         CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1789                 if (base->flag & SELECT) {
1790                         ok= a= 1;
1791                         break;
1792                 }
1793                 else ok=1;
1794         }
1795         CTX_DATA_END;
1796         
1797         if (!ok) return OPERATOR_PASS_THROUGH;
1798         
1799         CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1800                 if (a) ED_base_object_select(base, BA_DESELECT);
1801                 else ED_base_object_select(base, BA_SELECT);
1802         }
1803         CTX_DATA_END;
1804         
1805         /* undo? */
1806         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
1807         
1808         return OPERATOR_FINISHED;
1809 }
1810
1811 void OBJECT_OT_select_all_toggle(wmOperatorType *ot)
1812 {
1813         
1814         /* identifiers */
1815         ot->name= "deselect all";
1816         ot->description = "(de)select all visible objects in scene.";
1817         ot->idname= "OBJECT_OT_select_all_toggle";
1818         
1819         /* api callbacks */
1820         ot->exec= object_select_de_select_all_exec;
1821         ot->poll= ED_operator_scene_editable;
1822         
1823         /* flags */
1824         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1825         
1826 }
1827 /* ****** random selection *******/
1828
1829 static int object_select_random_exec(bContext *C, wmOperator *op)
1830 {       
1831         float percent;
1832         short seltype;
1833         
1834         seltype = RNA_enum_get(op->ptr, "seltype");
1835         
1836         if (seltype == 0) {
1837                 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1838                         ED_base_object_select(base, BA_DESELECT);
1839                 }
1840                 CTX_DATA_END;
1841         }
1842         percent = RNA_float_get(op->ptr, "percent");
1843                 
1844         CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1845                 if (BLI_frand() < percent) {
1846                                 ED_base_object_select(base, BA_SELECT);
1847                 }
1848         }
1849         CTX_DATA_END;
1850         
1851         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
1852         
1853         return OPERATOR_FINISHED;
1854 }
1855
1856 void OBJECT_OT_select_random(wmOperatorType *ot)
1857 {
1858         /* identifiers */
1859         ot->name= "Random select";
1860         ot->description = "Set select on random visible objects.";
1861         ot->idname= "OBJECT_OT_select_random";
1862         
1863         /* api callbacks */
1864         /*ot->invoke= object_select_random_invoke XXX - need a number popup ;*/
1865         ot->exec = object_select_random_exec;
1866         ot->poll= ED_operator_scene_editable;
1867         
1868         /* flags */
1869         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1870         
1871         RNA_def_float_percentage(ot->srna, "percent", 0.5f, 0.0f, 1.0f, "Percent", "percentage of objects to randomly select", 0.0001f, 1.0f);
1872         RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
1873 }
1874
1875 /* ******** Clear object Translation *********** */
1876
1877 static int object_location_clear_exec(bContext *C, wmOperator *op)
1878 {
1879         int armature_clear= 0;
1880
1881         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1882                 if((G.f & G_WEIGHTPAINT)==0) {
1883                         if ((ob->protectflag & OB_LOCK_LOCX)==0)
1884                                 ob->loc[0]= ob->dloc[0]= 0.0f;
1885                         if ((ob->protectflag & OB_LOCK_LOCY)==0)
1886                                 ob->loc[1]= ob->dloc[1]= 0.0f;
1887                         if ((ob->protectflag & OB_LOCK_LOCZ)==0)
1888                                 ob->loc[2]= ob->dloc[2]= 0.0f;
1889                 }
1890                 ob->recalc |= OB_RECALC_OB;
1891         }
1892         CTX_DATA_END;
1893
1894         if(armature_clear==0) /* in this case flush was done */
1895                 ED_anim_dag_flush_update(C);    
1896         
1897         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
1898         
1899         return OPERATOR_FINISHED;
1900 }
1901
1902
1903 void OBJECT_OT_location_clear(wmOperatorType *ot)
1904 {
1905         
1906         /* identifiers */
1907         ot->name= "Clear Object Location";
1908         ot->description = "Clear the object's location.";
1909         ot->idname= "OBJECT_OT_location_clear";
1910         
1911         /* api callbacks */
1912         ot->invoke= WM_operator_confirm;
1913         ot->exec= object_location_clear_exec;
1914         ot->poll= ED_operator_object_active;
1915         
1916         /* flags */
1917         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1918 }
1919
1920 static int object_rotation_clear_exec(bContext *C, wmOperator *op)
1921 {
1922         int armature_clear= 0;
1923
1924         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1925                 if((G.f & G_WEIGHTPAINT)==0) {
1926                         /* eulers can only get cleared if they are not protected */
1927                         if ((ob->protectflag & OB_LOCK_ROTX)==0)
1928                                 ob->rot[0]= ob->drot[0]= 0.0f;
1929                         if ((ob->protectflag & OB_LOCK_ROTY)==0)
1930                                 ob->rot[1]= ob->drot[1]= 0.0f;
1931                         if ((ob->protectflag & OB_LOCK_ROTZ)==0)
1932                                 ob->rot[2]= ob->drot[2]= 0.0f;
1933                 }
1934                 ob->recalc |= OB_RECALC_OB;
1935         }
1936         CTX_DATA_END;
1937
1938         if(armature_clear==0) /* in this case flush was done */
1939                 ED_anim_dag_flush_update(C);    
1940         
1941         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
1942         
1943         return OPERATOR_FINISHED;
1944 }
1945
1946
1947 void OBJECT_OT_rotation_clear(wmOperatorType *ot)
1948 {
1949         
1950         /* identifiers */
1951         ot->name= "Clear Object Rotation";
1952         ot->description = "Clear the object's rotation.";
1953         ot->idname= "OBJECT_OT_rotation_clear";
1954         
1955         /* api callbacks */
1956         ot->invoke= WM_operator_confirm;
1957         ot->exec= object_rotation_clear_exec;
1958         ot->poll= ED_operator_object_active;
1959         
1960         /* flags */
1961         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1962 }
1963
1964 static int object_scale_clear_exec(bContext *C, wmOperator *op)
1965 {
1966         int armature_clear= 0;
1967
1968         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1969                 if((G.f & G_WEIGHTPAINT)==0) {
1970                         if ((ob->protectflag & OB_LOCK_SCALEX)==0) {
1971                                 ob->dsize[0]= 0.0f;
1972                                 ob->size[0]= 1.0f;
1973                         }
1974                         if ((ob->protectflag & OB_LOCK_SCALEY)==0) {
1975                                 ob->dsize[1]= 0.0f;
1976                                 ob->size[1]= 1.0f;
1977                         }
1978                         if ((ob->protectflag & OB_LOCK_SCALEZ)==0) {
1979                                 ob->dsize[2]= 0.0f;
1980                                 ob->size[2]= 1.0f;
1981                         }
1982                 }
1983                 ob->recalc |= OB_RECALC_OB;
1984         }
1985         CTX_DATA_END;
1986         
1987         if(armature_clear==0) /* in this case flush was done */
1988                 ED_anim_dag_flush_update(C);    
1989         
1990         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
1991         
1992         return OPERATOR_FINISHED;
1993 }
1994
1995 void OBJECT_OT_scale_clear(wmOperatorType *ot)
1996 {
1997         
1998         /* identifiers */
1999         ot->name= "Clear Object Scale";
2000         ot->description = "Clear the object's scale.";
2001         ot->idname= "OBJECT_OT_scale_clear";
2002         
2003         /* api callbacks */
2004         ot->invoke= WM_operator_confirm;
2005         ot->exec= object_scale_clear_exec;
2006         ot->poll= ED_operator_object_active;
2007         
2008         /* flags */
2009         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2010 }
2011
2012 static int object_origin_clear_exec(bContext *C, wmOperator *op)
2013 {
2014         float *v1, *v3, mat[3][3];
2015         int armature_clear= 0;
2016
2017         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2018                 if(ob->parent) {
2019                         v1= ob->loc;
2020                         v3= ob->parentinv[3];
2021                         
2022                         Mat3CpyMat4(mat, ob->parentinv);
2023                         VECCOPY(v3, v1);
2024                         v3[0]= -v3[0];
2025                         v3[1]= -v3[1];
2026                         v3[2]= -v3[2];
2027                         Mat3MulVecfl(mat, v3);
2028                 }
2029                 ob->recalc |= OB_RECALC_OB;
2030         }
2031         CTX_DATA_END;
2032
2033         if(armature_clear==0) /* in this case flush was done */
2034                 ED_anim_dag_flush_update(C);    
2035         
2036         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2037         
2038         return OPERATOR_FINISHED;
2039 }
2040
2041 void OBJECT_OT_origin_clear(wmOperatorType *ot)
2042 {
2043
2044         /* identifiers */
2045         ot->name= "Clear Object Origin";
2046         ot->description = "Clear the object's origin.";
2047         ot->idname= "OBJECT_OT_origin_clear";
2048         
2049         /* api callbacks */
2050         ot->invoke= WM_operator_confirm;
2051         ot->exec= object_origin_clear_exec;
2052         ot->poll= ED_operator_object_active;
2053         
2054         /* flags */
2055         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2056 }
2057
2058 /* ********* clear/set restrict view *********/
2059 static int object_restrictview_clear_exec(bContext *C, wmOperator *op)
2060 {
2061         ScrArea *sa= CTX_wm_area(C);
2062         View3D *v3d= sa->spacedata.first;
2063         Scene *scene= CTX_data_scene(C);
2064         Base *base;
2065         int changed = 0;
2066         
2067         /* XXX need a context loop to handle such cases */
2068         for(base = FIRSTBASE; base; base=base->next){
2069                 if((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
2070                         base->flag |= SELECT;
2071                         base->object->flag = base->flag;
2072                         base->object->restrictflag &= ~OB_RESTRICT_VIEW; 
2073                         changed = 1;
2074                 }
2075         }
2076         if (changed) {
2077                 DAG_scene_sort(scene);
2078                 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
2079         }
2080
2081         return OPERATOR_FINISHED;
2082 }
2083
2084 void OBJECT_OT_restrictview_clear(wmOperatorType *ot)
2085 {
2086         
2087         /* identifiers */
2088         ot->name= "Clear restrict view";
2089         ot->description = "Reveal the object by setting the restrictview flag.";
2090         ot->idname= "OBJECT_OT_restrictview_clear";
2091         
2092         /* api callbacks */
2093         ot->invoke= WM_operator_confirm;
2094         ot->exec= object_restrictview_clear_exec;
2095         ot->poll= ED_operator_view3d_active;
2096         
2097         /* flags */
2098         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2099 }
2100
2101 static EnumPropertyItem prop_set_restrictview_types[] = {
2102         {0, "SELECTED", "Selected", ""},
2103         {1, "UNSELECTED", "Unselected ", ""},
2104         {0, NULL, NULL, NULL}
2105 };
2106
2107 static int object_restrictview_set_exec(bContext *C, wmOperator *op)
2108 {
2109         Scene *scene= CTX_data_scene(C);
2110         short changed = 0;
2111         
2112         CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2113                 if(RNA_enum_is_equal(op->ptr, "type", "SELECTED")){
2114                         if (base->flag & SELECT){
2115                                 base->flag &= ~SELECT;
2116                                 base->object->flag = base->flag;
2117                                 base->object->restrictflag |= OB_RESTRICT_VIEW;
2118                                 changed = 1;
2119                                 if (base==BASACT) {
2120                                         ED_base_object_activate(C, NULL);
2121                                 }
2122                         }
2123                 }
2124                 else if (RNA_enum_is_equal(op->ptr, "type", "UNSELECTED")){
2125                         if (!(base->flag & SELECT)){
2126                                 base->object->restrictflag |= OB_RESTRICT_VIEW;
2127                                 changed = 1;
2128                         }
2129                 }       
2130         }
2131         CTX_DATA_END;
2132
2133         if (changed) {
2134                 DAG_scene_sort(scene);
2135                 
2136                 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2137                 
2138         }
2139
2140         return OPERATOR_FINISHED;
2141 }
2142
2143 void OBJECT_OT_restrictview_set(wmOperatorType *ot)
2144 {
2145         /* identifiers */
2146         ot->name= "Set restrict view";
2147         ot->description = "Hide the object by setting the restrictview flag.";
2148         ot->idname= "OBJECT_OT_restrictview_set";
2149         
2150         /* api callbacks */
2151         ot->invoke= WM_menu_invoke;
2152         ot->exec= object_restrictview_set_exec;
2153         ot->poll= ED_operator_view3d_active;
2154         
2155         /* flags */
2156         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2157         
2158         RNA_def_enum(ot->srna, "type", prop_set_restrictview_types, 0, "Type", "");
2159         
2160 }
2161 /* ************* Slow Parent ******************* */
2162 static int object_slowparent_set_exec(bContext *C, wmOperator *op)
2163 {
2164
2165         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2166                 
2167                 if(base->object->parent) base->object->partype |= PARSLOW;
2168                 base->object->recalc |= OB_RECALC_OB;
2169                 
2170         }
2171         CTX_DATA_END;
2172
2173         ED_anim_dag_flush_update(C);    
2174         
2175         WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
2176         
2177         return OPERATOR_FINISHED;
2178 }
2179
2180 void OBJECT_OT_slowparent_set(wmOperatorType *ot)
2181 {
2182         
2183         /* identifiers */
2184         ot->name= "Set Slow Parent";
2185         ot->description = "Set the object's slow parent.";
2186         ot->idname= "OBJECT_OT_slow_parent_set";
2187         
2188         /* api callbacks */
2189         ot->invoke= WM_operator_confirm;
2190         ot->exec= object_slowparent_set_exec;
2191         ot->poll= ED_operator_view3d_active;
2192         
2193         /* flags */
2194         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2195 }
2196
2197 static int object_slowparent_clear_exec(bContext *C, wmOperator *op)
2198 {
2199         Scene *scene= CTX_data_scene(C);
2200
2201         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2202                 if(base->object->parent) {
2203                         if(base->object->partype & PARSLOW) {
2204                                 base->object->partype -= PARSLOW;
2205                                 where_is_object(scene, base->object);
2206                                 base->object->partype |= PARSLOW;
2207                                 base->object->recalc |= OB_RECALC_OB;
2208                         }
2209                 }
2210                 
2211         }
2212         CTX_DATA_END;
2213
2214         ED_anim_dag_flush_update(C);    
2215         
2216         WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
2217         
2218         return OPERATOR_FINISHED;
2219 }
2220
2221 void OBJECT_OT_slowparent_clear(wmOperatorType *ot)
2222 {
2223         
2224         /* identifiers */
2225         ot->name= "Clear Slow Parent";
2226         ot->description = "Clear the object's slow parent.";
2227         ot->idname= "OBJECT_OT_slow_parent_clear";
2228         
2229         /* api callbacks */
2230         ot->invoke= WM_operator_confirm;
2231         ot->exec= object_slowparent_clear_exec;
2232         ot->poll= ED_operator_view3d_active;
2233         
2234         /* flags */
2235         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2236 }
2237 /* ******************** **************** */
2238
2239 // XXX
2240 #define BEZSELECTED_HIDDENHANDLES(bezt)   ((G.f & G_HIDDENHANDLES) ? (bezt)->f2 & SELECT : BEZSELECTED(bezt))
2241 /* only in edit mode */
2242 void make_vertex_parent(Scene *scene, Object *obedit, View3D *v3d)
2243 {
2244         EditVert *eve;
2245         Base *base;
2246         Nurb *nu;
2247         BezTriple *bezt;
2248         BPoint *bp;
2249         Object *par, *ob;
2250         int a, v1=0, v2=0, v3=0, v4=0, nr=1;
2251         
2252         /* we need 1 to 3 selected vertices */
2253         
2254         if(obedit->type==OB_MESH) {
2255                 Mesh *me= obedit->data;
2256                 EditMesh *em = BKE_mesh_get_editmesh(me);
2257
2258                 eve= em->verts.first;
2259                 while(eve) {
2260                         if(eve->f & 1) {
2261                                 if(v1==0) v1= nr;
2262                                 else if(v2==0) v2= nr;
2263                                 else if(v3==0) v3= nr;
2264                                 else if(v4==0) v4= nr;
2265                                 else break;
2266                         }
2267                         nr++;
2268                         eve= eve->next;
2269                 }
2270
2271                 BKE_mesh_end_editmesh(me, em);
2272         }
2273         else if(ELEM(obedit->type, OB_SURF, OB_CURVE)) {
2274                 ListBase *editnurb= curve_get_editcurve(obedit);
2275
2276                 nu= editnurb->first;
2277                 while(nu) {
2278                         if((nu->type & 7)==CU_BEZIER) {
2279                                 bezt= nu->bezt;
2280                                 a= nu->pntsu;
2281                                 while(a--) {
2282                                         if(BEZSELECTED_HIDDENHANDLES(bezt)) {
2283                                                 if(v1==0) v1= nr;
2284                                                 else if(v2==0) v2= nr;
2285                                                 else if(v3==0) v3= nr;
2286                                                 else if(v4==0) v4= nr;
2287                                                 else break;
2288                                         }
2289                                         nr++;
2290                                         bezt++;
2291                                 }
2292                         }
2293                         else {
2294                                 bp= nu->bp;
2295                                 a= nu->pntsu*nu->pntsv;
2296                                 while(a--) {
2297                                         if(bp->f1 & SELECT) {
2298                                                 if(v1==0) v1= nr;
2299                                                 else if(v2==0) v2= nr;
2300                                                 else if(v3==0) v3= nr;
2301                                                 else if(v4==0) v4= nr;
2302                                                 else break;
2303                                         }
2304                                         nr++;
2305                                         bp++;
2306                                 }
2307                         }
2308                         nu= nu->next;
2309                 }
2310         }
2311         else if(obedit->type==OB_LATTICE) {
2312                 Lattice *lt= obedit->data;
2313                 
2314                 a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
2315                 bp= lt->editlatt->def;
2316                 while(a--) {
2317                         if(bp->f1 & SELECT) {
2318                                 if(v1==0) v1= nr;
2319                                 else if(v2==0) v2= nr;
2320                                 else if(v3==0) v3= nr;
2321                                 else if(v4==0) v4= nr;
2322                                 else break;
2323                         }
2324                         nr++;
2325                         bp++;
2326                 }
2327         }
2328         
2329         if(v4 || !((v1 && v2==0 && v3==0) || (v1 && v2 && v3)) ) {
2330                 error("Select either 1 or 3 vertices to parent to");
2331                 return;
2332         }
2333         
2334         if(okee("Make vertex parent")==0) return;
2335         
2336         for(base= FIRSTBASE; base; base= base->next) {
2337                 if(TESTBASELIB(v3d, base)) {
2338                         if(base!=BASACT) {
2339                                 
2340                                 ob= base->object;
2341                                 ob->recalc |= OB_RECALC;
2342                                 par= BASACT->object->parent;
2343                                 
2344                                 while(par) {
2345                                         if(par==ob) break;
2346                                         par= par->parent;
2347                                 }
2348                                 if(par) {
2349                                         error("Loop in parents");
2350                                 }
2351                                 else {
2352                                         Object workob;
2353                                         
2354                                         ob->parent= BASACT->object;
2355                                         if(v3) {
2356                                                 ob->partype= PARVERT3;
2357                                                 ob->par1= v1-1;
2358                                                 ob->par2= v2-1;
2359                                                 ob->par3= v3-1;
2360
2361                                                 /* inverse parent matrix */
2362                                                 what_does_parent(scene, ob, &workob);
2363                                                 Mat4Invert(ob->parentinv, workob.obmat);
2364                                         }
2365                                         else {
2366                                                 ob->partype= PARVERT1;
2367                                                 ob->par1= v1-1;
2368
2369                                                 /* inverse parent matrix */
2370                                                 what_does_parent(scene, ob, &workob);
2371                                                 Mat4Invert(ob->parentinv, workob.obmat);
2372                                         }
2373                                 }
2374                         }
2375                 }
2376         }
2377         
2378         DAG_scene_sort(scene);
2379 }
2380
2381 static Object *group_objects_menu(Group *group)
2382 {
2383         GroupObject *go;
2384         int len= 0;
2385         short a, nr;
2386         char *str;
2387                 
2388         for(go= group->gobject.first; go; go= go->next) {
2389                 if(go->ob)
2390                         len++;
2391         }
2392         if(len==0) return NULL;
2393         
2394         str= MEM_callocN(40+32*len, "menu");
2395         
2396         strcpy(str, "Make Proxy for: %t");
2397         a= strlen(str);
2398         for(nr=1, go= group->gobject.first; go; go= go->next, nr++) {
2399                 a+= sprintf(str+a, "|%s %%x%d", go->ob->id.name+2, nr);
2400         }
2401         
2402         a= pupmenu_col(str, 20);
2403         MEM_freeN(str);
2404         if(a>0) {
2405                 go= BLI_findlink(&group->gobject, a-1);
2406                 return go->ob;
2407         }
2408         return NULL;
2409 }
2410
2411
2412 /* adds empty object to become local replacement data of a library-linked object */
2413 void make_proxy(Scene *scene)
2414 {
2415         Object *ob= OBACT;
2416         Object *gob= NULL;
2417         
2418         if(scene->id.lib) return;
2419         if(ob==NULL) return;
2420         
2421         
2422         if(ob->dup_group && ob->dup_group->id.lib) {
2423                 gob= ob;
2424                 /* gives menu with list of objects in group */
2425                 ob= group_objects_menu(ob->dup_group);
2426         }
2427         else if(ob->id.lib) {
2428                 if(okee("Make Proxy Object")==0)
2429                 return;
2430         }
2431         else {
2432                 error("Can only make proxy for a referenced object or group");
2433                 return;
2434         }
2435         
2436         if(ob) {
2437                 Object *newob;
2438                 Base *newbase, *oldbase= BASACT;
2439                 char name[32];
2440                 
2441                 newob= add_object(scene, OB_EMPTY);
2442                 if(gob)
2443                         strcpy(name, gob->id.name+2);
2444                 else
2445                         strcpy(name, ob->id.name+2);
2446                 strcat(name, "_proxy");
2447                 rename_id(&newob->id, name);
2448                 
2449                 /* set layers OK */
2450                 newbase= BASACT;        /* add_object sets active... */
2451                 newbase->lay= oldbase->lay;
2452                 newob->lay= newbase->lay;
2453                 
2454                 /* remove base, leave user count of object, it gets linked in object_make_proxy */
2455                 if(gob==NULL) {
2456                         BLI_remlink(&scene->base, oldbase);
2457                         MEM_freeN(oldbase);
2458                 }               
2459                 object_make_proxy(newob, ob, gob);
2460                 
2461                 DAG_scene_sort(scene);
2462                 DAG_object_flush_update(scene, newob, OB_RECALC);
2463         }
2464 }
2465
2466 /* ******************** make parent operator *********************** */
2467
2468 #define PAR_OBJECT              0
2469 #define PAR_ARMATURE    1
2470 #define PAR_BONE                2
2471 #define PAR_CURVE               3
2472 #define PAR_FOLLOW              4
2473 #define PAR_PATH_CONST  5
2474 #define PAR_LATTICE             6
2475 #define PAR_VERTEX              7
2476 #define PAR_TRIA                8
2477
2478 static EnumPropertyItem prop_make_parent_types[] = {
2479         {PAR_OBJECT, "OBJECT", "Object", ""},
2480         {PAR_ARMATURE, "ARMATURE", "Armature Deform", ""},
2481         {PAR_BONE, "BONE", "Bone", ""},
2482         {PAR_CURVE, "CURVE", "Curve Deform", ""},
2483         {PAR_FOLLOW, "FOLLOW", "Follow Path", ""},
2484         {PAR_PATH_CONST, "PATH_CONST", "Path Constraint", ""},
2485         {PAR_LATTICE, "LATTICE", "Lattice Deform", ""},
2486         {PAR_VERTEX, "VERTEX", "Vertex", ""},
2487         {PAR_TRIA, "TRIA", "Triangle", ""},
2488         {0, NULL, NULL, NULL}
2489 };
2490
2491 static int test_parent_loop(Object *par, Object *ob)
2492 {
2493         /* test if 'ob' is a parent somewhere in par's parents */
2494         
2495         if(par == NULL) return 0;
2496         if(ob == par) return 1;
2497         
2498         return test_parent_loop(par->parent, ob);
2499 }
2500
2501
2502 static int parent_set_exec(bContext *C, wmOperator *op)
2503 {
2504         Scene *scene= CTX_data_scene(C);
2505         Object *par= CTX_data_active_object(C);
2506         bPoseChannel *pchan= NULL;
2507         int partype= RNA_enum_get(op->ptr, "type");
2508         
2509         par->recalc |= OB_RECALC_OB;
2510         
2511         /* preconditions */
2512         if(partype==PAR_FOLLOW || partype==PAR_PATH_CONST) {
2513                 if(par->type!=OB_CURVE)
2514                         return OPERATOR_CANCELLED;
2515                 else {
2516                         Curve *cu= par->data;
2517                         
2518                         if((cu->flag & CU_PATH)==0) {
2519                                 cu->flag |= CU_PATH|CU_FOLLOW;
2520                                 makeDispListCurveTypes(scene, par, 0);  /* force creation of path data */
2521                         }
2522                         else cu->flag |= CU_FOLLOW;
2523                         
2524                         /* fall back on regular parenting now */
2525                         partype= PAR_OBJECT;
2526                 }               
2527         }
2528         else if(partype==PAR_BONE) {
2529                 pchan= get_active_posechannel(par);
2530                 
2531                 if(pchan==NULL) {
2532                         error("No active Bone");
2533                         return OPERATOR_CANCELLED;
2534                 }
2535         }
2536         
2537         /* context itterator */
2538         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2539                 
2540                 if(ob!=par) {
2541                         
2542                         if( test_parent_loop(par, ob) ) {
2543                                 error("Loop in parents");
2544                         }
2545                         else {
2546                                 Object workob;
2547                                 
2548                                 /* apply transformation of previous parenting */
2549                                 ED_object_apply_obmat(ob);
2550                                 
2551                                 ob->parent= par;
2552                                 
2553                                 /* handle types */
2554                                 if (pchan)
2555                                         strcpy (ob->parsubstr, pchan->name);
2556                                 else
2557                                         ob->parsubstr[0]= 0;
2558                                 
2559                                 /* constraint */
2560                                 if(partype==PAR_PATH_CONST) {
2561                                         bConstraint *con;
2562                                         bFollowPathConstraint *data;
2563                                         float cmat[4][4], vec[3];
2564                                         
2565                                         con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
2566                                         strcpy (con->name, "AutoPath");
2567                                         
2568                                         data = con->data;
2569                                         data->tar = par;
2570                                         
2571                                         add_constraint_to_object(con, ob);
2572                                         
2573                                         get_constraint_target_matrix(con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra - give_timeoffset(ob));
2574                                         VecSubf(vec, ob->obmat[3], cmat[3]);
2575                                         
2576                                         ob->loc[0] = vec[0];
2577                                         ob->loc[1] = vec[1];
2578                                 }
2579                                 else if(partype==PAR_ARMATURE && ob->type==OB_MESH && par->type == OB_ARMATURE) {
2580                                         
2581                                         if(1) {
2582                                                 /* Prompt the user as to whether he wants to
2583                                                 * add some vertex groups based on the bones
2584                                                 * in the parent armature.
2585                                                 */
2586                                                 create_vgroups_from_armature(scene, ob, par);
2587                                                 
2588                                                 /* get corrected inverse */
2589                                                 ob->partype= PAROBJECT;
2590                                                 what_does_parent(scene, ob, &workob);
2591                                                 
2592                                                 ob->partype= PARSKEL;
2593                                         }
2594                                         else
2595                                                 what_does_parent(scene, ob, &workob);
2596                                         
2597                                         Mat4Invert(ob->parentinv, workob.obmat);
2598                                 }
2599                                 else {
2600                                         /* calculate inverse parent matrix */
2601                                         what_does_parent(scene, ob, &workob);
2602                                         Mat4Invert(ob->parentinv, workob.obmat);
2603                                 }
2604                                 
2605                                 ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
2606                                 
2607                                 if( ELEM3(partype, PAR_CURVE, PAR_ARMATURE, PAR_LATTICE) )
2608                                         ob->partype= PARSKEL; /* note, dna define, not operator property */
2609                                 else
2610                                         ob->partype= PAROBJECT; /* note, dna define, not operator property */
2611                         }
2612                 }
2613         }
2614         CTX_DATA_END;
2615         
2616         DAG_scene_sort(CTX_data_scene(C));
2617         ED_anim_dag_flush_update(C);    
2618         
2619         return OPERATOR_FINISHED;
2620 }
2621
2622 static int parent_set_invoke(bContext *C, wmOperator *op, wmEvent *event)
2623 {
2624         Object *ob= CTX_data_active_object(C);
2625         uiMenuItem *head= uiPupMenuBegin("Set Parent To", 0);
2626         
2627         uiMenuContext(head, WM_OP_EXEC_DEFAULT);
2628         uiMenuItemEnumO(head, "", 0, "OBJECT_OT_parent_set", "type", PAR_OBJECT);
2629         
2630         /* ob becomes parent, make the associated menus */
2631         if(ob->type==OB_ARMATURE) {
2632                 uiMenuItemEnumO(head, "", 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE);
2633                 uiMenuItemEnumO(head, "", 0, "OBJECT_OT_parent_set", "type", PAR_BONE);
2634         }
2635         else if(ob->type==OB_CURVE) {
2636                 uiMenuItemEnumO(head, "", 0, "OBJECT_OT_parent_set", "type", PAR_CURVE);
2637                 uiMenuItemEnumO(head, "", 0, "OBJECT_OT_parent_set", "type", PAR_FOLLOW);
2638                 uiMenuItemEnumO(head, "", 0, "OBJECT_OT_parent_set", "type", PAR_PATH_CONST);
2639         }
2640         else if(ob->type == OB_LATTICE) {
2641                 uiMenuItemEnumO(head, "", 0, "OBJECT_OT_parent_set", "type", PAR_LATTICE);
2642         }
2643         
2644         uiPupMenuEnd(C, head);
2645         
2646         return OPERATOR_CANCELLED;
2647 }
2648
2649
2650 void OBJECT_OT_parent_set(wmOperatorType *ot)
2651 {
2652         /* identifiers */
2653         ot->name= "Make parent";
2654         ot->description = "Set the object's parenting.";
2655         ot->idname= "OBJECT_OT_parent_set";
2656         
2657         /* api callbacks */
2658         ot->invoke= parent_set_invoke;
2659         ot->exec= parent_set_exec;
2660         
2661         ot->poll= ED_operator_object_active;
2662         
2663         /* flags */
2664         ot->flag= 0;
2665         
2666         RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
2667 }
2668
2669 /* *** make track ***** */
2670 static EnumPropertyItem prop_make_track_types[] = {
2671         {1, "TRACKTO", "TrackTo Constraint", ""},
2672         {2, "LOCKTRACK", "LockTrack Constraint", ""},
2673         {3, "OLDTRACK", "Old Track", ""},
2674         {0, NULL, NULL, NULL}
2675 };
2676
2677 static int track_set_exec(bContext *C, wmOperator *op)
2678 {
2679         Scene *scene= CTX_data_scene(C);
2680                 
2681         if(RNA_enum_is_equal(op->ptr, "type", "TRACKTO")){
2682                 bConstraint *con;
2683                 bTrackToConstraint *data;
2684
2685                 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2686                         if(base!=BASACT) {
2687                                 con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
2688                                 strcpy (con->name, "AutoTrack");
2689
2690                                 data = con->data;
2691                                 data->tar = BASACT->object;
2692                                 base->object->recalc |= OB_RECALC;
2693                                 
2694                                 /* Lamp and Camera track differently by default */
2695                                 if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
2696                                         data->reserved1 = TRACK_nZ;
2697                                         data->reserved2 = UP_Y;
2698                                 }
2699
2700                                 add_constraint_to_object(con, base->object);
2701                         }
2702                 }
2703                 CTX_DATA_END;
2704         }
2705         else if(RNA_enum_is_equal(op->ptr, "type", "LOCKTRACK")){
2706                 bConstraint *con;
2707                 bLockTrackConstraint *data;
2708
2709                 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2710                         if(base!=BASACT) {
2711                                 con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
2712                                 strcpy (con->name, "AutoTrack");
2713
2714                                 data = con->data;
2715                                 data->tar = BASACT->object;
2716                                 base->object->recalc |= OB_RECALC;
2717                                 
2718                                 /* Lamp and Camera track differently by default */
2719                                 if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
2720                                         data->trackflag = TRACK_nZ;
2721                                         data->lockflag = LOCK_Y;
2722                                 }
2723
2724                                 add_constraint_to_object(con, base->object);
2725                         }
2726                 }
2727                 CTX_DATA_END;
2728         }
2729         else if(RNA_enum_is_equal(op->ptr, "type", "OLDTRACK")){
2730                 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2731                         if(base!=BASACT) {
2732                                 base->object->track= BASACT->object;
2733                                 base->object->recalc |= OB_RECALC;
2734                         }
2735                 }
2736                 CTX_DATA_END;
2737         }
2738         DAG_scene_sort(CTX_data_scene(C));
2739         ED_anim_dag_flush_update(C);    
2740         
2741         return OPERATOR_FINISHED;
2742 }
2743
2744 void OBJECT_OT_track_set(wmOperatorType *ot)
2745 {
2746         /* identifiers */
2747         ot->name= "Make Track";
2748         ot->description = "Make the object track another object, either by constraint or old way or locked track.";
2749         ot->idname= "OBJECT_OT_track_set";
2750         
2751         /* api callbacks */
2752         ot->invoke= WM_menu_invoke;
2753         ot->exec= track_set_exec;
2754         
2755         ot->poll= ED_operator_scene_editable;
2756         
2757         /* flags */
2758         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2759         
2760         RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
2761 }
2762
2763 /* ************* Make Dupli Real ********* */
2764 static void make_object_duplilist_real(Scene *scene, View3D *v3d, Base *base)
2765 {
2766         Base *basen;
2767         Object *ob;
2768         ListBase *lb;
2769         DupliObject *dob;
2770         
2771         if(!base && !(base = BASACT))
2772                 return;
2773         
2774         if(!(base->object->transflag & OB_DUPLI))
2775                 return;
2776         
2777         lb= object_duplilist(scene, base->object);
2778         
2779         for(dob= lb->first; dob; dob= dob->next) {
2780                 ob= copy_object(dob->ob);
2781                 /* font duplis can have a totcol without material, we get them from parent
2782                 * should be implemented better...
2783                 */
2784                 if(ob->mat==NULL) ob->totcol= 0;
2785                 
2786                 basen= MEM_dupallocN(base);
2787                 basen->flag &= ~OB_FROMDUPLI;
2788                 BLI_addhead(&scene->base, basen);       /* addhead: othwise eternal loop */
2789                 basen->object= ob;
2790                 ob->ipo= NULL;          /* make sure apply works */
2791                 ob->parent= ob->track= NULL;
2792                 ob->disp.first= ob->disp.last= NULL;
2793                 ob->transflag &= ~OB_DUPLI;     
2794                 
2795                 Mat4CpyMat4(ob->obmat, dob->mat);
2796                 ED_object_apply_obmat(ob);
2797         }
2798         
2799         copy_object_set_idnew(scene, v3d, 0);
2800         
2801         free_object_duplilist(lb);
2802         
2803         base->object->transflag &= ~OB_DUPLI;   
2804 }
2805
2806
2807 static int object_dupli_set_real_exec(bContext *C, wmOperator *op)
2808 {
2809         Scene *scene= CTX_data_scene(C);
2810         ScrArea *sa= CTX_wm_area(C);
2811         View3D *v3d= sa->spacedata.first;
2812         
2813         clear_id_newpoins();
2814                 
2815         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2816                 make_object_duplilist_real(scene, v3d, base);
2817         }
2818         CTX_DATA_END;
2819
2820         DAG_scene_sort(CTX_data_scene(C));
2821         ED_anim_dag_flush_update(C);    
2822         WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
2823         
2824         return OPERATOR_FINISHED;
2825 }
2826
2827 void OBJECT_OT_dupli_set_real(wmOperatorType *ot)
2828 {
2829         
2830         /* identifiers */
2831         ot->name= "Make Dupli Real";
2832         ot->description = "Make dupli objects attached to this object real.";
2833         ot->idname= "OBJECT_OT_dupli_set_real";
2834         
2835         /* api callbacks */
2836         ot->invoke= WM_operator_confirm;
2837         ot->exec= object_dupli_set_real_exec;
2838         
2839         ot->poll= ED_operator_scene_editable;
2840         
2841         /* flags */
2842         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2843 }
2844 /* ******************* Set Object Center ********************** */
2845
2846 static EnumPropertyItem prop_set_center_types[] = {
2847         {0, "CENTER", "ObData to Center", "Move object data around Object center"},
2848         {1, "CENTERNEW", "Center New", "Move Object center to center of object data"},
2849         {2, "CENTERCURSOR", "Center Cursor", "Move Object Center to position of the 3d cursor"},
2850         {0, NULL, NULL, NULL}
2851 };
2852
2853 /* 0 == do center, 1 == center new, 2 == center cursor */
2854 static int object_center_set_exec(bContext *C, wmOperator *op)
2855 {
2856         Scene *scene= CTX_data_scene(C);
2857         ScrArea *sa= CTX_wm_area(C);
2858         View3D *v3d= sa->spacedata.first;
2859         Object *obedit= CTX_data_edit_object(C);
2860         Object *ob;
2861         Mesh *me, *tme;
2862         Curve *cu;
2863 /*      BezTriple *bezt;
2864         BPoint *bp; */
2865         Nurb *nu, *nu1;
2866         EditVert *eve;
2867         float cent[3], centn[3], min[3], max[3], omat[3][3];
2868         int a, total= 0;
2869         int centermode = RNA_enum_get(op->ptr, "type");
2870         
2871         /* keep track of what is changed */
2872         int tot_change=0, tot_lib_error=0, tot_multiuser_arm_error=0;
2873         MVert *mvert;
2874
2875         if(scene->id.lib || v3d==NULL){
2876                 BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed on Lib data");
2877                  return OPERATOR_CANCELLED;
2878         }
2879         if (obedit && centermode > 0) {
2880                 BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in EditMode");
2881                 return OPERATOR_CANCELLED;
2882         }       
2883         cent[0]= cent[1]= cent[2]= 0.0; 
2884         
2885         if(obedit) {
2886
2887                 INIT_MINMAX(min, max);
2888         
2889                 if(obedit->type==OB_MESH) {
2890                         Mesh *me= obedit->data;
2891                         EditMesh *em = BKE_mesh_get_editmesh(me);
2892
2893                         for(eve= em->verts.first; eve; eve= eve->next) {
2894                                 if(v3d->around==V3D_CENTROID) {
2895                                         total++;
2896                                         VECADD(cent, cent, eve->co);
2897                                 }
2898                                 else {
2899                                         DO_MINMAX(eve->co, min, max);
2900                                 }
2901                         }
2902                         
2903                         if(v3d->around==V3D_CENTROID) {
2904                                 VecMulf(cent, 1.0f/(float)total);
2905                         }
2906                         else {
2907                                 cent[0]= (min[0]+max[0])/2.0f;
2908                                 cent[1]= (min[1]+max[1])/2.0f;
2909                                 cent[2]= (min[2]+max[2])/2.0f;
2910                         }
2911                         
2912                         for(eve= em->verts.first; eve; eve= eve->next) {
2913                                 VecSubf(eve->co, eve->co, cent);                        
2914                         }
2915                         
2916                         recalc_editnormals(em);
2917                         tot_change++;
2918                         DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
2919                         BKE_mesh_end_editmesh(me, em);
2920                 }
2921         }
2922         
2923         /* reset flags */
2924         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2925                         base->object->flag &= ~OB_DONE;
2926         }
2927         CTX_DATA_END;
2928         
2929         for (me= G.main->mesh.first; me; me= me->id.next) {
2930                 me->flag &= ~ME_ISDONE;
2931         }
2932         
2933         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2934                 if((base->object->flag & OB_DONE)==0) {
2935                         base->object->flag |= OB_DONE;
2936                                 
2937                         if(obedit==NULL && (me=get_mesh(base->object)) ) {
2938                                 if (me->id.lib) {
2939                                         tot_lib_error++;
2940                                 } else {
2941                                         if(centermode==2) {
2942                                                 VECCOPY(cent, give_cursor(scene, v3d));
2943                                                 Mat4Invert(base->object->imat, base->object->obmat);
2944                                                 Mat4MulVecfl(base->object->imat, cent);
2945                                         } else {
2946                                                 INIT_MINMAX(min, max);
2947                                                 mvert= me->mvert;
2948                                                 for(a=0; a<me->totvert; a++, mvert++) {
2949                                                         DO_MINMAX(mvert->co, min, max);
2950                                                 }
2951                                         
2952                                                 cent[0]= (min[0]+max[0])/2.0f;
2953                                                 cent[1]= (min[1]+max[1])/2.0f;
2954                                                 cent[2]= (min[2]+max[2])/2.0f;
2955                                         }
2956
2957                                         mvert= me->mvert;
2958                                         for(a=0; a<me->totvert; a++, mvert++) {
2959                                                 VecSubf(mvert->co, mvert->co, cent);
2960                                         }
2961                                         
2962                                         if (me->key) {
2963                                                 KeyBlock *kb;
2964                                                 for (kb=me->key->block.first; kb; kb=kb->next) {
2965                                                         float *fp= kb->data;
2966                                                         
2967                                                         for (a=0; a<kb->totelem; a++, fp+=3) {
2968                                                                 VecSubf(fp, fp, cent);
2969                                                         }
2970                                                 }
2971                                         }
2972                                                 
2973                                         me->flag |= ME_ISDONE;
2974                                                 
2975                                         if(centermode) {
2976                                                 Mat3CpyMat4(omat, base->object->obmat);
2977                                                 
2978                                                 VECCOPY(centn, cent);
2979                                                 Mat3MulVecfl(omat, centn);
2980                                                 base->object->loc[0]+= centn[0];
2981                                                 base->object->loc[1]+= centn[1];
2982                                                 base->object->loc[2]+= centn[2];
2983                                                 
2984                                                 where_is_object(scene, base->object);
2985                                                 ignore_parent_tx(scene, base->object);
2986                                                 
2987                                                 /* other users? */
2988                                                 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2989                                                         ob = base->object;
2990                                                         if((ob->flag & OB_DONE)==0) {
2991                                                                 tme= get_mesh(ob);
2992                                                                 
2993                                                                 if(tme==me) {
2994                                                                         
2995                                                                         ob->flag |= OB_DONE;
2996                                                                         ob->recalc= OB_RECALC_OB|OB_RECALC_DATA;
2997
2998                                                                         Mat3CpyMat4(omat, ob->obmat);
2999                                                                         VECCOPY(centn, cent);
3000                                                                         Mat3MulVecfl(omat, centn);
3001                                                                         ob->loc[0]+= centn[0];
3002                                                                         ob->loc[1]+= centn[1];
3003                                                                         ob->loc[2]+= centn[2];
3004                                                                         
3005                                                                         where_is_object(scene, ob);
3006                                                                         ignore_parent_tx(scene, ob);
3007                                                                         
3008                                                                         if(tme && (tme->flag & ME_ISDONE)==0) {
3009                                                                                 mvert= tme->mvert;
3010                                                                                 for(a=0; a<tme->totvert; a++, mvert++) {
3011                                                                                         VecSubf(mvert->co, mvert->co, cent);
3012                                                                                 }
3013                                                                                 
3014                                                                                 if (tme->key) {
3015                                                                                         KeyBlock *kb;
3016                                                                                         for (kb=tme->key->block.first; kb; kb=kb->next) {
3017                                                                                                 float *fp= kb->data;
3018                                                                                                 
3019                                                                                                 for (a=0; a<kb->totelem; a++, fp+=3) {
3020                                                                                                         VecSubf(fp, fp, cent);
3021                                                                                                 }
3022                                                                                         }
3023                                                                                 }
3024                                                                                 
3025                                                                                 tme->flag |= ME_ISDONE;
3026                                                                         }
3027                                                                 }
3028                                                         }
3029                                                         
3030                                                         ob= ob->id.next;
3031                                                 }
3032                                                 CTX_DATA_END;
3033                                         }
3034                                         tot_change++;
3035                                 }
3036                         }
3037                         else if (ELEM(base->object->type, OB_CURVE, OB_SURF)) {
3038                                 
3039                                 /* weak code here... (ton) */
3040                                 if(obedit==base->object) {
3041                                         ListBase *editnurb= curve_get_editcurve(obedit);
3042
3043                                         nu1= editnurb->first;
3044                                         cu= obedit->data;
3045                                 }
3046                                 else {
3047                                         cu= base->object->data;
3048                                         nu1= cu->nurb.first;
3049                                 }
3050                                 
3051                                 if (cu->id.lib) {
3052                                         tot_lib_error++;
3053                                 } else {
3054                                         if(centermode==2) {
3055                                                 VECCOPY(cent, give_cursor(scene, v3d));
3056                                                 Mat4Invert(base->object->imat, base->object->obmat);
3057                                                 Mat4MulVecfl(base->object->imat, cent);
3058
3059                                                 /* don't allow Z change if curve is 2D */
3060                                                 if( !( cu->flag & CU_3D ) )
3061                                                         cent[2] = 0.0;
3062                                         } 
3063                                         else {
3064                                                 INIT_MINMAX(min, max);
3065                                                 
3066                                                 nu= nu1;
3067                                                 while(nu) {
3068                                                         minmaxNurb(nu, min, max);
3069                                                         nu= nu->next;
3070                                                 }
3071                                                 
3072                                                 cent[0]= (min[0]+max[0])/2.0f;
3073                                                 cent[1]= (min[1]+max[1])/2.0f;
3074                                                 cent[2]= (min[2]+max[2])/2.0f;
3075                                         }
3076                                         
3077                                         nu= nu1;
3078                                         while(nu) {
3079                                                 if( (nu->type & 7)==CU_BEZIER) {
3080                                                         a= nu->pntsu;
3081                                                         while (a--) {
3082                                                                 VecSubf(nu->bezt[a].vec[0], nu->bezt[a].vec[0], cent);
3083                                                                 VecSubf(nu->bezt[a].vec[1], nu->bezt[a].vec[1], cent);
3084                                                                 VecSubf(nu->bezt[a].vec[2], nu->bezt[a].vec[2], cent);
3085   &nbs