61377d76c56b55ba0e4277b1737f4f1ce91145da
[blender.git] / source / blender / editors / object / object_add.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
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "DNA_action_types.h"
34 #include "DNA_curve_types.h"
35 #include "DNA_group_types.h"
36 #include "DNA_lamp_types.h"
37 #include "DNA_material_types.h"
38 #include "DNA_mesh_types.h"
39 #include "DNA_meta_types.h"
40 #include "DNA_object_fluidsim.h"
41 #include "DNA_object_types.h"
42 #include "DNA_object_force.h"
43 #include "DNA_scene_types.h"
44 #include "DNA_screen_types.h"
45 #include "DNA_userdef_types.h"
46 #include "DNA_view3d_types.h"
47 #include "DNA_vfont_types.h"
48
49 #include "BLI_math.h"
50 #include "BLI_listbase.h"
51
52 #include "BKE_anim.h"
53 #include "BKE_armature.h"
54 #include "BKE_constraint.h"
55 #include "BKE_context.h"
56 #include "BKE_curve.h"
57 #include "BKE_customdata.h"
58 #include "BKE_depsgraph.h"
59 #include "BKE_DerivedMesh.h"
60 #include "BKE_displist.h"
61 #include "BKE_effect.h"
62 #include "BKE_global.h"
63 #include "BKE_group.h"
64 #include "BKE_lattice.h"
65 #include "BKE_library.h"
66 #include "BKE_main.h"
67 #include "BKE_material.h"
68 #include "BKE_mball.h"
69 #include "BKE_mesh.h"
70 #include "BKE_modifier.h"
71 #include "BKE_object.h"
72 #include "BKE_particle.h"
73 #include "BKE_report.h"
74 #include "BKE_sca.h"
75 #include "BKE_scene.h"
76 #include "BKE_texture.h"
77 #include "BKE_utildefines.h"
78
79 #include "RNA_access.h"
80 #include "RNA_define.h"
81 #include "RNA_enum_types.h"
82
83 #include "WM_api.h"
84 #include "WM_types.h"
85
86 #include "ED_anim_api.h"
87 #include "ED_armature.h"
88 #include "ED_curve.h"
89 #include "ED_mball.h"
90 #include "ED_mesh.h"
91 #include "ED_object.h"
92 #include "ED_screen.h"
93 #include "ED_transform.h"
94
95 #include "UI_interface.h"
96 #include "UI_resources.h"
97
98 #include "object_intern.h"
99
100 /************************** Exported *****************************/
101
102 void ED_object_base_init_from_view(bContext *C, Base *base, int view_align)
103 {
104         View3D *v3d= CTX_wm_view3d(C);
105         Scene *scene= CTX_data_scene(C);
106         Object *ob= base->object;
107         
108         if (scene==NULL)
109                 return;
110         
111         if (v3d==NULL) {
112                 base->lay = scene->lay;
113                 VECCOPY(ob->loc, scene->cursor);
114         } 
115         else {
116                 if (v3d->localvd) {
117                         base->lay= ob->lay= v3d->layact | v3d->lay;
118                         VECCOPY(ob->loc, v3d->cursor);
119                 } 
120                 else {
121                         base->lay= ob->lay= v3d->layact;
122                         VECCOPY(ob->loc, scene->cursor);
123                 }
124                 
125                 if (view_align) {
126                         RegionView3D *rv3d = CTX_wm_region_view3d(C);
127                         if(rv3d) {
128                                 rv3d->viewquat[0]= -rv3d->viewquat[0];
129                                 quat_to_eul( ob->rot,rv3d->viewquat);
130                                 rv3d->viewquat[0]= -rv3d->viewquat[0];
131                         }
132                 }
133         }
134         where_is_object(scene, ob);
135 }
136
137 /********************* Add Object Operator ********************/
138
139 void add_object_draw(Scene *scene, View3D *v3d, int type)       /* for toolbox or menus, only non-editmode stuff */
140 {
141         /* keep here to get things compile, remove later */
142 }
143
144 void ED_object_add_generic_props(wmOperatorType *ot, int do_editmode)
145 {
146         RNA_def_boolean(ot->srna, "view_align", 0, "View Align", "Align the new object to the view.");
147
148         if(do_editmode)
149                 RNA_def_boolean(ot->srna, "enter_editmode", 0, "Enter Editmode", "Enter editmode when adding this object.");
150 }
151
152 static void object_add_generic_invoke_options(bContext *C, wmOperator *op)
153 {
154         if (!RNA_property_is_set(op->ptr, "view_align"))
155                 RNA_boolean_set(op->ptr, "view_align", U.flag & USER_ADD_VIEWALIGNED);
156
157         if(RNA_struct_find_property(op->ptr, "enter_editmode")) /* optional */
158                 if (!RNA_property_is_set(op->ptr, "enter_editmode"))
159                         RNA_boolean_set(op->ptr, "enter_editmode", U.flag & USER_ADD_EDITMODE);
160 }
161
162 int ED_object_add_generic_invoke(bContext *C, wmOperator *op, wmEvent *event)
163 {
164         object_add_generic_invoke_options(C, op);
165         return op->type->exec(C, op);
166 }
167
168 void ED_object_add_generic_get_opts(wmOperator *op, int *view_align, int *enter_editmode)
169 {
170         *view_align= RNA_boolean_get(op->ptr, "view_align");
171         *enter_editmode = FALSE;
172
173         if(RNA_struct_find_property(op->ptr, "enter_editmode") && RNA_boolean_get(op->ptr, "enter_editmode")) {
174                 *enter_editmode = TRUE;
175         }
176 }
177
178 /* for object add primitive operators */
179 Object *ED_object_add_type(bContext *C, int type, int view_align, int enter_editmode)
180 {
181         Scene *scene= CTX_data_scene(C);
182         Object *ob;
183         
184         /* for as long scene has editmode... */
185         if (CTX_data_edit_object(C)) 
186                 ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR|EM_DO_UNDO); /* freedata, and undo */
187         
188         /* deselects all, sets scene->basact */
189         ob= add_object(scene, type);
190         /* editor level activate, notifiers */
191         ED_base_object_activate(C, BASACT);
192
193         /* more editor stuff */
194         ED_object_base_init_from_view(C, BASACT, view_align);
195
196         DAG_scene_sort(scene);
197
198         if(enter_editmode)
199                 ED_object_enter_editmode(C, EM_IGNORE_LAYER);
200
201         return ob;
202 }
203
204 /* for object add operator */
205 static int object_add_exec(bContext *C, wmOperator *op)
206 {
207         int view_align, enter_editmode;
208         ED_object_add_generic_get_opts(op, &view_align, &enter_editmode);
209         ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), view_align, enter_editmode);
210         
211         return OPERATOR_FINISHED;
212 }
213
214 void OBJECT_OT_add(wmOperatorType *ot)
215 {
216         /* identifiers */
217         ot->name= "Add Object";
218         ot->description = "Add an object to the scene.";
219         ot->idname= "OBJECT_OT_add";
220         
221         /* api callbacks */
222         ot->invoke= ED_object_add_generic_invoke;
223         ot->exec= object_add_exec;
224         
225         ot->poll= ED_operator_scene_editable;
226         
227         /* flags */
228         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
229         
230         RNA_def_enum(ot->srna, "type", object_type_items, 0, "Type", "");
231
232         ED_object_add_generic_props(ot, TRUE);
233 }
234
235 /********************* Add Effector Operator ********************/
236 /* copy from rna_object_force.c*/
237 static EnumPropertyItem field_type_items[] = {
238         {0, "NONE", 0, "None", ""},
239         {PFIELD_FORCE, "FORCE", 0, "Force", ""},
240         {PFIELD_WIND, "WIND", 0, "Wind", ""},
241         {PFIELD_VORTEX, "VORTEX", 0, "Vortex", ""},
242         {PFIELD_MAGNET, "MAGNET", 0, "Magnetic", ""},
243         {PFIELD_HARMONIC, "HARMONIC", 0, "Harmonic", ""},
244         {PFIELD_CHARGE, "CHARGE", 0, "Charge", ""},
245         {PFIELD_LENNARDJ, "LENNARDJ", 0, "Lennard-Jones", ""},
246         {PFIELD_TEXTURE, "TEXTURE", 0, "Texture", ""},
247         {PFIELD_GUIDE, "GUIDE", 0, "Curve Guide", ""},
248         {PFIELD_BOID, "BOID", 0, "Boid", ""},
249         {PFIELD_TURBULENCE, "TURBULENCE", 0, "Turbulence", ""},
250         {PFIELD_DRAG, "DRAG", 0, "Drag", ""},
251         {0, NULL, 0, NULL, NULL}};
252
253 void add_effector_draw(Scene *scene, View3D *v3d, int type)     /* for toolbox or menus, only non-editmode stuff */
254 {
255         /* keep here to get things compile, remove later */
256 }
257
258 /* for effector add primitive operators */
259 static Object *effector_add_type(bContext *C, wmOperator *op, int type)
260 {
261         Object *ob;
262         int view_align, enter_editmode;
263         ED_object_add_generic_get_opts(op, &view_align, &enter_editmode);
264
265         if(type==PFIELD_GUIDE) {
266                 ob= ED_object_add_type(C, OB_CURVE, view_align, FALSE);
267                 rename_id(&ob->id, "CurveGuide");
268
269                 ((Curve*)ob->data)->flag |= CU_PATH|CU_3D;
270                 ED_object_enter_editmode(C, 0);
271                 BLI_addtail(curve_get_editcurve(ob), add_nurbs_primitive(C, CU_NURBS|CU_PRIM_PATH, 1));
272
273                 if(!enter_editmode)
274                         ED_object_exit_editmode(C, EM_FREEDATA|EM_DO_UNDO);
275         }
276         else {
277                 ob= ED_object_add_type(C, OB_EMPTY, view_align, FALSE);
278                 rename_id(&ob->id, "Field");
279
280                 switch(type) {
281                         case PFIELD_WIND:
282                         case PFIELD_VORTEX:
283                                 ob->empty_drawtype = OB_SINGLE_ARROW;
284                                 break;
285                 }
286         }
287
288         ob->pd= object_add_collision_fields(type);
289
290         return ob;
291 }
292
293 /* for object add operator */
294 static int effector_add_exec(bContext *C, wmOperator *op)
295 {
296         effector_add_type(C, op, RNA_int_get(op->ptr, "type"));
297         
298         return OPERATOR_FINISHED;
299 }
300
301 void OBJECT_OT_effector_add(wmOperatorType *ot)
302 {
303         /* identifiers */
304         ot->name= "Add Effector";
305         ot->description = "Add an empty object with a physics effector to the scene.";
306         ot->idname= "OBJECT_OT_effector_add";
307         
308         /* api callbacks */
309         ot->invoke= WM_menu_invoke;
310         ot->exec= effector_add_exec;
311         
312         ot->poll= ED_operator_scene_editable;
313         
314         /* flags */
315         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
316         
317         RNA_def_enum(ot->srna, "type", field_type_items, 0, "Type", "");
318
319         ED_object_add_generic_props(ot, TRUE);
320 }
321
322 /* ***************** add primitives *************** */
323
324 static EnumPropertyItem prop_curve_types[] = {
325         {CU_BEZIER|CU_PRIM_CURVE, "BEZIER_CURVE", ICON_CURVE_BEZCURVE, "Bezier Curve", ""},
326         {CU_BEZIER|CU_PRIM_CIRCLE, "BEZIER_CIRCLE", ICON_CURVE_BEZCIRCLE, "Bezier Circle", ""},
327         {CU_NURBS|CU_PRIM_CURVE, "NURBS_CURVE", ICON_CURVE_NCURVE, "NURBS Curve", ""},
328         {CU_NURBS|CU_PRIM_CIRCLE, "NURBS_CIRCLE", ICON_CURVE_NCIRCLE, "NURBS Circle", ""},
329         {CU_NURBS|CU_PRIM_PATH, "PATH", ICON_CURVE_PATH, "Path", ""},
330         {0, NULL, 0, NULL, NULL}
331 };
332
333 static int object_add_curve_exec(bContext *C, wmOperator *op)
334 {
335         Object *obedit= CTX_data_edit_object(C);
336         ListBase *editnurb;
337         Nurb *nu;
338         int newob= 0, type= RNA_enum_get(op->ptr, "type");
339         int view_align, enter_editmode;
340         
341         object_add_generic_invoke_options(C, op); // XXX these props don't get set right when only exec() is called
342         ED_object_add_generic_get_opts(op, &view_align, &enter_editmode);
343         
344         if(obedit==NULL || obedit->type!=OB_CURVE) {
345                 obedit= ED_object_add_type(C, OB_CURVE, view_align, TRUE);
346                 newob = 1;
347
348                 if(type & CU_PRIM_PATH)
349                         ((Curve*)obedit->data)->flag |= CU_PATH|CU_3D;
350         }
351         else DAG_id_flush_update(&obedit->id, OB_RECALC_DATA);
352         
353         nu= add_nurbs_primitive(C, type, newob);
354         editnurb= curve_get_editcurve(obedit);
355         BLI_addtail(editnurb, nu);
356         
357         /* userdef */
358         if (newob && !enter_editmode) {
359                 ED_object_exit_editmode(C, EM_FREEDATA|EM_DO_UNDO);
360         }
361         
362         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit);
363         
364         return OPERATOR_FINISHED;
365 }
366
367 static int object_add_curve_invoke(bContext *C, wmOperator *op, wmEvent *event)
368 {
369         Object *obedit= CTX_data_edit_object(C);
370         uiPopupMenu *pup;
371         uiLayout *layout;
372
373         object_add_generic_invoke_options(C, op);
374
375         pup= uiPupMenuBegin(C, op->type->name, 0);
376         layout= uiPupMenuLayout(pup);
377         if(!obedit || obedit->type == OB_CURVE)
378                 uiItemsEnumO(layout, op->type->idname, "type");
379         else
380                 uiItemsEnumO(layout, "OBJECT_OT_surface_add", "type");
381         uiPupMenuEnd(C, pup);
382
383         return OPERATOR_CANCELLED;
384 }
385
386 void OBJECT_OT_curve_add(wmOperatorType *ot)
387 {
388         /* identifiers */
389         ot->name= "Add Curve";
390         ot->description = "Add a curve object to the scene.";
391         ot->idname= "OBJECT_OT_curve_add";
392         
393         /* api callbacks */
394         ot->invoke= object_add_curve_invoke;
395         ot->exec= object_add_curve_exec;
396         
397         ot->poll= ED_operator_scene_editable;
398         
399         /* flags */
400         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
401         
402         RNA_def_enum(ot->srna, "type", prop_curve_types, 0, "Primitive", "");
403
404         ED_object_add_generic_props(ot, TRUE);
405 }
406
407 static EnumPropertyItem prop_surface_types[]= {
408         {CU_PRIM_CURVE|CU_NURBS, "NURBS_CURVE", ICON_SURFACE_NCURVE, "NURBS Curve", ""},
409         {CU_PRIM_CIRCLE|CU_NURBS, "NURBS_CIRCLE", ICON_SURFACE_NCIRCLE, "NURBS Circle", ""},
410         {CU_PRIM_PATCH|CU_NURBS, "NURBS_SURFACE", ICON_SURFACE_NSURFACE, "NURBS Surface", ""},
411         {CU_PRIM_TUBE|CU_NURBS, "NURBS_TUBE", ICON_SURFACE_NTUBE, "NURBS Tube", ""},
412         {CU_PRIM_SPHERE|CU_NURBS, "NURBS_SPHERE", ICON_SURFACE_NSPHERE, "NURBS Sphere", ""},
413         {CU_PRIM_DONUT|CU_NURBS, "NURBS_DONUT", ICON_SURFACE_NDONUT, "NURBS Donut", ""},
414         {0, NULL, 0, NULL, NULL}
415 };
416
417 static int object_add_surface_exec(bContext *C, wmOperator *op)
418 {
419         Object *obedit= CTX_data_edit_object(C);
420         ListBase *editnurb;
421         Nurb *nu;
422         int newob= 0;
423         int view_align, enter_editmode;
424         
425         object_add_generic_invoke_options(C, op); // XXX these props don't get set right when only exec() is called
426         ED_object_add_generic_get_opts(op, &view_align, &enter_editmode);
427         
428         if(obedit==NULL || obedit->type!=OB_SURF) {
429                 obedit= ED_object_add_type(C, OB_SURF, view_align, TRUE);
430                 newob = 1;
431         }
432         else DAG_id_flush_update(&obedit->id, OB_RECALC_DATA);
433         
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 && !enter_editmode) {
440                 ED_object_exit_editmode(C, EM_FREEDATA|EM_DO_UNDO);
441         }
442         
443         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit);
444         
445         return OPERATOR_FINISHED;
446 }
447
448 void OBJECT_OT_surface_add(wmOperatorType *ot)
449 {
450         /* identifiers */
451         ot->name= "Add Surface";
452         ot->description = "Add a surface object to the scene.";
453         ot->idname= "OBJECT_OT_surface_add";
454         
455         /* api callbacks */
456         ot->invoke= ED_object_add_generic_invoke; // WM_menu_invoke
457         ot->exec= object_add_surface_exec;
458         
459         ot->poll= ED_operator_scene_editable;
460         
461         /* flags */
462         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
463         
464         RNA_def_enum(ot->srna, "type", prop_surface_types, 0, "Primitive", "");
465         ED_object_add_generic_props(ot, TRUE);
466 }
467
468 static EnumPropertyItem prop_metaball_types[]= {
469         {MB_BALL, "MBALL_BALL", ICON_META_BALL, "Meta Ball", ""},
470         {MB_TUBE, "MBALL_TUBE", ICON_META_TUBE, "Meta Tube", ""},
471         {MB_PLANE, "MBALL_PLANE", ICON_META_PLANE, "Meta Plane", ""},
472         {MB_CUBE, "MBALL_CUBE", ICON_META_CUBE, "Meta Cube", ""},
473         {MB_ELIPSOID, "MBALL_ELLIPSOID", ICON_META_ELLIPSOID, "Meta Ellipsoid", ""},
474         {0, NULL, 0, NULL, NULL}
475 };
476
477 static int object_metaball_add_exec(bContext *C, wmOperator *op)
478 {
479         Object *obedit= CTX_data_edit_object(C);
480         MetaBall *mball;
481         MetaElem *elem;
482         int newob= 0;
483         int view_align, enter_editmode;
484         
485         object_add_generic_invoke_options(C, op); // XXX these props don't get set right when only exec() is called
486         ED_object_add_generic_get_opts(op, &view_align, &enter_editmode);
487         
488         if(obedit==NULL || obedit->type!=OB_MBALL) {
489                 obedit= ED_object_add_type(C, OB_MBALL, view_align, TRUE);
490                 newob = 1;
491         }
492         else DAG_id_flush_update(&obedit->id, OB_RECALC_DATA);
493         
494         elem= (MetaElem*)add_metaball_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
495         mball= (MetaBall*)obedit->data;
496         BLI_addtail(mball->editelems, elem);
497         
498         /* userdef */
499         if (newob && !enter_editmode) {
500                 ED_object_exit_editmode(C, EM_FREEDATA|EM_DO_UNDO);
501         }
502         
503         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit);
504         
505         return OPERATOR_FINISHED;
506 }
507
508 static int object_metaball_add_invoke(bContext *C, wmOperator *op, wmEvent *event)
509 {
510         Object *obedit= CTX_data_edit_object(C);
511         uiPopupMenu *pup;
512         uiLayout *layout;
513
514         object_add_generic_invoke_options(C, op);
515
516         pup= uiPupMenuBegin(C, op->type->name, 0);
517         layout= uiPupMenuLayout(pup);
518         if(!obedit || obedit->type == OB_MBALL)
519                 uiItemsEnumO(layout, op->type->idname, "type");
520         else
521                 uiItemsEnumO(layout, "OBJECT_OT_metaball_add", "type");
522         uiPupMenuEnd(C, pup);
523
524         return OPERATOR_CANCELLED;
525 }
526
527 void OBJECT_OT_metaball_add(wmOperatorType *ot)
528 {
529         /* identifiers */
530         ot->name= "Add Metaball";
531         ot->description= "Add an metaball object to the scene.";
532         ot->idname= "OBJECT_OT_metaball_add";
533
534         /* api callbacks */
535         ot->invoke= object_metaball_add_invoke;
536         ot->exec= object_metaball_add_exec;
537         ot->poll= ED_operator_scene_editable;
538
539         /* flags */
540         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
541         
542         RNA_def_enum(ot->srna, "type", prop_metaball_types, 0, "Primitive", "");
543         ED_object_add_generic_props(ot, TRUE);
544 }
545 static int object_add_text_exec(bContext *C, wmOperator *op)
546 {
547         Object *obedit= CTX_data_edit_object(C);
548         int view_align, enter_editmode;
549         
550         object_add_generic_invoke_options(C, op); // XXX these props don't get set right when only exec() is called
551         ED_object_add_generic_get_opts(op, &view_align, &enter_editmode);
552         
553         if(obedit && obedit->type==OB_FONT)
554                 return OPERATOR_CANCELLED;
555
556         obedit= ED_object_add_type(C, OB_FONT, view_align, enter_editmode);
557         
558         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit);
559         
560         return OPERATOR_FINISHED;
561 }
562
563 void OBJECT_OT_text_add(wmOperatorType *ot)
564 {
565         /* identifiers */
566         ot->name= "Add Text";
567         ot->description = "Add a text object to the scene";
568         ot->idname= "OBJECT_OT_text_add";
569         
570         /* api callbacks */
571         ot->invoke= ED_object_add_generic_invoke;
572         ot->exec= object_add_text_exec;
573         ot->poll= ED_operator_scene_editable;
574         
575         /* flags */
576         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
577         ED_object_add_generic_props(ot, TRUE);
578 }
579
580 static int object_armature_add_exec(bContext *C, wmOperator *op)
581 {
582         Object *obedit= CTX_data_edit_object(C);
583         View3D *v3d= CTX_wm_view3d(C);
584         RegionView3D *rv3d= NULL;
585         int newob= 0;
586         int view_align, enter_editmode;
587         
588         object_add_generic_invoke_options(C, op); // XXX these props don't get set right when only exec() is called
589         ED_object_add_generic_get_opts(op, &view_align, &enter_editmode);
590         
591         if ((obedit==NULL) || (obedit->type != OB_ARMATURE)) {
592                 obedit= ED_object_add_type(C, OB_ARMATURE, view_align, TRUE);
593                 ED_object_enter_editmode(C, 0);
594                 newob = 1;
595         }
596         else DAG_id_flush_update(&obedit->id, OB_RECALC_DATA);
597         
598         if(obedit==NULL) {
599                 BKE_report(op->reports, RPT_ERROR, "Cannot create editmode armature.");
600                 return OPERATOR_CANCELLED;
601         }
602         
603         if(v3d) 
604                 rv3d= CTX_wm_region(C)->regiondata;
605         
606         /* v3d and rv3d are allowed to be NULL */
607         add_primitive_bone(CTX_data_scene(C), v3d, rv3d);
608
609         /* userdef */
610         if (newob && !enter_editmode) {
611                 ED_object_exit_editmode(C, EM_FREEDATA|EM_DO_UNDO);
612         }
613         
614         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit);
615         
616         return OPERATOR_FINISHED;
617 }
618
619 void OBJECT_OT_armature_add(wmOperatorType *ot)
620 {       
621         /* identifiers */
622         ot->name= "Add Armature";
623         ot->description = "Add an armature object to the scene.";
624         ot->idname= "OBJECT_OT_armature_add";
625         
626         /* api callbacks */
627         ot->invoke= ED_object_add_generic_invoke;
628         ot->exec= object_armature_add_exec;
629         ot->poll= ED_operator_scene_editable;
630         
631         /* flags */
632         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
633         ED_object_add_generic_props(ot, TRUE);
634 }
635
636 static int object_lamp_add_exec(bContext *C, wmOperator *op)
637 {
638         Object *ob;
639         int type= RNA_enum_get(op->ptr, "type");
640         int view_align, enter_editmode;
641         ED_object_add_generic_get_opts(op, &view_align, &enter_editmode);
642
643         ob= ED_object_add_type(C, OB_LAMP, view_align, FALSE);
644         if(ob && ob->data)
645                 ((Lamp*)ob->data)->type= type;
646         
647         return OPERATOR_FINISHED;
648 }
649
650 void OBJECT_OT_lamp_add(wmOperatorType *ot)
651 {       
652         static EnumPropertyItem lamp_type_items[] = {
653                 {LA_LOCAL, "POINT", ICON_LAMP_POINT, "Point", "Omnidirectional point light source."},
654                 {LA_SUN, "SUN", ICON_LAMP_SUN, "Sun", "Constant direction parallel ray light source."},
655                 {LA_SPOT, "SPOT", ICON_LAMP_SPOT, "Spot", "Directional cone light source."},
656                 {LA_HEMI, "HEMI", ICON_LAMP_HEMI, "Hemi", "180 degree constant light source."},
657                 {LA_AREA, "AREA", ICON_LAMP_AREA, "Area", "Directional area light source."},
658                 {0, NULL, 0, NULL, NULL}};
659
660         /* identifiers */
661         ot->name= "Add Lamp";
662         ot->description = "Add a lamp object to the scene.";
663         ot->idname= "OBJECT_OT_lamp_add";
664         
665         /* api callbacks */
666         ot->invoke= WM_menu_invoke;
667         ot->exec= object_lamp_add_exec;
668         ot->poll= ED_operator_scene_editable;
669         
670         /* flags */
671         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
672
673         /* properties */
674         RNA_def_enum(ot->srna, "type", lamp_type_items, 0, "Type", "");
675
676         ED_object_add_generic_props(ot, FALSE);
677 }
678
679 static int group_instance_add_exec(bContext *C, wmOperator *op)
680 {
681         Group *group= BLI_findlink(&CTX_data_main(C)->group, RNA_enum_get(op->ptr, "type"));
682
683         int view_align, enter_editmode;
684         ED_object_add_generic_get_opts(op, &view_align, &enter_editmode);
685
686         if(group) {
687                 Object *ob= ED_object_add_type(C, OB_EMPTY, view_align, FALSE);
688                 rename_id(&ob->id, group->id.name+2);
689                 ob->dup_group= group;
690                 ob->transflag |= OB_DUPLIGROUP;
691                 id_us_plus(&group->id);
692
693
694                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
695
696                 return OPERATOR_FINISHED;
697         }
698
699         return OPERATOR_CANCELLED;
700 }
701
702 /* only used as menu */
703 void OBJECT_OT_group_instance_add(wmOperatorType *ot)
704 {
705         PropertyRNA *prop;
706
707         /* identifiers */
708         ot->name= "Add Group Instance";
709         ot->description = "Add a dupligroup instance.";
710         ot->idname= "OBJECT_OT_group_instance_add";
711
712         /* api callbacks */
713         ot->exec= group_instance_add_exec;
714
715         ot->poll= ED_operator_scene_editable;
716
717         /* flags */
718         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
719
720         /* properties */
721         prop= RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Type", "");
722         RNA_def_enum_funcs(prop, RNA_group_itemf);
723         ED_object_add_generic_props(ot, FALSE);
724 }
725
726 /**************************** Delete Object *************************/
727
728 /* remove base from a specific scene */
729 /* note: now unlinks constraints as well */
730 void ED_base_object_free_and_unlink(Scene *scene, Base *base)
731 {
732         BLI_remlink(&scene->base, base);
733         free_libblock_us(&G.main->object, base->object);
734         if(scene->basact==base) scene->basact= NULL;
735         MEM_freeN(base);
736 }
737
738 static int object_delete_exec(bContext *C, wmOperator *op)
739 {
740         Scene *scene= CTX_data_scene(C);
741         int islamp= 0;
742         
743         if(CTX_data_edit_object(C)) 
744                 return OPERATOR_CANCELLED;
745         
746         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
747
748                 if(base->object->type==OB_LAMP) islamp= 1;
749                 
750                 /* remove from current scene only */
751                 ED_base_object_free_and_unlink(scene, base);
752         }
753         CTX_DATA_END;
754
755         if(islamp) reshadeall_displist(scene);  /* only frees displist */
756         
757         DAG_scene_sort(scene);
758         ED_anim_dag_flush_update(C);
759         
760         WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, CTX_data_scene(C));
761         
762         return OPERATOR_FINISHED;
763 }
764
765 void OBJECT_OT_delete(wmOperatorType *ot)
766 {
767         /* identifiers */
768         ot->name= "Delete";
769         ot->description = "Delete selected objects.";
770         ot->idname= "OBJECT_OT_delete";
771         
772         /* api callbacks */
773         ot->invoke= WM_operator_confirm;
774         ot->exec= object_delete_exec;
775         ot->poll= ED_operator_scene_editable;
776         
777         /* flags */
778         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
779 }
780
781 /**************************** Copy Utilities ******************************/
782
783 static void copy_object__forwardModifierLinks(void *userData, Object *ob,
784                                               ID **idpoin)
785 {
786         /* this is copied from ID_NEW; it might be better to have a macro */
787         if(*idpoin && (*idpoin)->newid) *idpoin = (*idpoin)->newid;
788 }
789
790 /* after copying objects, copied data should get new pointers */
791 static void copy_object_set_idnew(bContext *C, int dupflag)
792 {
793         Material *ma, *mao;
794         ID *id;
795 #if 0 // XXX old animation system
796         Ipo *ipo;
797         bActionStrip *strip;
798 #endif // XXX old animation system
799         int a;
800         
801         /* XXX check object pointers */
802         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
803                 relink_constraints(&ob->constraints);
804                 if (ob->pose){
805                         bPoseChannel *chan;
806                         for (chan = ob->pose->chanbase.first; chan; chan=chan->next){
807                                 relink_constraints(&chan->constraints);
808                         }
809                 }
810                 modifiers_foreachIDLink(ob, copy_object__forwardModifierLinks, NULL);
811                 ID_NEW(ob->parent);
812                 ID_NEW(ob->track);
813                 ID_NEW(ob->proxy);
814                 ID_NEW(ob->proxy_group);
815                 
816 #if 0 // XXX old animation system
817                 for(strip= ob->nlastrips.first; strip; strip= strip->next) {
818                         bActionModifier *amod;
819                         for(amod= strip->modifiers.first; amod; amod= amod->next)
820                                 ID_NEW(amod->ob);
821                 }
822 #endif // XXX old animation system
823         }
824         CTX_DATA_END;
825         
826         /* materials */
827         if( dupflag & USER_DUP_MAT) {
828                 mao= G.main->mat.first;
829                 while(mao) {
830                         if(mao->id.newid) {
831                                 
832                                 ma= (Material *)mao->id.newid;
833                                 
834                                 if(dupflag & USER_DUP_TEX) {
835                                         for(a=0; a<MAX_MTEX; a++) {
836                                                 if(ma->mtex[a]) {
837                                                         id= (ID *)ma->mtex[a]->tex;
838                                                         if(id) {
839                                                                 ID_NEW_US(ma->mtex[a]->tex)
840                                                                 else ma->mtex[a]->tex= copy_texture(ma->mtex[a]->tex);
841                                                                 id->us--;
842                                                         }
843                                                 }
844                                         }
845                                 }
846 #if 0 // XXX old animation system
847                                 id= (ID *)ma->ipo;
848                                 if(id) {
849                                         ID_NEW_US(ma->ipo)
850                                         else ma->ipo= copy_ipo(ma->ipo);
851                                         id->us--;
852                                 }
853 #endif // XXX old animation system
854                         }
855                         mao= mao->id.next;
856                 }
857         }
858         
859 #if 0 // XXX old animation system
860         /* lamps */
861         if( dupflag & USER_DUP_IPO) {
862                 Lamp *la= G.main->lamp.first;
863                 while(la) {
864                         if(la->id.newid) {
865                                 Lamp *lan= (Lamp *)la->id.newid;
866                                 id= (ID *)lan->ipo;
867                                 if(id) {
868                                         ID_NEW_US(lan->ipo)
869                                         else lan->ipo= copy_ipo(lan->ipo);
870                                         id->us--;
871                                 }
872                         }
873                         la= la->id.next;
874                 }
875         }
876         
877         /* ipos */
878         ipo= G.main->ipo.first;
879         while(ipo) {
880                 if(ipo->id.lib==NULL && ipo->id.newid) {
881                         Ipo *ipon= (Ipo *)ipo->id.newid;
882                         IpoCurve *icu;
883                         for(icu= ipon->curve.first; icu; icu= icu->next) {
884                                 if(icu->driver) {
885                                         ID_NEW(icu->driver->ob);
886                                 }
887                         }
888                 }
889                 ipo= ipo->id.next;
890         }
891 #endif // XXX old animation system
892         
893         set_sca_new_poins();
894         
895         clear_id_newpoins();
896 }
897
898 /********************* Make Duplicates Real ************************/
899
900 static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base)
901 {
902         Base *basen;
903         Object *ob;
904         ListBase *lb;
905         DupliObject *dob;
906         
907         if(!base && !(base = BASACT))
908                 return;
909         
910         if(!(base->object->transflag & OB_DUPLI))
911                 return;
912         
913         lb= object_duplilist(scene, base->object);
914         
915         for(dob= lb->first; dob; dob= dob->next) {
916                 ob= copy_object(dob->ob);
917                 /* font duplis can have a totcol without material, we get them from parent
918                 * should be implemented better...
919                 */
920                 if(ob->mat==NULL) ob->totcol= 0;
921                 
922                 basen= MEM_dupallocN(base);
923                 basen->flag &= ~OB_FROMDUPLI;
924                 BLI_addhead(&scene->base, basen);       /* addhead: othwise eternal loop */
925                 basen->object= ob;
926                 ob->ipo= NULL;          /* make sure apply works */
927                 ob->parent= ob->track= NULL;
928                 ob->disp.first= ob->disp.last= NULL;
929                 ob->transflag &= ~OB_DUPLI;     
930                 
931                 copy_m4_m4(ob->obmat, dob->mat);
932                 ED_object_apply_obmat(ob);
933         }
934         
935         copy_object_set_idnew(C, 0);
936         
937         free_object_duplilist(lb);
938         
939         base->object->transflag &= ~OB_DUPLI;   
940 }
941
942 static int object_duplicates_make_real_exec(bContext *C, wmOperator *op)
943 {
944         Scene *scene= CTX_data_scene(C);
945         
946         clear_id_newpoins();
947                 
948         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
949                 make_object_duplilist_real(C, scene, base);
950         }
951         CTX_DATA_END;
952
953         DAG_scene_sort(scene);
954         ED_anim_dag_flush_update(C);    
955         WM_event_add_notifier(C, NC_SCENE, scene);
956         
957         return OPERATOR_FINISHED;
958 }
959
960 void OBJECT_OT_duplicates_make_real(wmOperatorType *ot)
961 {
962         
963         /* identifiers */
964         ot->name= "Make Duplicates Real";
965         ot->description = "Make dupli objects attached to this object real.";
966         ot->idname= "OBJECT_OT_duplicates_make_real";
967         
968         /* api callbacks */
969         ot->invoke= WM_operator_confirm;
970         ot->exec= object_duplicates_make_real_exec;
971         
972         ot->poll= ED_operator_scene_editable;
973         
974         /* flags */
975         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
976 }
977
978 /**************************** Convert **************************/
979
980 static EnumPropertyItem convert_target_items[]= {
981         {OB_CURVE, "CURVE", ICON_OUTLINER_OB_CURVE, "Curve from Mesh/Text", ""},
982         {OB_MESH, "MESH", ICON_OUTLINER_OB_MESH, "Mesh from Curve/Meta/Surf/Mesh", ""},
983         {0, NULL, 0, NULL, NULL}};
984
985 static void curvetomesh(Scene *scene, Object *ob) 
986 {
987         Curve *cu= ob->data;
988         
989         if(cu->disp.first==0)
990                 makeDispListCurveTypes(scene, ob, 0); /* force creation */
991
992         nurbs_to_mesh(ob); /* also does users */
993
994         if(ob->type == OB_MESH)
995                 object_free_modifiers(ob);
996 }
997
998 static int convert_poll(bContext *C)
999 {
1000         Object *obact= CTX_data_active_object(C);
1001         Scene *scene= CTX_data_scene(C);
1002
1003         return (!scene->id.lib && obact && scene->obedit != obact && (obact->flag & SELECT));
1004 }
1005
1006 static int convert_exec(bContext *C, wmOperator *op)
1007 {
1008         Scene *scene= CTX_data_scene(C);
1009         Base *basen=NULL, *basact=NULL, *basedel=NULL;
1010         Object *ob, *ob1, *obact= CTX_data_active_object(C);
1011         DerivedMesh *dm;
1012         Curve *cu;
1013         Nurb *nu;
1014         MetaBall *mb;
1015         Mesh *me;
1016         int target= RNA_enum_get(op->ptr, "target");
1017         int keep_original= RNA_boolean_get(op->ptr, "keep_original");
1018         int a;
1019         
1020         /* don't forget multiple users! */
1021
1022         /* reset flags */
1023         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
1024                 ob= base->object;
1025                 ob->flag &= ~OB_DONE;
1026         }
1027         CTX_DATA_END;
1028
1029         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
1030                 ob= base->object;
1031                 
1032                 if(ob->flag & OB_DONE)
1033                         continue;
1034                 else if (ob->type==OB_MESH && target == OB_CURVE) {
1035                         ob->flag |= OB_DONE;
1036
1037                         ob1= copy_object(ob);
1038                         ob1->recalc |= OB_RECALC;
1039
1040                         basen= MEM_mallocN(sizeof(Base), "duplibase");
1041                         *basen= *base;
1042                         BLI_addhead(&scene->base, basen);       /* addhead: otherwise eternal loop */
1043                         basen->object= ob1;
1044                         basen->flag |= SELECT;
1045                         base->flag &= ~SELECT;
1046                         ob->flag &= ~SELECT;
1047
1048                         mesh_to_curve(scene, ob1);
1049
1050                         if(ob1->type==OB_CURVE)
1051                                 object_free_modifiers(ob1);     /* after derivedmesh calls! */
1052                 }
1053                 else if(ob->type==OB_MESH && ob->modifiers.first) { /* converting a mesh with no modifiers causes a segfault */
1054                         ob->flag |= OB_DONE;
1055                         basedel = base;
1056
1057                         ob1= copy_object(ob);
1058                         ob1->recalc |= OB_RECALC;
1059
1060                         basen= MEM_mallocN(sizeof(Base), "duplibase");
1061                         *basen= *base;
1062                         BLI_addhead(&scene->base, basen);       /* addhead: otherwise eternal loop */
1063                         basen->object= ob1;
1064                         basen->flag |= SELECT;
1065                         base->flag &= ~SELECT;
1066                         ob->flag &= ~SELECT;
1067
1068                         /* decrement original mesh's usage count  */
1069                         me= ob1->data;
1070                         me->id.us--;
1071
1072                         /* make a new copy of the mesh */
1073                         ob1->data= copy_mesh(me);
1074
1075                         /* make new mesh data from the original copy */
1076                         dm= mesh_get_derived_final(scene, ob1, CD_MASK_MESH);
1077                         /* dm= mesh_create_derived_no_deform(ob1, NULL);        this was called original (instead of get_derived). man o man why! (ton) */
1078
1079                         DM_to_mesh(dm, ob1->data);
1080
1081                         dm->release(dm);
1082                         object_free_modifiers(ob1);     /* after derivedmesh calls! */
1083                 }
1084                 else if(ob->type==OB_FONT) {
1085                         ob->flag |= OB_DONE;
1086
1087                         ob->type= OB_CURVE;
1088                         cu= ob->data;
1089
1090                         if(cu->vfont) {
1091                                 cu->vfont->id.us--;
1092                                 cu->vfont= 0;
1093                         }
1094                         if(cu->vfontb) {
1095                                 cu->vfontb->id.us--;
1096                                 cu->vfontb= 0;
1097                         }
1098                         if(cu->vfonti) {
1099                                 cu->vfonti->id.us--;
1100                                 cu->vfonti= 0;
1101                         }
1102                         if(cu->vfontbi) {
1103                                 cu->vfontbi->id.us--;
1104                                 cu->vfontbi= 0;
1105                         }                                       
1106                         /* other users */
1107                         if(cu->id.us>1) {
1108                                 for(ob1= G.main->object.first; ob1; ob1=ob1->id.next) {
1109                                         if(ob1->data==cu) {
1110                                                 ob1->type= OB_CURVE;
1111                                                 ob1->recalc |= OB_RECALC;
1112                                         }
1113                                 }
1114                         }
1115
1116                         for(nu=cu->nurb.first; nu; nu=nu->next)
1117                                 nu->charidx= 0;
1118
1119                         if(target == OB_MESH)
1120                                 curvetomesh(scene, ob);
1121                 }
1122                 else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
1123                         ob->flag |= OB_DONE;
1124
1125                         if(target == OB_MESH)
1126                                 curvetomesh(scene, ob);
1127                 }
1128                 else if(ob->type==OB_MBALL) {
1129                         ob= find_basis_mball(scene, ob);
1130                         
1131                         if(ob->disp.first && !(ob->flag & OB_DONE)) {
1132                                 ob->flag |= OB_DONE;
1133                                 basedel = base;
1134
1135                                 ob1= copy_object(ob);
1136                                 ob1->recalc |= OB_RECALC;
1137
1138                                 basen= MEM_mallocN(sizeof(Base), "duplibase");
1139                                 *basen= *base;
1140                                 BLI_addhead(&scene->base, basen);       /* addhead: otherwise eternal loop */
1141                                 basen->object= ob1;
1142                                 basen->flag |= SELECT;
1143                                 basedel->flag &= ~SELECT;
1144                                 ob->flag &= ~SELECT;
1145                                 
1146                                 mb= ob1->data;
1147                                 mb->id.us--;
1148                                 
1149                                 ob1->data= add_mesh("Mesh");
1150                                 ob1->type= OB_MESH;
1151                                 
1152                                 me= ob1->data;
1153                                 me->totcol= mb->totcol;
1154                                 if(ob1->totcol) {
1155                                         me->mat= MEM_dupallocN(mb->mat);
1156                                         for(a=0; a<ob1->totcol; a++) id_us_plus((ID *)me->mat[a]);
1157                                 }
1158                                 
1159                                 mball_to_mesh(&ob->disp, ob1->data);
1160                                 
1161                                 /* So we can see the wireframe */
1162                                 BASACT= basen; // XXX hm
1163                         }
1164                         else
1165                                 continue;
1166                 }
1167                 else
1168                         continue;
1169
1170                 /* If the original object is active then make this object active */
1171                 if(basen) {
1172                         if(ob == obact) {
1173                                 ED_base_object_activate(C, basen);
1174                                 basact = basen;
1175                         }
1176
1177                         basen= NULL;
1178                 }
1179
1180                 /* delete original if needed */
1181                 if(basedel) {
1182                         if(!keep_original)
1183                                 ED_base_object_free_and_unlink(scene, basedel); 
1184
1185                         basedel = NULL;
1186                 }
1187         }
1188         CTX_DATA_END;
1189         
1190         /* delete object should renew depsgraph */
1191         if(!keep_original)
1192                 DAG_scene_sort(scene);
1193
1194         /* texspace and normals */
1195         if(!basen) BASACT= NULL; // XXX base;
1196
1197 // XXX  ED_object_enter_editmode(C, 0);
1198 // XXX  exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR); /* freedata, but no undo */
1199         BASACT= basact;
1200
1201         DAG_scene_sort(scene);
1202         WM_event_add_notifier(C, NC_SCENE|NC_OBJECT|ND_DRAW, scene); /* is NC_SCENE needed ? */
1203
1204
1205
1206         return OPERATOR_FINISHED;
1207 }
1208
1209
1210 void OBJECT_OT_convert(wmOperatorType *ot)
1211 {
1212         /* identifiers */
1213         ot->name= "Convert";
1214         ot->description = "Convert selected objects to another type.";
1215         ot->idname= "OBJECT_OT_convert";
1216         
1217         /* api callbacks */
1218         ot->invoke= WM_menu_invoke;
1219         ot->exec= convert_exec;
1220         ot->poll= convert_poll;
1221         
1222         /* flags */
1223         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1224
1225         /* properties */
1226         RNA_def_enum(ot->srna, "target", convert_target_items, OB_MESH, "Target", "Type of object to convert to.");
1227         RNA_def_boolean(ot->srna, "keep_original", 0, "Keep Original", "Keep original objects instead of replacing them.");
1228 }
1229
1230 /**************************** Duplicate ************************/
1231
1232 /* 
1233         dupflag: a flag made from constants declared in DNA_userdef_types.h
1234         The flag tells adduplicate() weather to copy data linked to the object, or to reference the existing data.
1235         U.dupflag for default operations or you can construct a flag as python does
1236         if the dupflag is 0 then no data will be copied (linked duplicate) */
1237
1238 /* used below, assumes id.new is correct */
1239 /* leaves selection of base/object unaltered */
1240 static Base *object_add_duplicate_internal(Scene *scene, Base *base, int dupflag)
1241 {
1242         Base *basen= NULL;
1243         Material ***matarar;
1244         Object *ob, *obn;
1245         ID *id;
1246         int a, didit;
1247
1248         ob= base->object;
1249         if(ob->mode & OB_MODE_POSE) {
1250                 ; /* nothing? */
1251         }
1252         else {
1253                 obn= copy_object(ob);
1254                 obn->recalc |= OB_RECALC;
1255                 
1256                 basen= MEM_mallocN(sizeof(Base), "duplibase");
1257                 *basen= *base;
1258                 BLI_addhead(&scene->base, basen);       /* addhead: prevent eternal loop */
1259                 basen->object= obn;
1260                 
1261                 if(basen->flag & OB_FROMGROUP) {
1262                         Group *group;
1263                         for(group= G.main->group.first; group; group= group->id.next) {
1264                                 if(object_in_group(ob, group))
1265                                         add_to_group(group, obn);
1266                         }
1267                         obn->flag |= OB_FROMGROUP; /* this flag is unset with copy_object() */
1268                 }
1269                 
1270                 /* duplicates using userflags */
1271 #if 0 // XXX old animation system                               
1272                 if(dupflag & USER_DUP_IPO) {
1273                         bConstraintChannel *chan;
1274                         id= (ID *)obn->ipo;
1275                         
1276                         if(id) {
1277                                 ID_NEW_US( obn->ipo)
1278                                 else obn->ipo= copy_ipo(obn->ipo);
1279                                 id->us--;
1280                         }
1281                         /* Handle constraint ipos */
1282                         for (chan=obn->constraintChannels.first; chan; chan=chan->next){
1283                                 id= (ID *)chan->ipo;
1284                                 if(id) {
1285                                         ID_NEW_US( chan->ipo)
1286                                         else chan->ipo= copy_ipo(chan->ipo);
1287                                         id->us--;
1288                                 }
1289                         }
1290                 }
1291                 if(dupflag & USER_DUP_ACT){ /* Not buttons in the UI to modify this, add later? */
1292                         id= (ID *)obn->action;
1293                         if (id){
1294                                 ID_NEW_US(obn->action)
1295                                 else{
1296                                         obn->action= copy_action(obn->action);
1297                                 }
1298                                 id->us--;
1299                         }
1300                 }
1301 #endif // XXX old animation system
1302                 if(dupflag & USER_DUP_MAT) {
1303                         for(a=0; a<obn->totcol; a++) {
1304                                 id= (ID *)obn->mat[a];
1305                                 if(id) {
1306                                         ID_NEW_US(obn->mat[a])
1307                                         else obn->mat[a]= copy_material(obn->mat[a]);
1308                                         id->us--;
1309                                 }
1310                         }
1311                 }
1312                 if(dupflag & USER_DUP_PSYS) {
1313                         ParticleSystem *psys;
1314                         for(psys=obn->particlesystem.first; psys; psys=psys->next) {
1315                                 id= (ID*) psys->part;
1316                                 if(id) {
1317                                         ID_NEW_US(psys->part)
1318                                         else psys->part= psys_copy_settings(psys->part);
1319                                         id->us--;
1320                                 }
1321                         }
1322                 }
1323                 
1324                 id= obn->data;
1325                 didit= 0;
1326                 
1327                 switch(obn->type) {
1328                         case OB_MESH:
1329                                 if(dupflag & USER_DUP_MESH) {
1330                                         ID_NEW_US2( obn->data )
1331                                         else {
1332                                                 obn->data= copy_mesh(obn->data);
1333                                                 
1334                                                 if(obn->fluidsimSettings) {
1335                                                         obn->fluidsimSettings->orgMesh = (Mesh *)obn->data;
1336                                                 }
1337                                                 
1338                                                 didit= 1;
1339                                         }
1340                                         id->us--;
1341                                 }
1342                                 break;
1343                         case OB_CURVE:
1344                                 if(dupflag & USER_DUP_CURVE) {
1345                                         ID_NEW_US2(obn->data )
1346                                         else {
1347                                                 obn->data= copy_curve(obn->data);
1348                                                 didit= 1;
1349                                         }
1350                                         id->us--;
1351                                 }
1352                                 break;
1353                         case OB_SURF:
1354                                 if(dupflag & USER_DUP_SURF) {
1355                                         ID_NEW_US2( obn->data )
1356                                         else {
1357                                                 obn->data= copy_curve(obn->data);
1358                                                 didit= 1;
1359                                         }
1360                                         id->us--;
1361                                 }
1362                                 break;
1363                         case OB_FONT:
1364                                 if(dupflag & USER_DUP_FONT) {
1365                                         ID_NEW_US2( obn->data )
1366                                         else {
1367                                                 obn->data= copy_curve(obn->data);
1368                                                 didit= 1;
1369                                         }
1370                                         id->us--;
1371                                 }
1372                                 break;
1373                         case OB_MBALL:
1374                                 if(dupflag & USER_DUP_MBALL) {
1375                                         ID_NEW_US2(obn->data )
1376                                         else {
1377                                                 obn->data= copy_mball(obn->data);
1378                                                 didit= 1;
1379                                         }
1380                                         id->us--;
1381                                 }
1382                                 break;
1383                         case OB_LAMP:
1384                                 if(dupflag & USER_DUP_LAMP) {
1385                                         ID_NEW_US2(obn->data )
1386                                         else obn->data= copy_lamp(obn->data);
1387                                         id->us--;
1388                                 }
1389                                 break;
1390                                 
1391                         case OB_ARMATURE:
1392                                 obn->recalc |= OB_RECALC_DATA;
1393                                 if(obn->pose) obn->pose->flag |= POSE_RECALC;
1394                                         
1395                                         if(dupflag & USER_DUP_ARM) {
1396                                                 ID_NEW_US2(obn->data )
1397                                                 else {
1398                                                         obn->data= copy_armature(obn->data);
1399                                                         armature_rebuild_pose(obn, obn->data);
1400                                                         didit= 1;
1401                                                 }
1402                                                 id->us--;
1403                                         }
1404                                                 
1405                                                 break;
1406                                 
1407                         case OB_LATTICE:
1408                                 if(dupflag!=0) {
1409                                         ID_NEW_US2(obn->data )
1410                                         else obn->data= copy_lattice(obn->data);
1411                                         id->us--;
1412                                 }
1413                                 break;
1414                         case OB_CAMERA:
1415                                 if(dupflag!=0) {
1416                                         ID_NEW_US2(obn->data )
1417                                         else obn->data= copy_camera(obn->data);
1418                                         id->us--;
1419                                 }
1420                                 break;
1421                 }
1422                 
1423                 if(dupflag & USER_DUP_MAT) {
1424                         matarar= give_matarar(obn);
1425                         if(didit && matarar) {
1426                                 for(a=0; a<obn->totcol; a++) {
1427                                         id= (ID *)(*matarar)[a];
1428                                         if(id) {
1429                                                 ID_NEW_US( (*matarar)[a] )
1430                                                 else (*matarar)[a]= copy_material((*matarar)[a]);
1431                                                 
1432                                                 id->us--;
1433                                         }
1434                                 }
1435                         }
1436                 }
1437         }
1438         return basen;
1439 }
1440
1441 /* single object duplicate, if dupflag==0, fully linked, else it uses the flags given */
1442 /* leaves selection of base/object unaltered */
1443 Base *ED_object_add_duplicate(Scene *scene, Base *base, int dupflag)
1444 {
1445         Base *basen;
1446
1447         clear_id_newpoins();
1448         clear_sca_new_poins();  /* sensor/contr/act */
1449         
1450         basen= object_add_duplicate_internal(scene, base, dupflag);
1451         
1452         DAG_scene_sort(scene);
1453         
1454         return basen;
1455 }
1456
1457 /* contextual operator dupli */
1458 static int duplicate_exec(bContext *C, wmOperator *op)
1459 {
1460         Scene *scene= CTX_data_scene(C);
1461         int linked= RNA_boolean_get(op->ptr, "linked");
1462         int dupflag= (linked)? 0: U.dupflag;
1463         
1464         clear_id_newpoins();
1465         clear_sca_new_poins();  /* sensor/contr/act */
1466         
1467         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
1468                 Base *basen= object_add_duplicate_internal(scene, base, dupflag);
1469                 
1470                 /* note that this is safe to do with this context iterator,
1471                    the list is made in advance */
1472                 ED_base_object_select(base, BA_DESELECT);
1473
1474                 /* new object becomes active */
1475                 if(BASACT==base)
1476                         ED_base_object_activate(C, basen);
1477                 
1478         }
1479         CTX_DATA_END;
1480
1481         copy_object_set_idnew(C, dupflag);
1482
1483         DAG_scene_sort(scene);
1484         ED_anim_dag_flush_update(C);    
1485
1486         WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
1487
1488         return OPERATOR_FINISHED;
1489 }
1490
1491 void OBJECT_OT_duplicate(wmOperatorType *ot)
1492 {
1493         /* identifiers */
1494         ot->name= "Duplicate";
1495         ot->description = "Duplicate selected objects.";
1496         ot->idname= "OBJECT_OT_duplicate";
1497         
1498         /* api callbacks */
1499         ot->exec= duplicate_exec;
1500         ot->poll= ED_operator_scene_editable;
1501         
1502         /* flags */
1503         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1504         
1505         /* to give to transform */
1506         RNA_def_boolean(ot->srna, "linked", 0, "Linked", "Duplicate object but not object data, linking to the original data.");
1507         RNA_def_int(ot->srna, "mode", TFM_TRANSLATION, 0, INT_MAX, "Mode", "", 0, INT_MAX);
1508 }
1509
1510 /**************************** Join *************************/
1511
1512 static int join_exec(bContext *C, wmOperator *op)
1513 {
1514         Scene *scene= CTX_data_scene(C);
1515         Object *ob= CTX_data_active_object(C);
1516
1517         if(scene->obedit) {
1518                 BKE_report(op->reports, RPT_ERROR, "This data does not support joining in editmode.");
1519                 return OPERATOR_CANCELLED;
1520         }
1521         else if(!ob) {
1522                 BKE_report(op->reports, RPT_ERROR, "Can't join unless there is an active object.");
1523                 return OPERATOR_CANCELLED;
1524         }
1525         else if(object_data_is_libdata(ob)) {
1526                 BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata.");
1527                 return OPERATOR_CANCELLED;
1528         }
1529
1530         if(ob->type == OB_MESH)
1531                 return join_mesh_exec(C, op);
1532         else if(ELEM(ob->type, OB_CURVE, OB_SURF))
1533                 return join_curve_exec(C, op);
1534         else if(ob->type == OB_ARMATURE)
1535                 return join_armature_exec(C, op);
1536
1537         BKE_report(op->reports, RPT_ERROR, "This object type doesn't support joining.");
1538
1539         return OPERATOR_CANCELLED;
1540 }
1541
1542 void OBJECT_OT_join(wmOperatorType *ot)
1543 {
1544         /* identifiers */
1545         ot->name= "Join";
1546         ot->description = "Join selected objects into active object.";
1547         ot->idname= "OBJECT_OT_join";
1548         
1549         /* api callbacks */
1550         ot->exec= join_exec;
1551         ot->poll= ED_operator_scene_editable;
1552         
1553         /* flags */
1554         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1555 }
1556