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