4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
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.
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.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * Contributor(s): Blender Foundation, 2002-2008 full recode
25 * ***** END GPL LICENSE BLOCK *****
32 #include "MEM_guardedalloc.h"
34 #include "IMB_imbuf_types.h"
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"
67 #include "BLI_blenlib.h"
68 #include "BLI_arithb.h"
69 #include "BLI_editVert.h"
70 #include "BLI_ghash.h"
73 #include "BKE_action.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"
89 #include "BKE_global.h"
90 #include "BKE_group.h"
91 #include "BKE_image.h"
93 #include "BKE_lattice.h"
94 #include "BKE_library.h"
96 #include "BKE_material.h"
97 #include "BKE_mball.h"
100 #include "BKE_object.h"
101 #include "BKE_particle.h"
102 #include "BKE_property.h"
103 #include "BKE_report.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"
112 #include "ED_anim_api.h"
113 #include "ED_armature.h"
114 #include "ED_curve.h"
115 #include "ED_particle.h"
117 #include "ED_object.h"
118 #include "ED_screen.h"
119 #include "ED_transform.h"
120 #include "ED_types.h"
122 #include "ED_view3d.h"
124 #include "UI_interface.h"
126 #include "RNA_access.h"
127 #include "RNA_define.h"
129 /* for menu/popup icons etc etc*/
130 #include "UI_interface.h"
131 #include "UI_resources.h"
134 #include "WM_types.h"
136 #include "object_intern.h" // own include
138 /* ************* XXX **************** */
139 static void error() {}
140 static void waitcursor() {}
141 static int pupmenu() {return 0;}
142 static int pupmenu_col() {return 0;}
143 static int okee() {return 0;}
147 static void error_libdata() {}
149 /* ********************************** */
151 /* --------------------------------- */
153 /* simple API for object selection, rather than just using the flag
154 * this takes into account the 'restrict selection in 3d view' flag.
155 * deselect works always, the restriction just prevents selection */
157 /* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! */
159 void ED_base_object_select(Base *base, short mode)
162 if (mode==BA_SELECT) {
163 if (!(base->object->restrictflag & OB_RESTRICT_SELECT))
164 if (mode==BA_SELECT) base->flag |= SELECT;
166 else if (mode==BA_DESELECT) {
167 base->flag &= ~SELECT;
169 base->object->flag= base->flag;
173 /* also to set active NULL */
174 void ED_base_object_activate(bContext *C, Base *base)
176 Scene *scene= CTX_data_scene(C);
179 /* activating a non-mesh, should end a couple of modes... */
180 if(base && base->object->type!=OB_MESH)
181 ED_view3d_exit_paint_modes(C);
183 /* sets scene->basact */
188 /* XXX old signals, remember to handle notifiers now! */
189 // select_actionchannel_by_name(base->object->action, "Object", 1);
191 /* disable temporal locks */
192 for(tbase=FIRSTBASE; tbase; tbase= tbase->next) {
193 if(base!=tbase && (tbase->object->shapeflag & OB_SHAPE_TEMPLOCK)) {
194 tbase->object->shapeflag &= ~OB_SHAPE_TEMPLOCK;
195 DAG_object_flush_update(scene, tbase->object, OB_RECALC_DATA);
198 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
201 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, NULL);
206 void ED_object_base_init_from_view(bContext *C, Base *base)
208 View3D *v3d= CTX_wm_view3d(C);
209 Scene *scene= CTX_data_scene(C);
210 Object *ob= base->object;
216 base->lay = scene->lay;
217 VECCOPY(ob->loc, scene->cursor);
220 if (v3d->localview) {
221 base->lay= ob->lay= v3d->layact | v3d->lay;
222 VECCOPY(ob->loc, v3d->cursor);
225 base->lay= ob->lay= v3d->layact;
226 VECCOPY(ob->loc, scene->cursor);
229 if (U.flag & USER_ADD_VIEWALIGNED) {
230 ARegion *ar= CTX_wm_region(C);
232 RegionView3D *rv3d= ar->regiondata;
234 rv3d->viewquat[0]= -rv3d->viewquat[0];
235 QuatToEul(rv3d->viewquat, ob->rot);
236 rv3d->viewquat[0]= -rv3d->viewquat[0];
240 where_is_object(scene, ob);
243 /* ******************* add object operator ****************** */
245 static EnumPropertyItem prop_object_types[] = {
246 {OB_MESH, "MESH", 0, "Mesh", ""},
247 {OB_CURVE, "CURVE", 0, "Curve", ""},
248 {OB_SURF, "SURFACE", 0, "Surface", ""},
249 {OB_MBALL, "META", 0, "Meta", ""},
250 {OB_FONT, "TEXT", 0, "Text", ""},
251 {0, "", 0, NULL, NULL},
252 {OB_ARMATURE, "ARMATURE", 0, "Armature", ""},
253 {OB_LATTICE, "LATTICE", 0, "Lattice", ""},
254 {OB_EMPTY, "EMPTY", 0, "Empty", ""},
255 {0, "", 0, NULL, NULL},
256 {OB_CAMERA, "CAMERA", 0, "Camera", ""},
257 {OB_LAMP, "LAMP", 0, "Lamp", ""},
258 {0, NULL, 0, NULL, NULL}
263 void add_object_draw(Scene *scene, View3D *v3d, int type) /* for toolbox or menus, only non-editmode stuff */
265 /* keep here to get things compile, remove later */
268 /* for object add primitive operators */
269 static Object *object_add_type(bContext *C, int type)
271 Scene *scene= CTX_data_scene(C);
274 /* XXX hrms, this is editor level operator, remove? */
275 ED_view3d_exit_paint_modes(C);
277 /* for as long scene has editmode... */
278 if (CTX_data_edit_object(C))
279 ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* freedata, and undo */
281 /* deselects all, sets scene->basact */
282 ob= add_object(scene, type);
283 /* editor level activate, notifiers */
284 ED_base_object_activate(C, BASACT);
286 /* more editor stuff */
287 ED_object_base_init_from_view(C, BASACT);
289 DAG_scene_sort(scene);
294 /* for object add operator */
295 static int object_add_exec(bContext *C, wmOperator *op)
297 object_add_type(C, RNA_int_get(op->ptr, "type"));
299 return OPERATOR_FINISHED;
302 void OBJECT_OT_object_add(wmOperatorType *ot)
305 ot->name= "Add Object";
306 ot->description = "Add an object to the scene.";
307 ot->idname= "OBJECT_OT_object_add";
310 ot->invoke= WM_menu_invoke;
311 ot->exec= object_add_exec;
313 ot->poll= ED_operator_scene_editable;
316 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
318 RNA_def_enum(ot->srna, "type", prop_object_types, 0, "Type", "");
321 /* ***************** add primitives *************** */
322 /* ****** work both in and outside editmode ****** */
324 static EnumPropertyItem prop_mesh_types[] = {
325 {0, "PLANE", ICON_MESH_PLANE, "Plane", ""},
326 {1, "CUBE", ICON_MESH_CUBE, "Cube", ""},
327 {2, "CIRCLE", ICON_MESH_CIRCLE, "Circle", ""},
328 {3, "UVSPHERE", ICON_MESH_UVSPHERE, "UVsphere", ""},
329 {4, "ICOSPHERE", ICON_MESH_ICOSPHERE, "Icosphere", ""},
330 {5, "CYLINDER", ICON_MESH_TUBE, "Cylinder", ""},
331 {6, "CONE", ICON_MESH_CONE, "Cone", ""},
332 {0, "", 0, NULL, NULL},
333 {7, "GRID", ICON_MESH_GRID, "Grid", ""},
334 {8, "MONKEY", ICON_MESH_MONKEY, "Monkey", ""},
335 {0, NULL, 0, NULL, NULL}
338 static int object_add_mesh_exec(bContext *C, wmOperator *op)
340 Object *obedit= CTX_data_edit_object(C);
343 if(obedit==NULL || obedit->type!=OB_MESH) {
344 object_add_type(C, OB_MESH);
345 ED_object_enter_editmode(C, EM_DO_UNDO);
348 else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
350 switch(RNA_enum_get(op->ptr, "type")) {
352 WM_operator_name_call(C, "MESH_OT_primitive_plane_add", WM_OP_INVOKE_REGION_WIN, NULL);
355 WM_operator_name_call(C, "MESH_OT_primitive_cube_add", WM_OP_INVOKE_REGION_WIN, NULL);
358 WM_operator_name_call(C, "MESH_OT_primitive_circle_add", WM_OP_INVOKE_REGION_WIN, NULL);
361 WM_operator_name_call(C, "MESH_OT_primitive_uv_sphere_add", WM_OP_INVOKE_REGION_WIN, NULL);
364 WM_operator_name_call(C, "MESH_OT_primitive_ico_sphere_add", WM_OP_INVOKE_REGION_WIN, NULL);
367 WM_operator_name_call(C, "MESH_OT_primitive_cylinder_add", WM_OP_INVOKE_REGION_WIN, NULL);
370 WM_operator_name_call(C, "MESH_OT_primitive_cone_add", WM_OP_INVOKE_REGION_WIN, NULL);
373 WM_operator_name_call(C, "MESH_OT_primitive_grid_add", WM_OP_INVOKE_REGION_WIN, NULL);
376 WM_operator_name_call(C, "MESH_OT_primitive_monkey_add", WM_OP_INVOKE_REGION_WIN, NULL);
380 if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
381 ED_object_exit_editmode(C, EM_FREEDATA);
384 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
386 return OPERATOR_FINISHED;
390 void OBJECT_OT_mesh_add(wmOperatorType *ot)
393 ot->name= "Add Mesh";
394 ot->description = "Add a mesh object to the scene.";
395 ot->idname= "OBJECT_OT_mesh_add";
398 ot->invoke= WM_menu_invoke;
399 ot->exec= object_add_mesh_exec;
401 ot->poll= ED_operator_scene_editable;
403 /* flags: no register or undo, this operator calls operators */
404 ot->flag= 0; //OPTYPE_REGISTER|OPTYPE_UNDO;
406 RNA_def_enum(ot->srna, "type", prop_mesh_types, 0, "Primitive", "");
409 static EnumPropertyItem prop_curve_types[] = {
410 {CU_BEZIER|CU_2D|CU_PRIM_CURVE, "BEZIER_CURVE", ICON_CURVE_BEZCURVE, "Bezier Curve", ""},
411 {CU_BEZIER|CU_2D|CU_PRIM_CIRCLE, "BEZIER_CIRCLE", ICON_CURVE_BEZCIRCLE, "Bezier Circle", ""},
412 {CU_NURBS|CU_2D|CU_PRIM_CURVE, "NURBS_CURVE", ICON_CURVE_NCURVE, "NURBS Curve", ""},
413 {CU_NURBS|CU_2D|CU_PRIM_CIRCLE, "NURBS_CIRCLE", ICON_CURVE_NCIRCLE, "NURBS Circle", ""},
414 {CU_NURBS|CU_2D|CU_PRIM_PATH, "PATH", ICON_CURVE_PATH, "Path", ""},
415 {0, NULL, 0, NULL, NULL}
418 static int object_add_curve_exec(bContext *C, wmOperator *op)
420 Object *obedit= CTX_data_edit_object(C);
425 if(obedit==NULL || obedit->type!=OB_CURVE) {
426 object_add_type(C, OB_CURVE);
427 ED_object_enter_editmode(C, 0);
430 else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
432 obedit= CTX_data_edit_object(C);
433 nu= add_nurbs_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
434 editnurb= curve_get_editcurve(obedit);
435 BLI_addtail(editnurb, nu);
438 if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
439 ED_object_exit_editmode(C, EM_FREEDATA);
442 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
444 return OPERATOR_FINISHED;
447 static int object_add_curve_invoke(bContext *C, wmOperator *op, wmEvent *event)
449 Object *obedit= CTX_data_edit_object(C);
453 pup= uiPupMenuBegin(C, op->type->name, 0);
454 layout= uiPupMenuLayout(pup);
455 if(!obedit || obedit->type == OB_CURVE)
456 uiItemsEnumO(layout, op->type->idname, "type");
458 uiItemsEnumO(layout, "OBJECT_OT_surface_add", "type");
459 uiPupMenuEnd(C, pup);
461 return OPERATOR_CANCELLED;
464 void OBJECT_OT_curve_add(wmOperatorType *ot)
467 ot->name= "Add Curve";
468 ot->description = "Add a curve object to the scene.";
469 ot->idname= "OBJECT_OT_curve_add";
472 ot->invoke= object_add_curve_invoke;
473 ot->exec= object_add_curve_exec;
475 ot->poll= ED_operator_scene_editable;
478 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
480 RNA_def_enum(ot->srna, "type", prop_curve_types, 0, "Primitive", "");
483 static EnumPropertyItem prop_surface_types[]= {
484 {CU_PRIM_CURVE|CU_NURBS, "NURBS_CURVE", ICON_SURFACE_NCURVE, "NURBS Curve", ""},
485 {CU_PRIM_CIRCLE|CU_NURBS, "NURBS_CIRCLE", ICON_SURFACE_NCIRCLE, "NURBS Circle", ""},
486 {CU_PRIM_PATCH|CU_NURBS, "NURBS_SURFACE", ICON_SURFACE_NSURFACE, "NURBS Surface", ""},
487 {CU_PRIM_TUBE|CU_NURBS, "NURBS_TUBE", ICON_SURFACE_NTUBE, "NURBS Tube", ""},
488 {CU_PRIM_SPHERE|CU_NURBS, "NURBS_SPHERE", ICON_SURFACE_NSPHERE, "NURBS Sphere", ""},
489 {CU_PRIM_DONUT|CU_NURBS, "NURBS_DONUT", ICON_SURFACE_NDONUT, "NURBS Donut", ""},
490 {0, NULL, 0, NULL, NULL}
493 static int object_add_surface_exec(bContext *C, wmOperator *op)
495 Object *obedit= CTX_data_edit_object(C);
500 if(obedit==NULL || obedit->type!=OB_SURF) {
501 object_add_type(C, OB_SURF);
502 ED_object_enter_editmode(C, 0);
505 else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
507 obedit= CTX_data_edit_object(C);
508 nu= add_nurbs_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
509 editnurb= curve_get_editcurve(obedit);
510 BLI_addtail(editnurb, nu);
513 if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
514 ED_object_exit_editmode(C, EM_FREEDATA);
517 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
519 return OPERATOR_FINISHED;
522 void OBJECT_OT_surface_add(wmOperatorType *ot)
525 ot->name= "Add Surface";
526 ot->description = "Add a surface object to the scene.";
527 ot->idname= "OBJECT_OT_surface_add";
530 ot->invoke= WM_menu_invoke;
531 ot->exec= object_add_surface_exec;
533 ot->poll= ED_operator_scene_editable;
536 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
538 RNA_def_enum(ot->srna, "type", prop_surface_types, 0, "Primitive", "");
541 static int object_add_text_exec(bContext *C, wmOperator *op)
543 Object *obedit= CTX_data_edit_object(C);
545 if(obedit && obedit->type==OB_FONT)
546 return OPERATOR_CANCELLED;
548 object_add_type(C, OB_FONT);
549 obedit= CTX_data_active_object(C);
551 if(U.flag & USER_ADD_EDITMODE)
552 ED_object_enter_editmode(C, 0);
554 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
556 return OPERATOR_FINISHED;
559 void OBJECT_OT_text_add(wmOperatorType *ot)
562 ot->name= "Add Text";
563 ot->description = "Add a text object to the scene";
564 ot->idname= "OBJECT_OT_text_add";
567 ot->exec= object_add_text_exec;
568 ot->poll= ED_operator_scene_editable;
571 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
574 static int object_armature_add_exec(bContext *C, wmOperator *op)
576 Object *obedit= CTX_data_edit_object(C);
577 View3D *v3d= CTX_wm_view3d(C);
578 RegionView3D *rv3d= NULL;
581 if ((obedit==NULL) || (obedit->type != OB_ARMATURE)) {
582 object_add_type(C, OB_ARMATURE);
583 ED_object_enter_editmode(C, 0);
586 else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
589 rv3d= CTX_wm_region(C)->regiondata;
591 /* v3d and rv3d are allowed to be NULL */
592 add_primitive_bone(CTX_data_scene(C), v3d, rv3d);
595 if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
596 ED_object_exit_editmode(C, EM_FREEDATA);
599 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
601 return OPERATOR_FINISHED;
604 void OBJECT_OT_armature_add(wmOperatorType *ot)
607 ot->name= "Add Armature";
608 ot->description = "Add an armature object to the scene.";
609 ot->idname= "OBJECT_OT_armature_add";
612 ot->exec= object_armature_add_exec;
613 ot->poll= ED_operator_scene_editable;
616 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
620 static int object_primitive_add_invoke(bContext *C, wmOperator *op, wmEvent *event)
622 uiPopupMenu *pup= uiPupMenuBegin(C, "Add Object", 0);
623 uiLayout *layout= uiPupMenuLayout(pup);
625 uiItemMenuEnumO(layout, "Mesh", ICON_OUTLINER_OB_MESH, "OBJECT_OT_mesh_add", "type");
626 uiItemMenuEnumO(layout, "Curve", ICON_OUTLINER_OB_CURVE, "OBJECT_OT_curve_add", "type");
627 uiItemMenuEnumO(layout, "Surface", ICON_OUTLINER_OB_SURFACE, "OBJECT_OT_surface_add", "type");
628 uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_META, "OBJECT_OT_object_add", "type", OB_MBALL);
629 uiItemO(layout, "Text", ICON_OUTLINER_OB_FONT, "OBJECT_OT_text_add");
631 uiItemO(layout, "Armature", ICON_OUTLINER_OB_ARMATURE, "OBJECT_OT_armature_add");
632 uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_LATTICE, "OBJECT_OT_object_add", "type", OB_LATTICE);
633 uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_EMPTY, "OBJECT_OT_object_add", "type", OB_EMPTY);
635 uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_CAMERA, "OBJECT_OT_object_add", "type", OB_CAMERA);
636 uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_LAMP, "OBJECT_OT_object_add", "type", OB_LAMP);
638 uiPupMenuEnd(C, pup);
640 /* this operator is only for a menu, not used further */
641 return OPERATOR_CANCELLED;
644 /* only used as menu */
645 void OBJECT_OT_primitive_add(wmOperatorType *ot)
648 ot->name= "Add Primitive";
649 ot->description = "Add a primitive object.";
650 ot->idname= "OBJECT_OT_primitive_add";
653 ot->invoke= object_primitive_add_invoke;
655 ot->poll= ED_operator_scene_editable;
662 /* ******************************* */
664 /* remove base from a specific scene */
665 /* note: now unlinks constraints as well */
666 void ED_base_object_free_and_unlink(Scene *scene, Base *base)
668 BLI_remlink(&scene->base, base);
669 free_libblock_us(&G.main->object, base->object);
670 if(scene->basact==base) scene->basact= NULL;
674 static int object_delete_exec(bContext *C, wmOperator *op)
676 Scene *scene= CTX_data_scene(C);
679 if(CTX_data_edit_object(C))
680 return OPERATOR_CANCELLED;
682 ED_view3d_exit_paint_modes(C);
684 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
686 if(base->object->type==OB_LAMP) islamp= 1;
688 /* remove from current scene only */
689 ED_base_object_free_and_unlink(scene, base);
693 if(islamp) reshadeall_displist(scene); /* only frees displist */
695 DAG_scene_sort(scene);
696 ED_anim_dag_flush_update(C);
698 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, CTX_data_scene(C));
700 return OPERATOR_FINISHED;
703 void OBJECT_OT_delete(wmOperatorType *ot)
708 ot->description = "Delete selected objects.";
709 ot->idname= "OBJECT_OT_delete";
712 ot->invoke= WM_operator_confirm;
713 ot->exec= object_delete_exec;
714 ot->poll= ED_operator_scene_editable;
717 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
722 static void single_object_users__forwardModifierLinks(void *userData, Object *ob, Object **obpoin)
727 static void copy_object__forwardModifierLinks(void *userData, Object *ob,
730 /* this is copied from ID_NEW; it might be better to have a macro */
731 if(*idpoin && (*idpoin)->newid) *idpoin = (*idpoin)->newid;
735 /* after copying objects, copied data should get new pointers */
736 static void copy_object_set_idnew(Scene *scene, View3D *v3d, int dupflag)
742 #if 0 // XXX old animation system
745 #endif // XXX old animation system
748 /* XXX check object pointers */
749 for(base= FIRSTBASE; base; base= base->next) {
750 if(TESTBASELIB_BGMODE(v3d, base)) {
752 relink_constraints(&ob->constraints);
755 for (chan = ob->pose->chanbase.first; chan; chan=chan->next){
756 relink_constraints(&chan->constraints);
759 modifiers_foreachIDLink(ob, copy_object__forwardModifierLinks, NULL);
763 ID_NEW(ob->proxy_group);
765 #if 0 // XXX old animation system
766 for(strip= ob->nlastrips.first; strip; strip= strip->next) {
767 bActionModifier *amod;
768 for(amod= strip->modifiers.first; amod; amod= amod->next)
771 #endif // XXX old animation system
776 if( dupflag & USER_DUP_MAT) {
777 mao= G.main->mat.first;
781 ma= (Material *)mao->id.newid;
783 if(dupflag & USER_DUP_TEX) {
784 for(a=0; a<MAX_MTEX; a++) {
786 id= (ID *)ma->mtex[a]->tex;
788 ID_NEW_US(ma->mtex[a]->tex)
789 else ma->mtex[a]->tex= copy_texture(ma->mtex[a]->tex);
795 #if 0 // XXX old animation system
799 else ma->ipo= copy_ipo(ma->ipo);
802 #endif // XXX old animation system
808 #if 0 // XXX old animation system
810 if( dupflag & USER_DUP_IPO) {
811 Lamp *la= G.main->lamp.first;
814 Lamp *lan= (Lamp *)la->id.newid;
818 else lan->ipo= copy_ipo(lan->ipo);
827 ipo= G.main->ipo.first;
829 if(ipo->id.lib==NULL && ipo->id.newid) {
830 Ipo *ipon= (Ipo *)ipo->id.newid;
832 for(icu= ipon->curve.first; icu; icu= icu->next) {
834 ID_NEW(icu->driver->ob);
840 #endif // XXX old animation system
848 static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float *cent)
851 int *index, nr, totvert=0;
853 for(eve= em->verts.first; eve; eve= eve->next) {
854 if(eve->f & SELECT) totvert++;
856 if(totvert==0) return 0;
858 *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
861 cent[0]= cent[1]= cent[2]= 0.0;
863 for(eve= em->verts.first; eve; eve= eve->next) {
864 if(eve->f & SELECT) {
866 VecAddf(cent, cent, eve->co);
871 VecMulf(cent, 1.0f/(float)totvert);
876 static int return_editmesh_vgroup(Object *obedit, EditMesh *em, char *name, float *cent)
882 cent[0]= cent[1]= cent[2]= 0.0;
886 /* find the vertices */
887 for(eve= em->verts.first; eve; eve= eve->next) {
888 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
891 for(i=0; i<dvert->totweight; i++){
892 if(dvert->dw[i].def_nr == (obedit->actdef-1)) {
894 VecAddf(cent, cent, eve->co);
900 bDeformGroup *defGroup = BLI_findlink(&obedit->defbase, obedit->actdef-1);
901 strcpy(name, defGroup->name);
902 VecMulf(cent, 1.0f/(float)totvert);
910 static void select_editmesh_hook(Object *ob, HookModifierData *hmd)
913 EditMesh *em= BKE_mesh_get_editmesh(me);
917 for(eve= em->verts.first; eve; eve= eve->next, nr++) {
918 if(nr==hmd->indexar[index]) {
920 if(index < hmd->totindex-1) index++;
925 BKE_mesh_end_editmesh(me, em);
928 static int return_editlattice_indexar(Lattice *editlatt, int *tot, int **indexar, float *cent)
931 int *index, nr, totvert=0, a;
934 a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
937 if(bp->f1 & SELECT) {
938 if(bp->hide==0) totvert++;
943 if(totvert==0) return 0;
945 *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
948 cent[0]= cent[1]= cent[2]= 0.0;
950 a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
953 if(bp->f1 & SELECT) {
956 VecAddf(cent, cent, bp->vec);
963 VecMulf(cent, 1.0f/(float)totvert);
968 static void select_editlattice_hook(Object *obedit, HookModifierData *hmd)
970 Lattice *lt= obedit->data;
972 int index=0, nr=0, a;
975 a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
976 bp= lt->editlatt->def;
978 if(hmd->indexar[index]==nr) {
980 if(index < hmd->totindex-1) index++;
987 static int return_editcurve_indexar(Object *obedit, int *tot, int **indexar, float *cent)
989 ListBase *editnurb= curve_get_editcurve(obedit);
993 int *index, a, nr, totvert=0;
995 for(nu= editnurb->first; nu; nu= nu->next) {
996 if((nu->type & 7)==CU_BEZIER) {
1000 if(bezt->f1 & SELECT) totvert++;
1001 if(bezt->f2 & SELECT) totvert++;
1002 if(bezt->f3 & SELECT) totvert++;
1008 a= nu->pntsu*nu->pntsv;
1010 if(bp->f1 & SELECT) totvert++;
1015 if(totvert==0) return 0;
1017 *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
1020 cent[0]= cent[1]= cent[2]= 0.0;
1022 for(nu= editnurb->first; nu; nu= nu->next) {
1023 if((nu->type & 7)==CU_BEZIER) {
1027 if(bezt->f1 & SELECT) {
1028 *index= nr; index++;
1029 VecAddf(cent, cent, bezt->vec[0]);
1032 if(bezt->f2 & SELECT) {
1033 *index= nr; index++;
1034 VecAddf(cent, cent, bezt->vec[1]);
1037 if(bezt->f3 & SELECT) {
1038 *index= nr; index++;
1039 VecAddf(cent, cent, bezt->vec[2]);
1047 a= nu->pntsu*nu->pntsv;
1049 if(bp->f1 & SELECT) {
1050 *index= nr; index++;
1051 VecAddf(cent, cent, bp->vec);
1059 VecMulf(cent, 1.0f/(float)totvert);
1064 void ED_object_apply_obmat(Object *ob)
1066 float mat[3][3], imat[3][3], tmat[3][3];
1068 /* from obmat to loc rot size */
1070 if(ob==NULL) return;
1071 Mat3CpyMat4(mat, ob->obmat);
1073 VECCOPY(ob->loc, ob->obmat[3]);
1075 Mat3ToEul(mat, ob->rot);
1076 EulToMat3(ob->rot, tmat);
1078 Mat3Inv(imat, tmat);
1080 Mat3MulMat3(tmat, imat, mat);
1082 ob->size[0]= tmat[0][0];
1083 ob->size[1]= tmat[1][1];
1084 ob->size[2]= tmat[2][2];
1088 int hook_getIndexArray(Object *obedit, int *tot, int **indexar, char *name, float *cent_r)
1094 switch(obedit->type) {
1097 Mesh *me= obedit->data;
1098 EditMesh *em = BKE_mesh_get_editmesh(me);
1100 /* check selected vertices first */
1101 if( return_editmesh_indexar(em, tot, indexar, cent_r)) {
1102 BKE_mesh_end_editmesh(me, em);
1105 int ret = return_editmesh_vgroup(obedit, em, name, cent_r);
1106 BKE_mesh_end_editmesh(me, em);
1112 return return_editcurve_indexar(obedit, tot, indexar, cent_r);
1115 Lattice *lt= obedit->data;
1116 return return_editlattice_indexar(lt->editlatt, tot, indexar, cent_r);
1123 static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
1125 ListBase *editnurb= curve_get_editcurve(obedit);
1129 int index=0, a, nr=0;
1131 for(nu= editnurb->first; nu; nu= nu->next) {
1132 if((nu->type & 7)==CU_BEZIER) {
1136 if(nr == hmd->indexar[index]) {
1138 if(index<hmd->totindex-1) index++;
1141 if(nr == hmd->indexar[index]) {
1143 if(index<hmd->totindex-1) index++;
1146 if(nr == hmd->indexar[index]) {
1148 if(index<hmd->totindex-1) index++;
1157 a= nu->pntsu*nu->pntsv;
1159 if(nr == hmd->indexar[index]) {
1161 if(index<hmd->totindex-1) index++;
1170 void obedit_hook_select(Object *ob, HookModifierData *hmd)
1173 if(ob->type==OB_MESH) select_editmesh_hook(ob, hmd);
1174 else if(ob->type==OB_LATTICE) select_editlattice_hook(ob, hmd);
1175 else if(ob->type==OB_CURVE) select_editcurve_hook(ob, hmd);
1176 else if(ob->type==OB_SURF) select_editcurve_hook(ob, hmd);
1180 void add_hook(Scene *scene, View3D *v3d, int mode)
1182 ModifierData *md = NULL;
1183 HookModifierData *hmd = NULL;
1185 Object *obedit= scene->obedit; // XXX get from context
1187 if(obedit==NULL) return;
1190 if(mode==2) { /* selected object */
1192 for(base= FIRSTBASE; base; base= base->next) {
1193 if(TESTBASELIB(v3d, base)) {
1201 error("Requires selected Object");
1206 int maxlen=0, a, nr;
1209 /* make pupmenu with hooks */
1210 for(md=obedit->modifiers.first; md; md= md->next) {
1211 if (md->type==eModifierType_Hook)
1216 error("Object has no hooks yet");
1220 cp= MEM_callocN(maxlen+32, "temp string");
1221 if(mode==3) strcpy(cp, "Remove %t|");
1222 else if(mode==4) strcpy(cp, "Reassign %t|");
1223 else if(mode==5) strcpy(cp, "Select %t|");
1224 else if(mode==6) strcpy(cp, "Clear Offset %t|");
1226 for(md=obedit->modifiers.first; md; md= md->next) {
1227 if (md->type==eModifierType_Hook) {
1228 strcat(cp, md->name);
1239 for(md=obedit->modifiers.first; md; md=md->next) {
1240 if (md->type==eModifierType_Hook) {
1246 hmd = (HookModifierData*) md;
1250 /* do it, new hooks or reassign */
1251 if(mode==1 || mode==2 || mode==4) {
1253 int tot, ok, *indexar;
1256 ok = hook_getIndexArray(obedit, &tot, &indexar, name, cent);
1259 error("Requires selected vertices or active Vertex Group");
1264 Base *base= BASACT, *newbase;
1266 ob= add_object(scene, OB_EMPTY);
1269 newbase->lay= base->lay;
1270 ob->lay= newbase->lay;
1272 /* transform cent to global coords for loc */
1273 VecMat4MulVecfl(ob->loc, obedit->obmat, cent);
1275 /* restore, add_object sets active */
1278 /* if mode is 2 or 4, ob has been set */
1281 if(mode==1 || mode==2) {
1282 ModifierData *md = obedit->modifiers.first;
1284 while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
1288 hmd = (HookModifierData*) modifier_new(eModifierType_Hook);
1289 BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
1290 sprintf(hmd->modifier.name, "Hook-%s", ob->id.name+2);
1292 else if (hmd->indexar) MEM_freeN(hmd->indexar); /* reassign, hook was set */
1295 hmd->indexar= indexar;
1296 VECCOPY(hmd->cent, cent);
1298 BLI_strncpy(hmd->name, name, 32);
1300 if(mode==1 || mode==2) {
1301 /* matrix calculus */
1302 /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
1305 where_is_object(scene, ob);
1307 Mat4Invert(ob->imat, ob->obmat);
1308 /* apparently this call goes from right to left... */
1309 Mat4MulSerie(hmd->parentinv, ob->imat, obedit->obmat, NULL,
1310 NULL, NULL, NULL, NULL, NULL);
1314 else if(mode==3) { /* remove */
1315 BLI_remlink(&obedit->modifiers, md);
1318 else if(mode==5) { /* select */
1319 obedit_hook_select(obedit, hmd);
1321 else if(mode==6) { /* clear offset */
1322 where_is_object(scene, ob); /* ob is hook->parent */
1324 Mat4Invert(ob->imat, ob->obmat);
1325 /* this call goes from right to left... */
1326 Mat4MulSerie(hmd->parentinv, ob->imat, obedit->obmat, NULL,
1327 NULL, NULL, NULL, NULL, NULL);
1330 DAG_scene_sort(scene);
1334 /* use this when the loc/size/rot of the parent has changed but the children should stay in the same place
1335 * apply-size-rot or object center for eg */
1336 static void ignore_parent_tx(Scene *scene, Object *ob )
1341 /* a change was made, adjust the children to compensate */
1342 for (ob_child=G.main->object.first; ob_child; ob_child=ob_child->id.next) {
1343 if (ob_child->parent == ob) {
1344 ED_object_apply_obmat(ob_child);
1345 what_does_parent(scene, ob_child, &workob);
1346 Mat4Invert(ob_child->parentinv, workob.obmat);
1352 void add_hook_menu(Scene *scene, View3D *v3d)
1354 Object *obedit= scene->obedit; // XXX get from context
1357 if(obedit==NULL) return;
1359 if(modifiers_findByType(obedit, eModifierType_Hook))
1360 mode= pupmenu("Hooks %t|Add, To New Empty %x1|Add, To Selected Object %x2|Remove... %x3|Reassign... %x4|Select... %x5|Clear Offset...%x6");
1362 mode= pupmenu("Hooks %t|Add, New Empty %x1|Add, To Selected Object %x2");
1367 add_hook(scene, v3d, mode);
1370 /* ******************** clear parent operator ******************* */
1372 static EnumPropertyItem prop_clear_parent_types[] = {
1373 {0, "CLEAR", 0, "Clear Parent", ""},
1374 {1, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation (Clear Track)", ""},
1375 {2, "CLEAR_INVERSE", 0, "Clear Parent Inverse", ""},
1376 {0, NULL, 0, NULL, NULL}
1379 /* note, poll should check for editable scene */
1380 static int parent_clear_exec(bContext *C, wmOperator *op)
1382 int type= RNA_enum_get(op->ptr, "type");
1384 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1389 else if(type == 1) {
1392 ED_object_apply_obmat(ob);
1395 Mat4One(ob->parentinv);
1397 ob->recalc |= OB_RECALC;
1401 DAG_scene_sort(CTX_data_scene(C));
1402 ED_anim_dag_flush_update(C);
1403 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
1405 return OPERATOR_FINISHED;
1408 void OBJECT_OT_parent_clear(wmOperatorType *ot)
1411 ot->name= "Clear Parent";
1412 ot->description = "Clear the object's parenting.";
1413 ot->idname= "OBJECT_OT_parent_clear";
1416 ot->invoke= WM_menu_invoke;
1417 ot->exec= parent_clear_exec;
1419 ot->poll= ED_operator_object_active;
1422 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1424 RNA_def_enum(ot->srna, "type", prop_clear_parent_types, 0, "Type", "");
1427 /* ******************** clear track operator ******************* */
1430 static EnumPropertyItem prop_clear_track_types[] = {
1431 {0, "CLEAR", 0, "Clear Track", ""},
1432 {1, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation (Clear Track)", ""},
1433 {0, NULL, 0, NULL, NULL}
1436 /* note, poll should check for editable scene */
1437 static int object_track_clear_exec(bContext *C, wmOperator *op)
1439 int type= RNA_enum_get(op->ptr, "type");
1441 if(CTX_data_edit_object(C)) {
1442 BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in EditMode");
1443 return OPERATOR_CANCELLED;
1445 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1447 ob->recalc |= OB_RECALC;
1450 ED_object_apply_obmat(ob);
1454 DAG_scene_sort(CTX_data_scene(C));
1455 ED_anim_dag_flush_update(C);
1457 return OPERATOR_FINISHED;
1460 void OBJECT_OT_track_clear(wmOperatorType *ot)
1463 ot->name= "Clear track";
1464 ot->description = "Clear tracking constraint or flag from object.";
1465 ot->idname= "OBJECT_OT_track_clear";
1468 ot->invoke= WM_menu_invoke;
1469 ot->exec= object_track_clear_exec;
1471 ot->poll= ED_operator_scene_editable;
1474 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1476 RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
1479 /* *****************Selection Operators******************* */
1480 static EnumPropertyItem prop_select_types[] = {
1481 {0, "EXCLUSIVE", 0, "Exclusive", ""},
1482 {1, "EXTEND", 0, "Extend", ""},
1483 {0, NULL, 0, NULL, NULL}
1486 /* ****** Select by Type ****** */
1488 static int object_select_by_type_exec(bContext *C, wmOperator *op)
1490 short obtype, seltype;
1492 obtype = RNA_enum_get(op->ptr, "type");
1493 seltype = RNA_enum_get(op->ptr, "seltype");
1496 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1497 ED_base_object_select(base, BA_DESELECT);
1502 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1503 if(base->object->type==obtype) {
1504 ED_base_object_select(base, BA_SELECT);
1509 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
1511 return OPERATOR_FINISHED;
1514 void OBJECT_OT_select_by_type(wmOperatorType *ot)
1517 ot->name= "Select By Type";
1518 ot->description = "Select all visible objects that are of a type.";
1519 ot->idname= "OBJECT_OT_select_by_type";
1522 ot->invoke= WM_menu_invoke;
1523 ot->exec= object_select_by_type_exec;
1524 ot->poll= ED_operator_scene_editable;
1527 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1529 RNA_def_enum(ot->srna, "seltype", prop_select_types, 0, "Selection", "Extend selection or clear selection then select");
1530 RNA_def_enum(ot->srna, "type", prop_object_types, 1, "Type", "");
1533 /* ****** selection by links *******/
1535 static EnumPropertyItem prop_select_linked_types[] = {
1536 {1, "IPO", 0, "Object IPO", ""}, // XXX depreceated animation system stuff...
1537 {2, "OBDATA", 0, "Ob Data", ""},
1538 {3, "MATERIAL", 0, "Material", ""},
1539 {4, "TEXTURE", 0, "Texture", ""},
1540 {5, "DUPGROUP", 0, "Dupligroup", ""},
1541 {6, "PARTICLE", 0, "Particle System", ""},
1542 {0, NULL, 0, NULL, NULL}
1545 static int object_select_linked_exec(bContext *C, wmOperator *op)
1547 Scene *scene= CTX_data_scene(C);
1549 void *obdata = NULL;
1550 Material *mat = NULL, *mat1;
1553 int nr = RNA_enum_get(op->ptr, "type");
1554 short changed = 0, seltype;
1558 * Current Material: 3
1559 * Current Texture: 4
1564 seltype = RNA_enum_get(op->ptr, "seltype");
1567 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1568 ED_base_object_select(base, BA_DESELECT);
1575 BKE_report(op->reports, RPT_ERROR, "No Active Object");
1576 return OPERATOR_CANCELLED;
1580 // XXX old animation system
1582 //if(ipo==0) return OPERATOR_CANCELLED;
1583 return OPERATOR_CANCELLED;
1586 if(ob->data==0) return OPERATOR_CANCELLED;
1589 else if(nr==3 || nr==4) {
1590 mat= give_current_material(ob, ob->actcol);
1591 if(mat==0) return OPERATOR_CANCELLED;
1593 if(mat->mtex[ (int)mat->texact ]) tex= mat->mtex[ (int)mat->texact ]->tex;
1594 if(tex==0) return OPERATOR_CANCELLED;
1598 if(ob->dup_group==NULL) return OPERATOR_CANCELLED;
1601 if(ob->particlesystem.first==NULL) return OPERATOR_CANCELLED;
1603 else return OPERATOR_CANCELLED;
1605 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1607 // XXX old animation system
1608 //if(base->object->ipo==ipo) base->flag |= SELECT;
1612 if(base->object->data==obdata) base->flag |= SELECT;
1615 else if(nr==3 || nr==4) {
1618 for(a=1; a<=ob->totcol; a++) {
1619 mat1= give_current_material(ob, a);
1621 if(mat1==mat) base->flag |= SELECT;
1624 else if(mat1 && nr==4) {
1625 for(b=0; b<MAX_MTEX; b++) {
1627 if(tex==mat1->mtex[b]->tex) {
1628 base->flag |= SELECT;
1638 if(base->object->dup_group==ob->dup_group) {
1639 base->flag |= SELECT;
1644 /* loop through other, then actives particles*/
1645 ParticleSystem *psys;
1646 ParticleSystem *psys_act;
1648 for(psys=base->object->particlesystem.first; psys; psys=psys->next) {
1649 for(psys_act=ob->particlesystem.first; psys_act; psys_act=psys_act->next) {
1650 if (psys->part == psys_act->part) {
1651 base->flag |= SELECT;
1657 if (base->flag & SELECT) {
1662 base->object->flag= base->flag;
1667 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
1668 return OPERATOR_FINISHED;
1671 return OPERATOR_CANCELLED;
1674 void OBJECT_OT_select_linked(wmOperatorType *ot)
1677 ot->name= "Select Linked";
1678 ot->description = "Select all visible objects that are linked.";
1679 ot->idname= "OBJECT_OT_select_linked";
1682 ot->invoke= WM_menu_invoke;
1683 ot->exec= object_select_linked_exec;
1684 ot->poll= ED_operator_scene_editable;
1687 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1689 RNA_def_enum(ot->srna, "type", prop_select_linked_types, 0, "Type", "");
1690 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
1694 /* ****** selection grouped *******/
1696 static EnumPropertyItem prop_select_grouped_types[] = {
1697 {1, "CHILDREN_RECURSIVE", 0, "Children", ""}, // XXX depreceated animation system stuff...
1698 {2, "CHILDREN", 0, "Immediate Children", ""},
1699 {3, "PARENT", 0, "Parent", ""},
1700 {4, "SIBLINGS", 0, "Siblings", "Shared Parent"},
1701 {5, "TYPE", 0, "Type", "Shared object type"},
1702 {6, "LAYER", 0, "Layer", "Shared layers"},
1703 {7, "GROUP", 0, "Group", "Shared group"},
1704 {8, "HOOK", 0, "Hook", ""},
1705 {9, "PASS", 0, "Pass", "Render pass Index"},
1706 {10, "COLOR", 0, "Color", "Object Color"},
1707 {11, "PROPERTIES", 0, "Properties", "Game Properties"},
1708 {0, NULL, 0, NULL, NULL}
1712 static short select_grouped_children(bContext *C, Object *ob, int recursive)
1716 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1717 if (ob == base->object->parent) {
1718 if (!(base->flag & SELECT)) {
1719 ED_base_object_select(base, BA_SELECT);
1724 changed |= select_grouped_children(C, base->object, 1);
1731 static short select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */
1733 Scene *scene= CTX_data_scene(C);
1734 View3D *v3d= CTX_wm_view3d(C);
1737 Base *baspar, *basact= CTX_data_active_base(C);
1739 if (!basact || !(basact->object->parent)) return 0; /* we know OBACT is valid */
1741 baspar= object_in_scene(basact->object->parent, scene);
1743 /* can be NULL if parent in other scene */
1744 if(baspar && BASE_SELECTABLE(v3d, baspar)) {
1745 ED_base_object_select(basact, BA_DESELECT);
1746 ED_base_object_select(baspar, BA_SELECT);
1747 ED_base_object_activate(C, baspar);
1754 #define GROUP_MENU_MAX 24
1755 static short select_grouped_group(bContext *C, Object *ob) /* Select objects in the same group as the active */
1758 Group *group, *ob_groups[GROUP_MENU_MAX];
1759 //char str[10 + (24*GROUP_MENU_MAX)];
1761 int group_count=0; //, menu, i;
1763 for ( group=G.main->group.first;
1764 group && group_count < GROUP_MENU_MAX;
1765 group=group->id.next
1767 if (object_in_group (ob, group)) {
1768 ob_groups[group_count] = group;
1776 else if (group_count == 1) {
1777 group = ob_groups[0];
1778 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1779 if (!(base->flag & SELECT) && object_in_group(base->object, group)) {
1780 ED_base_object_select(base, BA_SELECT);
1787 #if 0 // XXX hows this work in 2.5?
1788 /* build the menu. */
1789 p += sprintf(str, "Groups%%t");
1790 for (i=0; i<group_count; i++) {
1791 group = ob_groups[i];
1792 p += sprintf (p, "|%s%%x%i", group->id.name+2, i);
1795 menu = pupmenu (str);
1799 group = ob_groups[menu];
1800 for (base= FIRSTBASE; base; base= base->next) {
1801 if (!(base->flag & SELECT) && object_in_group(base->object, group)) {
1802 ED_base_object_select(base, BA_SELECT);
1810 static short select_grouped_object_hooks(bContext *C, Object *ob)
1812 Scene *scene= CTX_data_scene(C);
1813 View3D *v3d= CTX_wm_view3d(C);
1818 HookModifierData *hmd;
1820 for (md = ob->modifiers.first; md; md=md->next) {
1821 if (md->type==eModifierType_Hook) {
1822 hmd= (HookModifierData*) md;
1823 if (hmd->object && !(hmd->object->flag & SELECT)) {
1824 base= object_in_scene(hmd->object, scene);
1825 if (base && (BASE_SELECTABLE(v3d, base))) {
1826 ED_base_object_select(base, BA_SELECT);
1835 /* Select objects woth the same parent as the active (siblings),
1836 * parent can be NULL also */
1837 static short select_grouped_siblings(bContext *C, Object *ob)
1841 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1842 if ((base->object->parent==ob->parent) && !(base->flag & SELECT)) {
1843 ED_base_object_select(base, BA_SELECT);
1851 static short select_grouped_type(bContext *C, Object *ob)
1855 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1856 if ((base->object->type == ob->type) && !(base->flag & SELECT)) {
1857 ED_base_object_select(base, BA_SELECT);
1865 static short select_grouped_layer(bContext *C, Object *ob)
1869 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1870 if ((base->lay & ob->lay) && !(base->flag & SELECT)) {
1871 ED_base_object_select(base, BA_SELECT);
1879 static short select_grouped_index_object(bContext *C, Object *ob)
1883 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1884 if ((base->object->index == ob->index) && !(base->flag & SELECT)) {
1885 ED_base_object_select(base, BA_SELECT);
1893 static short select_grouped_color(bContext *C, Object *ob)
1897 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1898 if (!(base->flag & SELECT) && (FloatCompare(base->object->col, ob->col, 0.005f))) {
1899 ED_base_object_select(base, BA_SELECT);
1907 static short objects_share_gameprop(Object *a, Object *b)
1910 /*make a copy of all its properties*/
1912 for( prop= a->prop.first; prop; prop = prop->next ) {
1913 if ( get_ob_property(b, prop->name) )
1919 static short select_grouped_gameprops(bContext *C, Object *ob)
1923 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1924 if (!(base->flag & SELECT) && (objects_share_gameprop(base->object, ob))) {
1925 ED_base_object_select(base, BA_SELECT);
1933 static int object_select_grouped_exec(bContext *C, wmOperator *op)
1935 Scene *scene= CTX_data_scene(C);
1937 int nr = RNA_enum_get(op->ptr, "type");
1938 short changed = 0, seltype;
1940 seltype = RNA_enum_get(op->ptr, "seltype");
1943 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1944 ED_base_object_select(base, BA_DESELECT);
1951 BKE_report(op->reports, RPT_ERROR, "No Active Object");
1952 return OPERATOR_CANCELLED;
1955 if(nr==1) changed = select_grouped_children(C, ob, 1);
1956 else if(nr==2) changed = select_grouped_children(C, ob, 0);
1957 else if(nr==3) changed = select_grouped_parent(C);
1958 else if(nr==4) changed = select_grouped_siblings(C, ob);
1959 else if(nr==5) changed = select_grouped_type(C, ob);
1960 else if(nr==6) changed = select_grouped_layer(C, ob);
1961 else if(nr==7) changed = select_grouped_group(C, ob);
1962 else if(nr==8) changed = select_grouped_object_hooks(C, ob);
1963 else if(nr==9) changed = select_grouped_index_object(C, ob);
1964 else if(nr==10) changed = select_grouped_color(C, ob);
1965 else if(nr==11) changed = select_grouped_gameprops(C, ob);
1968 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
1969 return OPERATOR_FINISHED;
1972 return OPERATOR_CANCELLED;
1975 void OBJECT_OT_select_grouped(wmOperatorType *ot)
1978 ot->name= "Select Grouped";
1979 ot->description = "Select all visible objects grouped by various properties.";
1980 ot->idname= "OBJECT_OT_select_grouped";
1983 ot->invoke= WM_menu_invoke;
1984 ot->exec= object_select_grouped_exec;
1985 ot->poll= ED_operator_scene_editable;
1988 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1990 RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
1991 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
1995 /* ****** selection by layer *******/
1997 static int object_select_by_layer_exec(bContext *C, wmOperator *op)
1999 unsigned int layernum;
2002 seltype = RNA_enum_get(op->ptr, "seltype");
2003 layernum = RNA_int_get(op->ptr, "layer");
2006 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2007 ED_base_object_select(base, BA_DESELECT);
2012 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2013 if(base->lay == (1<< (layernum -1)))
2014 ED_base_object_select(base, BA_SELECT);
2019 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2021 return OPERATOR_FINISHED;
2024 void OBJECT_OT_select_by_layer(wmOperatorType *ot)
2027 ot->name= "select by layer";
2028 ot->description = "Select all visible objects on a layer.";
2029 ot->idname= "OBJECT_OT_select_by_layer";
2032 /*ot->invoke = XXX - need a int grid popup*/
2033 ot->exec= object_select_by_layer_exec;
2034 ot->poll= ED_operator_scene_editable;
2037 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2039 RNA_def_int(ot->srna, "layer", 1, 1, 20, "Layer", "", 1, 20);
2040 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
2043 /* ****** invert selection *******/
2044 static int object_select_inverse_exec(bContext *C, wmOperator *op)
2046 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2047 if (base->flag & SELECT)
2048 ED_base_object_select(base, BA_DESELECT);
2050 ED_base_object_select(base, BA_SELECT);
2055 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2057 return OPERATOR_FINISHED;
2060 void OBJECT_OT_select_inverse(wmOperatorType *ot)
2064 ot->name= "Select Inverse";
2065 ot->description = "Invert selection of all visible objects.";
2066 ot->idname= "OBJECT_OT_select_inverse";
2069 ot->exec= object_select_inverse_exec;
2070 ot->poll= ED_operator_scene_editable;
2073 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2076 /* ****** (de)select All *******/
2078 static int object_select_de_select_all_exec(bContext *C, wmOperator *op)
2083 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2084 if (base->flag & SELECT) {
2092 if (!ok) return OPERATOR_PASS_THROUGH;
2094 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2095 if (a) ED_base_object_select(base, BA_DESELECT);
2096 else ED_base_object_select(base, BA_SELECT);
2101 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2103 return OPERATOR_FINISHED;
2106 void OBJECT_OT_select_all_toggle(wmOperatorType *ot)
2110 ot->name= "deselect all";
2111 ot->description = "(de)select all visible objects in scene.";
2112 ot->idname= "OBJECT_OT_select_all_toggle";
2115 ot->exec= object_select_de_select_all_exec;
2116 ot->poll= ED_operator_scene_editable;
2119 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2122 /* ****** random selection *******/
2124 static int object_select_random_exec(bContext *C, wmOperator *op)
2129 seltype = RNA_enum_get(op->ptr, "seltype");
2132 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2133 ED_base_object_select(base, BA_DESELECT);
2137 percent = RNA_float_get(op->ptr, "percent");
2139 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2140 if (BLI_frand() < percent) {
2141 ED_base_object_select(base, BA_SELECT);
2146 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2148 return OPERATOR_FINISHED;
2151 void OBJECT_OT_select_random(wmOperatorType *ot)
2154 ot->name= "Random select";
2155 ot->description = "Set select on random visible objects.";
2156 ot->idname= "OBJECT_OT_select_random";
2159 /*ot->invoke= object_select_random_invoke XXX - need a number popup ;*/
2160 ot->exec = object_select_random_exec;
2161 ot->poll= ED_operator_scene_editable;
2164 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2166 RNA_def_float_percentage(ot->srna, "percent", 0.5f, 0.0f, 1.0f, "Percent", "percentage of objects to randomly select", 0.0001f, 1.0f);
2167 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
2170 /* ******** Clear object Translation *********** */
2172 static int object_location_clear_exec(bContext *C, wmOperator *op)
2174 int armature_clear= 0;
2176 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2177 if((G.f & G_WEIGHTPAINT)==0) {
2178 if ((ob->protectflag & OB_LOCK_LOCX)==0)
2179 ob->loc[0]= ob->dloc[0]= 0.0f;
2180 if ((ob->protectflag & OB_LOCK_LOCY)==0)
2181 ob->loc[1]= ob->dloc[1]= 0.0f;
2182 if ((ob->protectflag & OB_LOCK_LOCZ)==0)
2183 ob->loc[2]= ob->dloc[2]= 0.0f;
2185 ob->recalc |= OB_RECALC_OB;
2189 if(armature_clear==0) /* in this case flush was done */
2190 ED_anim_dag_flush_update(C);
2192 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2194 return OPERATOR_FINISHED;
2198 void OBJECT_OT_location_clear(wmOperatorType *ot)
2202 ot->name= "Clear Location";
2203 ot->description = "Clear the object's location.";
2204 ot->idname= "OBJECT_OT_location_clear";
2207 ot->invoke= WM_operator_confirm;
2208 ot->exec= object_location_clear_exec;
2209 ot->poll= ED_operator_object_active;
2212 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2215 static int object_rotation_clear_exec(bContext *C, wmOperator *op)
2217 int armature_clear= 0;
2219 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2220 if((G.f & G_WEIGHTPAINT)==0) {
2221 /* eulers can only get cleared if they are not protected */
2222 if ((ob->protectflag & OB_LOCK_ROTX)==0)
2223 ob->rot[0]= ob->drot[0]= 0.0f;
2224 if ((ob->protectflag & OB_LOCK_ROTY)==0)
2225 ob->rot[1]= ob->drot[1]= 0.0f;
2226 if ((ob->protectflag & OB_LOCK_ROTZ)==0)
2227 ob->rot[2]= ob->drot[2]= 0.0f;
2229 ob->recalc |= OB_RECALC_OB;
2233 if(armature_clear==0) /* in this case flush was done */
2234 ED_anim_dag_flush_update(C);
2236 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2238 return OPERATOR_FINISHED;
2242 void OBJECT_OT_rotation_clear(wmOperatorType *ot)
2246 ot->name= "Clear Rotation";
2247 ot->description = "Clear the object's rotation.";
2248 ot->idname= "OBJECT_OT_rotation_clear";
2251 ot->invoke= WM_operator_confirm;
2252 ot->exec= object_rotation_clear_exec;
2253 ot->poll= ED_operator_object_active;
2256 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2259 static int object_scale_clear_exec(bContext *C, wmOperator *op)
2261 int armature_clear= 0;
2263 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2264 if((G.f & G_WEIGHTPAINT)==0) {
2265 if ((ob->protectflag & OB_LOCK_SCALEX)==0) {
2269 if ((ob->protectflag & OB_LOCK_SCALEY)==0) {
2273 if ((ob->protectflag & OB_LOCK_SCALEZ)==0) {
2278 ob->recalc |= OB_RECALC_OB;
2282 if(armature_clear==0) /* in this case flush was done */
2283 ED_anim_dag_flush_update(C);
2285 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2287 return OPERATOR_FINISHED;
2290 void OBJECT_OT_scale_clear(wmOperatorType *ot)
2294 ot->name= "Clear Scale";
2295 ot->description = "Clear the object's scale.";
2296 ot->idname= "OBJECT_OT_scale_clear";
2299 ot->invoke= WM_operator_confirm;
2300 ot->exec= object_scale_clear_exec;
2301 ot->poll= ED_operator_object_active;
2304 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2307 static int object_origin_clear_exec(bContext *C, wmOperator *op)
2309 float *v1, *v3, mat[3][3];
2310 int armature_clear= 0;
2312 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2315 v3= ob->parentinv[3];
2317 Mat3CpyMat4(mat, ob->parentinv);
2322 Mat3MulVecfl(mat, v3);
2324 ob->recalc |= OB_RECALC_OB;
2328 if(armature_clear==0) /* in this case flush was done */
2329 ED_anim_dag_flush_update(C);
2331 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2333 return OPERATOR_FINISHED;
2336 void OBJECT_OT_origin_clear(wmOperatorType *ot)
2340 ot->name= "Clear Origin";
2341 ot->description = "Clear the object's origin.";
2342 ot->idname= "OBJECT_OT_origin_clear";
2345 ot->invoke= WM_operator_confirm;
2346 ot->exec= object_origin_clear_exec;
2347 ot->poll= ED_operator_object_active;
2350 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2353 /* ********* clear/set restrict view *********/
2354 static int object_restrictview_clear_exec(bContext *C, wmOperator *op)
2356 ScrArea *sa= CTX_wm_area(C);
2357 View3D *v3d= sa->spacedata.first;
2358 Scene *scene= CTX_data_scene(C);
2362 /* XXX need a context loop to handle such cases */
2363 for(base = FIRSTBASE; base; base=base->next){
2364 if((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
2365 base->flag |= SELECT;
2366 base->object->flag = base->flag;
2367 base->object->restrictflag &= ~OB_RESTRICT_VIEW;
2372 DAG_scene_sort(scene);
2373 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
2376 return OPERATOR_FINISHED;
2379 void OBJECT_OT_restrictview_clear(wmOperatorType *ot)
2383 ot->name= "Clear Restrict View";
2384 ot->description = "Reveal the object by setting the restrictview flag.";
2385 ot->idname= "OBJECT_OT_restrictview_clear";
2388 ot->exec= object_restrictview_clear_exec;
2389 ot->poll= ED_operator_view3d_active;
2392 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2395 static int object_restrictview_set_exec(bContext *C, wmOperator *op)
2397 Scene *scene= CTX_data_scene(C);
2399 int unselected= RNA_boolean_get(op->ptr, "unselected");
2401 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2403 if (base->flag & SELECT){
2404 base->flag &= ~SELECT;
2405 base->object->flag = base->flag;
2406 base->object->restrictflag |= OB_RESTRICT_VIEW;
2409 ED_base_object_activate(C, NULL);
2414 if (!(base->flag & SELECT)){
2415 base->object->restrictflag |= OB_RESTRICT_VIEW;
2423 DAG_scene_sort(scene);
2425 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2429 return OPERATOR_FINISHED;
2432 void OBJECT_OT_restrictview_set(wmOperatorType *ot)
2435 ot->name= "Set Restrict View";
2436 ot->description = "Hide the object by setting the restrictview flag.";
2437 ot->idname= "OBJECT_OT_restrictview_set";
2440 ot->exec= object_restrictview_set_exec;
2441 ot->poll= ED_operator_view3d_active;
2444 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2446 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects.");
2449 /* ************* Slow Parent ******************* */
2450 static int object_slowparent_set_exec(bContext *C, wmOperator *op)
2453 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2455 if(base->object->parent) base->object->partype |= PARSLOW;
2456 base->object->recalc |= OB_RECALC_OB;
2461 ED_anim_dag_flush_update(C);
2463 WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
2465 return OPERATOR_FINISHED;
2468 void OBJECT_OT_slowparent_set(wmOperatorType *ot)
2472 ot->name= "Set Slow Parent";
2473 ot->description = "Set the object's slow parent.";
2474 ot->idname= "OBJECT_OT_slow_parent_set";
2477 ot->invoke= WM_operator_confirm;
2478 ot->exec= object_slowparent_set_exec;
2479 ot->poll= ED_operator_view3d_active;
2482 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2485 static int object_slowparent_clear_exec(bContext *C, wmOperator *op)
2487 Scene *scene= CTX_data_scene(C);
2489 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2490 if(base->object->parent) {
2491 if(base->object->partype & PARSLOW) {
2492 base->object->partype -= PARSLOW;
2493 where_is_object(scene, base->object);
2494 base->object->partype |= PARSLOW;
2495 base->object->recalc |= OB_RECALC_OB;
2502 ED_anim_dag_flush_update(C);
2504 WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
2506 return OPERATOR_FINISHED;
2509 void OBJECT_OT_slowparent_clear(wmOperatorType *ot)
2513 ot->name= "Clear Slow Parent";
2514 ot->description = "Clear the object's slow parent.";
2515 ot->idname= "OBJECT_OT_slow_parent_clear";
2518 ot->invoke= WM_operator_confirm;
2519 ot->exec= object_slowparent_clear_exec;
2520 ot->poll= ED_operator_view3d_active;
2523 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2525 /* ******************** **************** */
2528 #define BEZSELECTED_HIDDENHANDLES(bezt) ((G.f & G_HIDDENHANDLES) ? (bezt)->f2 & SELECT : BEZSELECTED(bezt))
2529 /* only in edit mode */
2530 void make_vertex_parent(Scene *scene, Object *obedit, View3D *v3d)
2538 int a, v1=0, v2=0, v3=0, v4=0, nr=1;
2540 /* we need 1 to 3 selected vertices */
2542 if(obedit->type==OB_MESH) {
2543 Mesh *me= obedit->data;
2544 EditMesh *em = BKE_mesh_get_editmesh(me);
2546 eve= em->verts.first;
2550 else if(v2==0) v2= nr;
2551 else if(v3==0) v3= nr;
2552 else if(v4==0) v4= nr;
2559 BKE_mesh_end_editmesh(me, em);
2561 else if(ELEM(obedit->type, OB_SURF, OB_CURVE)) {
2562 ListBase *editnurb= curve_get_editcurve(obedit);
2564 nu= editnurb->first;
2566 if((nu->type & 7)==CU_BEZIER) {
2570 if(BEZSELECTED_HIDDENHANDLES(bezt)) {
2572 else if(v2==0) v2= nr;
2573 else if(v3==0) v3= nr;
2574 else if(v4==0) v4= nr;
2583 a= nu->pntsu*nu->pntsv;
2585 if(bp->f1 & SELECT) {
2587 else if(v2==0) v2= nr;
2588 else if(v3==0) v3= nr;
2589 else if(v4==0) v4= nr;
2599 else if(obedit->type==OB_LATTICE) {
2600 Lattice *lt= obedit->data;
2602 a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
2603 bp= lt->editlatt->def;
2605 if(bp->f1 & SELECT) {
2607 else if(v2==0) v2= nr;
2608 else if(v3==0) v3= nr;
2609 else if(v4==0) v4= nr;
2617 if(v4 || !((v1 && v2==0 && v3==0) || (v1 && v2 && v3)) ) {
2618 error("Select either 1 or 3 vertices to parent to");
2622 if(okee("Make vertex parent")==0) return;
2624 for(base= FIRSTBASE; base; base= base->next) {
2625 if(TESTBASELIB(v3d, base)) {
2629 ob->recalc |= OB_RECALC;
2630 par= BASACT->object->parent;
2637 error("Loop in parents");
2642 ob->parent= BASACT->object;
2644 ob->partype= PARVERT3;
2649 /* inverse parent matrix */
2650 what_does_parent(scene, ob, &workob);
2651 Mat4Invert(ob->parentinv, workob.obmat);
2654 ob->partype= PARVERT1;
2657 /* inverse parent matrix */
2658 what_does_parent(scene, ob, &workob);
2659 Mat4Invert(ob->parentinv, workob.obmat);
2666 DAG_scene_sort(scene);
2669 static Object *group_objects_menu(Group *group)
2676 for(go= group->gobject.first; go; go= go->next) {
2680 if(len==0) return NULL;
2682 str= MEM_callocN(40+32*len, "menu");
2684 strcpy(str, "Make Proxy for: %t");
2686 for(nr=1, go= group->gobject.first; go; go= go->next, nr++) {
2687 a+= sprintf(str+a, "|%s %%x%d", go->ob->id.name+2, nr);
2690 a= pupmenu_col(str, 20);
2693 go= BLI_findlink(&group->gobject, a-1);
2700 /* adds empty object to become local replacement data of a library-linked object */
2701 void make_proxy(Scene *scene)
2706 if(scene->id.lib) return;
2707 if(ob==NULL) return;
2710 if(ob->dup_group && ob->dup_group->id.lib) {
2712 /* gives menu with list of objects in group */
2713 ob= group_objects_menu(ob->dup_group);
2715 else if(ob->id.lib) {
2716 if(okee("Make Proxy Object")==0)
2720 error("Can only make proxy for a referenced object or group");
2726 Base *newbase, *oldbase= BASACT;
2729 newob= add_object(scene, OB_EMPTY);
2731 strcpy(name, gob->id.name+2);
2733 strcpy(name, ob->id.name+2);
2734 strcat(name, "_proxy");
2735 rename_id(&newob->id, name);
2738 newbase= BASACT; /* add_object sets active... */
2739 newbase->lay= oldbase->lay;
2740 newob->lay= newbase->lay;
2742 /* remove base, leave user count of object, it gets linked in object_make_proxy */
2744 BLI_remlink(&scene->base, oldbase);
2747 object_make_proxy(newob, ob, gob);
2749 DAG_scene_sort(scene);
2750 DAG_object_flush_update(scene, newob, OB_RECALC);
2754 /* ******************** make parent operator *********************** */
2756 #define PAR_OBJECT 0
2757 #define PAR_ARMATURE 1
2758 #define PAR_ARMATURE_NAME 2
2759 #define PAR_ARMATURE_ENVELOPE 3
2760 #define PAR_ARMATURE_AUTO 4
2763 #define PAR_FOLLOW 7
2764 #define PAR_PATH_CONST 8
2765 #define PAR_LATTICE 9
2766 #define PAR_VERTEX 10
2769 static EnumPropertyItem prop_make_parent_types[] = {
2770 {PAR_OBJECT, "OBJECT", 0, "Object", ""},
2771 {PAR_ARMATURE, "ARMATURE", 0, "Armature Deform", ""},
2772 {PAR_ARMATURE_NAME, "ARMATURE_NAME", 0, " With Empty Groups", ""},
2773 {PAR_ARMATURE_AUTO, "ARMATURE_AUTO", 0, " With Automatic Weights", ""},
2774 {PAR_ARMATURE_ENVELOPE, "ARMATURE_ENVELOPE", 0, " With Envelope Weights", ""},
2775 {PAR_BONE, "BONE", 0, "Bone", ""},
2776 {PAR_CURVE, "CURVE", 0, "Curve Deform", ""},
2777 {PAR_FOLLOW, "FOLLOW", 0, "Follow Path", ""},
2778 {PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""},
2779 {PAR_LATTICE, "LATTICE", 0, "Lattice Deform", ""},
2780 {PAR_VERTEX, "VERTEX", 0, "Vertex", ""},
2781 {PAR_TRIA, "TRIA", 0, "Triangle", ""},
2782 {0, NULL, 0, NULL, NULL}
2785 static int test_parent_loop(Object *par, Object *ob)
2787 /* test if 'ob' is a parent somewhere in par's parents */
2789 if(par == NULL) return 0;
2790 if(ob == par) return 1;
2792 return test_parent_loop(par->parent, ob);
2795 void ED_object_parent(Object *ob, Object *par, int type, const char *substr)
2797 if(!par || test_parent_loop(par, ob)) {
2799 ob->partype= PAROBJECT;
2800 ob->parsubstr[0]= 0;
2804 /* this could use some more checks */
2807 ob->partype &= ~PARTYPE;
2808 ob->partype |= type;
2809 BLI_strncpy(ob->parsubstr, substr, sizeof(ob->parsubstr));
2812 static int parent_set_exec(bContext *C, wmOperator *op)
2814 Scene *scene= CTX_data_scene(C);
2815 Object *par= CTX_data_active_object(C);
2816 bPoseChannel *pchan= NULL;
2817 int partype= RNA_enum_get(op->ptr, "type");
2818 int pararm= ELEM4(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
2820 par->recalc |= OB_RECALC_OB;
2823 if(partype==PAR_FOLLOW || partype==PAR_PATH_CONST) {
2824 if(par->type!=OB_CURVE)
2825 return OPERATOR_CANCELLED;
2827 Curve *cu= par->data;
2829 if((cu->flag & CU_PATH)==0) {
2830 cu->flag |= CU_PATH|CU_FOLLOW;
2831 makeDispListCurveTypes(scene, par, 0); /* force creation of path data */
2833 else cu->flag |= CU_FOLLOW;
2835 /* fall back on regular parenting now */
2836 partype= PAR_OBJECT;
2839 else if(partype==PAR_BONE) {
2840 pchan= get_active_posechannel(par);
2843 error("No active Bone");
2844 return OPERATOR_CANCELLED;
2848 /* context itterator */
2849 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2853 if( test_parent_loop(par, ob) ) {
2854 error("Loop in parents");
2859 /* apply transformation of previous parenting */
2860 ED_object_apply_obmat(ob);
2866 strcpy (ob->parsubstr, pchan->name);
2868 ob->parsubstr[0]= 0;
2871 if(partype==PAR_PATH_CONST) {
2873 bFollowPathConstraint *data;
2874 float cmat[4][4], vec[3];
2876 con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
2877 strcpy (con->name, "AutoPath");
2882 add_constraint_to_object(con, ob);
2884 get_constraint_target_matrix(con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra - give_timeoffset(ob));
2885 VecSubf(vec, ob->obmat[3], cmat[3]);
2887 ob->loc[0] = vec[0];
2888 ob->loc[1] = vec[1];
2890 else if(pararm && ob->type==OB_MESH && par->type == OB_ARMATURE) {
2891 if(partype == PAR_ARMATURE_NAME)
2892 create_vgroups_from_armature(scene, ob, par, ARM_GROUPS_NAME);
2893 else if(partype == PAR_ARMATURE_ENVELOPE)
2894 create_vgroups_from_armature(scene, ob, par, ARM_GROUPS_ENVELOPE);
2895 else if(partype == PAR_ARMATURE_AUTO)
2896 create_vgroups_from_armature(scene, ob, par, ARM_GROUPS_AUTO);
2898 /* get corrected inverse */
2899 ob->partype= PAROBJECT;
2900 what_does_parent(scene, ob, &workob);
2902 ob->partype= PARSKEL;
2904 Mat4Invert(ob->parentinv, workob.obmat);
2907 /* calculate inverse parent matrix */
2908 what_does_parent(scene, ob, &workob);
2909 Mat4Invert(ob->parentinv, workob.obmat);
2912 ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
2914 if( ELEM(partype, PAR_CURVE, PAR_LATTICE) || pararm )
2915 ob->partype= PARSKEL; /* note, dna define, not operator property */
2917 ob->partype= PAROBJECT; /* note, dna define, not operator property */
2923 DAG_scene_sort(CTX_data_scene(C));
2924 ED_anim_dag_flush_update(C);
2925 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2927 return OPERATOR_FINISHED;
2930 static int parent_set_invoke(bContext *C, wmOperator *op, wmEvent *event)
2932 Object *ob= CTX_data_active_object(C);
2933 uiPopupMenu *pup= uiPupMenuBegin(C, "Set Parent To", 0);
2934 uiLayout *layout= uiPupMenuLayout(pup);
2936 uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
2937 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_OBJECT);
2939 /* ob becomes parent, make the associated menus */
2940 if(ob->type==OB_ARMATURE) {
2941 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE);
2942 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE_NAME);
2943 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE_ENVELOPE);
2944 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE_AUTO);
2945 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_BONE);
2947 else if(ob->type==OB_CURVE) {
2948 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_CURVE);
2949 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_FOLLOW);
2950 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_PATH_CONST);
2952 else if(ob->type == OB_LATTICE) {
2953 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_LATTICE);
2956 uiPupMenuEnd(C, pup);
2958 return OPERATOR_CANCELLED;
2962 void OBJECT_OT_parent_set(wmOperatorType *ot)
2965 ot->name= "Make Parent";
2966 ot->description = "Set the object's parenting.";
2967 ot->idname= "OBJECT_OT_parent_set";
2970 ot->invoke= parent_set_invoke;
2971 ot->exec= parent_set_exec;
2973 ot->poll= ED_operator_object_active;
2976 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2978 RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
2981 /* *** make track ***** */
2982 static EnumPropertyItem prop_make_track_types[] = {
2983 {1, "TRACKTO", 0, "TrackTo Constraint", ""},
2984 {2, "LOCKTRACK", 0, "LockTrack Constraint", ""},
2985 {3, "OLDTRACK", 0, "Old Track", ""},
2986 {0, NULL, 0, NULL, NULL}
2989 static int track_set_exec(bContext *C, wmOperator *op)
2991 Scene *scene= CTX_data_scene(C);
2992 int type= RNA_enum_get(op->ptr, "type");
2996 bTrackToConstraint *data;
2998 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
3000 con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
3001 strcpy (con->name, "AutoTrack");
3004 data->tar = BASACT->object;
3005 base->object->recalc |= OB_RECALC;
3007 /* Lamp and Camera track differently by default */
3008 if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
3009 data->reserved1 = TRACK_nZ;
3010 data->reserved2 = UP_Y;
3013 add_constraint_to_object(con, base->object);
3018 else if(type == 2) {
3020 bLockTrackConstraint *data;
3022 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
3024 con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
3025 strcpy (con->name, "AutoTrack");
3028 data->tar = BASACT->object;
3029 base->object->recalc |= OB_RECALC;
3031 /* Lamp and Camera track differently by default */
3032 if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
3033 data->trackflag = TRACK_nZ;
3034 data->lockflag = LOCK_Y;
3037 add_constraint_to_object(con, base->object);
3043 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
3045 base->object->track= BASACT->object;
3046 base->object->recalc |= OB_RECALC;
3051 DAG_scene_sort(CTX_data_scene(C));
3052 ED_anim_dag_flush_update(C);
3054 return OPERATOR_FINISHED;
3057 void OBJECT_OT_track_set(wmOperatorType *ot)
3060 ot->name= "Make Track";
3061 ot->description = "Make the object track another object, either by constraint or old way or locked track.";
3062 ot->idname= "OBJECT_OT_track_set";
3065 ot->invoke= WM_menu_invoke;
3066 ot->exec= track_set_exec;
3068 ot->poll= ED_operator_scene_editable;
3071 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
3073 RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
3076 /* ************* Make Dupli Real ********* */
3077 static void make_object_duplilist_real(Scene *scene, View3D *v3d, Base *base)
3084 if(!base && !(base = BASACT))
3087 if(!(base->object->transflag & OB_DUPLI))
3090 lb= object_duplilist(scene, base->object);
3092 for(dob= lb->first; dob; dob= dob->next) {
3093 ob= copy_object(dob->ob);
3094 /* font duplis can have a totcol without material, we get them from parent
3095 * should be implemented better...
3097 if(ob->mat==NULL) ob->totcol= 0;
3099 basen= MEM_dupallocN(base);
3100 basen->flag &= ~OB_FROMDUPLI;
3101 BLI_addhead(&scene->base, basen); /* addhead: othwise eternal loop */
3103 ob->ipo= NULL; /* make sure apply works */
3104 ob->parent= ob->track= NULL;
3105 ob->disp.first= ob->disp.last= NULL;
3106 ob->transflag &= ~OB_DUPLI;
3108 Mat4CpyMat4(ob->obmat, dob->mat);
3109 ED_object_apply_obmat(ob);
3112 copy_object_set_idnew(scene, v3d, 0);
3114 free_object_duplilist(lb);
3116 base->object->transflag &= ~OB_DUPLI;
3120 static int object_duplicates_make_real_exec(bContext *C, wmOperator *op)
3122 Scene *scene= CTX_data_scene(C);
3123 ScrArea *sa= CTX_wm_area(C);
3124 View3D *v3d= sa->spacedata.first;