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_mball.h"
118 #include "ED_object.h"
119 #include "ED_screen.h"
120 #include "ED_transform.h"
121 #include "ED_types.h"
123 #include "ED_view3d.h"
125 #include "UI_interface.h"
127 #include "RNA_access.h"
128 #include "RNA_define.h"
130 /* for menu/popup icons etc etc*/
131 #include "UI_interface.h"
132 #include "UI_resources.h"
135 #include "WM_types.h"
137 #include "object_intern.h" // own include
139 /* ************* XXX **************** */
140 static void error() {}
141 static void waitcursor(int val) {}
142 static int pupmenu(const char *msg) {return 0;}
143 static int pupmenu_col(const char *msg, int val) {return 0;}
144 static int okee(const char *msg) {return 0;}
148 static void error_libdata() {}
150 /* ********************************** */
152 /* --------------------------------- */
154 /* simple API for object selection, rather than just using the flag
155 * this takes into account the 'restrict selection in 3d view' flag.
156 * deselect works always, the restriction just prevents selection */
158 /* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! */
160 void ED_base_object_select(Base *base, short mode)
163 if (mode==BA_SELECT) {
164 if (!(base->object->restrictflag & OB_RESTRICT_SELECT))
165 if (mode==BA_SELECT) base->flag |= SELECT;
167 else if (mode==BA_DESELECT) {
168 base->flag &= ~SELECT;
170 base->object->flag= base->flag;
174 /* also to set active NULL */
175 void ED_base_object_activate(bContext *C, Base *base)
177 Scene *scene= CTX_data_scene(C);
180 /* activating a non-mesh, should end a couple of modes... */
181 if(base && base->object->type!=OB_MESH)
182 ED_view3d_exit_paint_modes(C);
184 /* sets scene->basact */
189 /* XXX old signals, remember to handle notifiers now! */
190 // select_actionchannel_by_name(base->object->action, "Object", 1);
192 /* disable temporal locks */
193 for(tbase=FIRSTBASE; tbase; tbase= tbase->next) {
194 if(base!=tbase && (tbase->object->shapeflag & OB_SHAPE_TEMPLOCK)) {
195 tbase->object->shapeflag &= ~OB_SHAPE_TEMPLOCK;
196 DAG_object_flush_update(scene, tbase->object, OB_RECALC_DATA);
199 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
202 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, NULL);
207 void ED_object_base_init_from_view(bContext *C, Base *base)
209 View3D *v3d= CTX_wm_view3d(C);
210 Scene *scene= CTX_data_scene(C);
211 Object *ob= base->object;
217 base->lay = scene->lay;
218 VECCOPY(ob->loc, scene->cursor);
221 if (v3d->localview) {
222 base->lay= ob->lay= v3d->layact | v3d->lay;
223 VECCOPY(ob->loc, v3d->cursor);
226 base->lay= ob->lay= v3d->layact;
227 VECCOPY(ob->loc, scene->cursor);
230 if (U.flag & USER_ADD_VIEWALIGNED) {
231 ARegion *ar= CTX_wm_region(C);
233 RegionView3D *rv3d= ar->regiondata;
235 rv3d->viewquat[0]= -rv3d->viewquat[0];
236 QuatToEul(rv3d->viewquat, ob->rot);
237 rv3d->viewquat[0]= -rv3d->viewquat[0];
241 where_is_object(scene, ob);
244 /* ******************* add object operator ****************** */
246 static EnumPropertyItem prop_object_types[] = {
247 {OB_MESH, "MESH", 0, "Mesh", ""},
248 {OB_CURVE, "CURVE", 0, "Curve", ""},
249 {OB_SURF, "SURFACE", 0, "Surface", ""},
250 {OB_MBALL, "META", 0, "Meta", ""},
251 {OB_FONT, "TEXT", 0, "Text", ""},
252 {0, "", 0, NULL, NULL},
253 {OB_ARMATURE, "ARMATURE", 0, "Armature", ""},
254 {OB_LATTICE, "LATTICE", 0, "Lattice", ""},
255 {OB_EMPTY, "EMPTY", 0, "Empty", ""},
256 {0, "", 0, NULL, NULL},
257 {OB_CAMERA, "CAMERA", 0, "Camera", ""},
258 {OB_LAMP, "LAMP", 0, "Lamp", ""},
259 {0, NULL, 0, NULL, NULL}
264 void add_object_draw(Scene *scene, View3D *v3d, int type) /* for toolbox or menus, only non-editmode stuff */
266 /* keep here to get things compile, remove later */
269 /* for object add primitive operators */
270 static Object *object_add_type(bContext *C, int type)
272 Scene *scene= CTX_data_scene(C);
275 /* XXX hrms, this is editor level operator, remove? */
276 ED_view3d_exit_paint_modes(C);
278 /* for as long scene has editmode... */
279 if (CTX_data_edit_object(C))
280 ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* freedata, and undo */
282 /* deselects all, sets scene->basact */
283 ob= add_object(scene, type);
284 /* editor level activate, notifiers */
285 ED_base_object_activate(C, BASACT);
287 /* more editor stuff */
288 ED_object_base_init_from_view(C, BASACT);
290 DAG_scene_sort(scene);
295 /* for object add operator */
296 static int object_add_exec(bContext *C, wmOperator *op)
298 object_add_type(C, RNA_int_get(op->ptr, "type"));
300 return OPERATOR_FINISHED;
303 void OBJECT_OT_object_add(wmOperatorType *ot)
306 ot->name= "Add Object";
307 ot->description = "Add an object to the scene.";
308 ot->idname= "OBJECT_OT_object_add";
311 ot->invoke= WM_menu_invoke;
312 ot->exec= object_add_exec;
314 ot->poll= ED_operator_scene_editable;
317 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
319 RNA_def_enum(ot->srna, "type", prop_object_types, 0, "Type", "");
322 /* ***************** add primitives *************** */
323 /* ****** work both in and outside editmode ****** */
325 static EnumPropertyItem prop_mesh_types[] = {
326 {0, "PLANE", ICON_MESH_PLANE, "Plane", ""},
327 {1, "CUBE", ICON_MESH_CUBE, "Cube", ""},
328 {2, "CIRCLE", ICON_MESH_CIRCLE, "Circle", ""},
329 {3, "UVSPHERE", ICON_MESH_UVSPHERE, "UVsphere", ""},
330 {4, "ICOSPHERE", ICON_MESH_ICOSPHERE, "Icosphere", ""},
331 {5, "CYLINDER", ICON_MESH_TUBE, "Cylinder", ""},
332 {6, "CONE", ICON_MESH_CONE, "Cone", ""},
333 {0, "", 0, NULL, NULL},
334 {7, "GRID", ICON_MESH_GRID, "Grid", ""},
335 {8, "MONKEY", ICON_MESH_MONKEY, "Monkey", ""},
336 {0, NULL, 0, NULL, NULL}
339 static int object_add_mesh_exec(bContext *C, wmOperator *op)
341 Object *obedit= CTX_data_edit_object(C);
344 if(obedit==NULL || obedit->type!=OB_MESH) {
345 object_add_type(C, OB_MESH);
346 ED_object_enter_editmode(C, EM_DO_UNDO);
349 else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
351 switch(RNA_enum_get(op->ptr, "type")) {
353 WM_operator_name_call(C, "MESH_OT_primitive_plane_add", WM_OP_INVOKE_REGION_WIN, NULL);
356 WM_operator_name_call(C, "MESH_OT_primitive_cube_add", WM_OP_INVOKE_REGION_WIN, NULL);
359 WM_operator_name_call(C, "MESH_OT_primitive_circle_add", WM_OP_INVOKE_REGION_WIN, NULL);
362 WM_operator_name_call(C, "MESH_OT_primitive_uv_sphere_add", WM_OP_INVOKE_REGION_WIN, NULL);
365 WM_operator_name_call(C, "MESH_OT_primitive_ico_sphere_add", WM_OP_INVOKE_REGION_WIN, NULL);
368 WM_operator_name_call(C, "MESH_OT_primitive_cylinder_add", WM_OP_INVOKE_REGION_WIN, NULL);
371 WM_operator_name_call(C, "MESH_OT_primitive_cone_add", WM_OP_INVOKE_REGION_WIN, NULL);
374 WM_operator_name_call(C, "MESH_OT_primitive_grid_add", WM_OP_INVOKE_REGION_WIN, NULL);
377 WM_operator_name_call(C, "MESH_OT_primitive_monkey_add", WM_OP_INVOKE_REGION_WIN, NULL);
381 if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
382 ED_object_exit_editmode(C, EM_FREEDATA);
385 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
387 return OPERATOR_FINISHED;
391 void OBJECT_OT_mesh_add(wmOperatorType *ot)
394 ot->name= "Add Mesh";
395 ot->description = "Add a mesh object to the scene.";
396 ot->idname= "OBJECT_OT_mesh_add";
399 ot->invoke= WM_menu_invoke;
400 ot->exec= object_add_mesh_exec;
402 ot->poll= ED_operator_scene_editable;
404 /* flags: no register or undo, this operator calls operators */
405 ot->flag= 0; //OPTYPE_REGISTER|OPTYPE_UNDO;
407 RNA_def_enum(ot->srna, "type", prop_mesh_types, 0, "Primitive", "");
410 static EnumPropertyItem prop_curve_types[] = {
411 {CU_BEZIER|CU_2D|CU_PRIM_CURVE, "BEZIER_CURVE", ICON_CURVE_BEZCURVE, "Bezier Curve", ""},
412 {CU_BEZIER|CU_2D|CU_PRIM_CIRCLE, "BEZIER_CIRCLE", ICON_CURVE_BEZCIRCLE, "Bezier Circle", ""},
413 {CU_NURBS|CU_2D|CU_PRIM_CURVE, "NURBS_CURVE", ICON_CURVE_NCURVE, "NURBS Curve", ""},
414 {CU_NURBS|CU_2D|CU_PRIM_CIRCLE, "NURBS_CIRCLE", ICON_CURVE_NCIRCLE, "NURBS Circle", ""},
415 {CU_NURBS|CU_2D|CU_PRIM_PATH, "PATH", ICON_CURVE_PATH, "Path", ""},
416 {0, NULL, 0, NULL, NULL}
419 static int object_add_curve_exec(bContext *C, wmOperator *op)
421 Object *obedit= CTX_data_edit_object(C);
426 if(obedit==NULL || obedit->type!=OB_CURVE) {
427 object_add_type(C, OB_CURVE);
428 ED_object_enter_editmode(C, 0);
431 else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
433 obedit= CTX_data_edit_object(C);
434 nu= add_nurbs_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
435 editnurb= curve_get_editcurve(obedit);
436 BLI_addtail(editnurb, nu);
439 if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
440 ED_object_exit_editmode(C, EM_FREEDATA);
443 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
445 return OPERATOR_FINISHED;
448 static int object_add_curve_invoke(bContext *C, wmOperator *op, wmEvent *event)
450 Object *obedit= CTX_data_edit_object(C);
454 pup= uiPupMenuBegin(C, op->type->name, 0);
455 layout= uiPupMenuLayout(pup);
456 if(!obedit || obedit->type == OB_CURVE)
457 uiItemsEnumO(layout, op->type->idname, "type");
459 uiItemsEnumO(layout, "OBJECT_OT_surface_add", "type");
460 uiPupMenuEnd(C, pup);
462 return OPERATOR_CANCELLED;
465 void OBJECT_OT_curve_add(wmOperatorType *ot)
468 ot->name= "Add Curve";
469 ot->description = "Add a curve object to the scene.";
470 ot->idname= "OBJECT_OT_curve_add";
473 ot->invoke= object_add_curve_invoke;
474 ot->exec= object_add_curve_exec;
476 ot->poll= ED_operator_scene_editable;
479 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
481 RNA_def_enum(ot->srna, "type", prop_curve_types, 0, "Primitive", "");
484 static EnumPropertyItem prop_surface_types[]= {
485 {CU_PRIM_CURVE|CU_NURBS, "NURBS_CURVE", ICON_SURFACE_NCURVE, "NURBS Curve", ""},
486 {CU_PRIM_CIRCLE|CU_NURBS, "NURBS_CIRCLE", ICON_SURFACE_NCIRCLE, "NURBS Circle", ""},
487 {CU_PRIM_PATCH|CU_NURBS, "NURBS_SURFACE", ICON_SURFACE_NSURFACE, "NURBS Surface", ""},
488 {CU_PRIM_TUBE|CU_NURBS, "NURBS_TUBE", ICON_SURFACE_NTUBE, "NURBS Tube", ""},
489 {CU_PRIM_SPHERE|CU_NURBS, "NURBS_SPHERE", ICON_SURFACE_NSPHERE, "NURBS Sphere", ""},
490 {CU_PRIM_DONUT|CU_NURBS, "NURBS_DONUT", ICON_SURFACE_NDONUT, "NURBS Donut", ""},
491 {0, NULL, 0, NULL, NULL}
494 static int object_add_surface_exec(bContext *C, wmOperator *op)
496 Object *obedit= CTX_data_edit_object(C);
501 if(obedit==NULL || obedit->type!=OB_SURF) {
502 object_add_type(C, OB_SURF);
503 ED_object_enter_editmode(C, 0);
506 else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
508 obedit= CTX_data_edit_object(C);
509 nu= add_nurbs_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
510 editnurb= curve_get_editcurve(obedit);
511 BLI_addtail(editnurb, nu);
514 if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
515 ED_object_exit_editmode(C, EM_FREEDATA);
518 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
520 return OPERATOR_FINISHED;
523 void OBJECT_OT_surface_add(wmOperatorType *ot)
526 ot->name= "Add Surface";
527 ot->description = "Add a surface object to the scene.";
528 ot->idname= "OBJECT_OT_surface_add";
531 ot->invoke= WM_menu_invoke;
532 ot->exec= object_add_surface_exec;
534 ot->poll= ED_operator_scene_editable;
537 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
539 RNA_def_enum(ot->srna, "type", prop_surface_types, 0, "Primitive", "");
542 static EnumPropertyItem prop_metaball_types[]= {
543 {MB_BALL, "MBALL_BALL", ICON_META_BALL, "Meta Ball", ""},
544 {MB_TUBE, "MBALL_TUBE", ICON_META_TUBE, "Meta Tube", ""},
545 {MB_PLANE, "MBALL_PLANE", ICON_META_PLANE, "Meta Plane", ""},
546 {MB_CUBE, "MBALL_CUBE", ICON_META_CUBE, "Meta Cube", ""},
547 {MB_ELIPSOID, "MBALL_ELLIPSOID", ICON_META_ELLIPSOID, "Meta Ellipsoid", ""},
548 {0, NULL, 0, NULL, NULL}
551 static int object_metaball_add_exec(bContext *C, wmOperator *op)
553 Object *obedit= CTX_data_edit_object(C);
558 if(obedit==NULL || obedit->type!=OB_MBALL) {
559 object_add_type(C, OB_MBALL);
560 ED_object_enter_editmode(C, 0);
563 else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
565 obedit= CTX_data_edit_object(C);
566 elem= (MetaElem*)add_metaball_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
567 mball= (MetaBall*)obedit->data;
568 BLI_addtail(mball->editelems, elem);
571 if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
572 ED_object_exit_editmode(C, EM_FREEDATA);
575 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
577 return OPERATOR_FINISHED;
580 static int object_metaball_add_invoke(bContext *C, wmOperator *op, wmEvent *event)
582 Object *obedit= CTX_data_edit_object(C);
586 pup= uiPupMenuBegin(C, op->type->name, 0);
587 layout= uiPupMenuLayout(pup);
588 if(!obedit || obedit->type == OB_MBALL)
589 uiItemsEnumO(layout, op->type->idname, "type");
591 uiItemsEnumO(layout, "OBJECT_OT_metaball_add", "type");
592 uiPupMenuEnd(C, pup);
594 return OPERATOR_CANCELLED;
597 void OBJECT_OT_metaball_add(wmOperatorType *ot)
600 ot->name= "Metaball";
601 ot->description= "Add an metaball object to the scene.";
602 ot->idname= "OBJECT_OT_metaball_add";
605 ot->invoke= object_metaball_add_invoke;
606 ot->exec= object_metaball_add_exec;
607 ot->poll= ED_operator_scene_editable;
610 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
612 RNA_def_enum(ot->srna, "type", prop_metaball_types, 0, "Primitive", "");
614 static int object_add_text_exec(bContext *C, wmOperator *op)
616 Object *obedit= CTX_data_edit_object(C);
618 if(obedit && obedit->type==OB_FONT)
619 return OPERATOR_CANCELLED;
621 object_add_type(C, OB_FONT);
622 obedit= CTX_data_active_object(C);
624 if(U.flag & USER_ADD_EDITMODE)
625 ED_object_enter_editmode(C, 0);
627 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
629 return OPERATOR_FINISHED;
632 void OBJECT_OT_text_add(wmOperatorType *ot)
635 ot->name= "Add Text";
636 ot->description = "Add a text object to the scene";
637 ot->idname= "OBJECT_OT_text_add";
640 ot->exec= object_add_text_exec;
641 ot->poll= ED_operator_scene_editable;
644 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
647 static int object_armature_add_exec(bContext *C, wmOperator *op)
649 Object *obedit= CTX_data_edit_object(C);
650 View3D *v3d= CTX_wm_view3d(C);
651 RegionView3D *rv3d= NULL;
654 if ((obedit==NULL) || (obedit->type != OB_ARMATURE)) {
655 object_add_type(C, OB_ARMATURE);
656 ED_object_enter_editmode(C, 0);
659 else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
662 rv3d= CTX_wm_region(C)->regiondata;
664 /* v3d and rv3d are allowed to be NULL */
665 add_primitive_bone(CTX_data_scene(C), v3d, rv3d);
668 if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
669 ED_object_exit_editmode(C, EM_FREEDATA);
672 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
674 return OPERATOR_FINISHED;
677 void OBJECT_OT_armature_add(wmOperatorType *ot)
680 ot->name= "Add Armature";
681 ot->description = "Add an armature object to the scene.";
682 ot->idname= "OBJECT_OT_armature_add";
685 ot->exec= object_armature_add_exec;
686 ot->poll= ED_operator_scene_editable;
689 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
692 static int object_primitive_add_invoke(bContext *C, wmOperator *op, wmEvent *event)
694 uiPopupMenu *pup= uiPupMenuBegin(C, "Add Object", 0);
695 uiLayout *layout= uiPupMenuLayout(pup);
697 uiItemMenuEnumO(layout, "Mesh", ICON_OUTLINER_OB_MESH, "OBJECT_OT_mesh_add", "type");
698 uiItemMenuEnumO(layout, "Curve", ICON_OUTLINER_OB_CURVE, "OBJECT_OT_curve_add", "type");
699 uiItemMenuEnumO(layout, "Surface", ICON_OUTLINER_OB_SURFACE, "OBJECT_OT_surface_add", "type");
700 uiItemMenuEnumO(layout, NULL, ICON_OUTLINER_OB_META, "OBJECT_OT_metaball_add", "type");
701 uiItemO(layout, "Text", ICON_OUTLINER_OB_FONT, "OBJECT_OT_text_add");
703 uiItemO(layout, "Armature", ICON_OUTLINER_OB_ARMATURE, "OBJECT_OT_armature_add");
704 uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_LATTICE, "OBJECT_OT_object_add", "type", OB_LATTICE);
705 uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_EMPTY, "OBJECT_OT_object_add", "type", OB_EMPTY);
707 uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_CAMERA, "OBJECT_OT_object_add", "type", OB_CAMERA);
708 uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_LAMP, "OBJECT_OT_object_add", "type", OB_LAMP);
710 uiPupMenuEnd(C, pup);
712 /* this operator is only for a menu, not used further */
713 return OPERATOR_CANCELLED;
716 /* only used as menu */
717 void OBJECT_OT_primitive_add(wmOperatorType *ot)
720 ot->name= "Add Primitive";
721 ot->description = "Add a primitive object.";
722 ot->idname= "OBJECT_OT_primitive_add";
725 ot->invoke= object_primitive_add_invoke;
727 ot->poll= ED_operator_scene_editable;
734 /* ******************************* */
736 /* remove base from a specific scene */
737 /* note: now unlinks constraints as well */
738 void ED_base_object_free_and_unlink(Scene *scene, Base *base)
740 BLI_remlink(&scene->base, base);
741 free_libblock_us(&G.main->object, base->object);
742 if(scene->basact==base) scene->basact= NULL;
746 static int object_delete_exec(bContext *C, wmOperator *op)
748 Scene *scene= CTX_data_scene(C);
751 if(CTX_data_edit_object(C))
752 return OPERATOR_CANCELLED;
754 ED_view3d_exit_paint_modes(C);
756 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
758 if(base->object->type==OB_LAMP) islamp= 1;
760 /* remove from current scene only */
761 ED_base_object_free_and_unlink(scene, base);
765 if(islamp) reshadeall_displist(scene); /* only frees displist */
767 DAG_scene_sort(scene);
768 ED_anim_dag_flush_update(C);
770 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, CTX_data_scene(C));
772 return OPERATOR_FINISHED;
775 void OBJECT_OT_delete(wmOperatorType *ot)
780 ot->description = "Delete selected objects.";
781 ot->idname= "OBJECT_OT_delete";
784 ot->invoke= WM_operator_confirm;
785 ot->exec= object_delete_exec;
786 ot->poll= ED_operator_scene_editable;
789 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
794 static void single_object_users__forwardModifierLinks(void *userData, Object *ob, Object **obpoin)
799 static void copy_object__forwardModifierLinks(void *userData, Object *ob,
802 /* this is copied from ID_NEW; it might be better to have a macro */
803 if(*idpoin && (*idpoin)->newid) *idpoin = (*idpoin)->newid;
807 /* after copying objects, copied data should get new pointers */
808 static void copy_object_set_idnew(Scene *scene, View3D *v3d, int dupflag)
814 #if 0 // XXX old animation system
817 #endif // XXX old animation system
820 /* XXX check object pointers */
821 for(base= FIRSTBASE; base; base= base->next) {
822 if(TESTBASELIB_BGMODE(v3d, base)) {
824 relink_constraints(&ob->constraints);
827 for (chan = ob->pose->chanbase.first; chan; chan=chan->next){
828 relink_constraints(&chan->constraints);
831 modifiers_foreachIDLink(ob, copy_object__forwardModifierLinks, NULL);
835 ID_NEW(ob->proxy_group);
837 #if 0 // XXX old animation system
838 for(strip= ob->nlastrips.first; strip; strip= strip->next) {
839 bActionModifier *amod;
840 for(amod= strip->modifiers.first; amod; amod= amod->next)
843 #endif // XXX old animation system
848 if( dupflag & USER_DUP_MAT) {
849 mao= G.main->mat.first;
853 ma= (Material *)mao->id.newid;
855 if(dupflag & USER_DUP_TEX) {
856 for(a=0; a<MAX_MTEX; a++) {
858 id= (ID *)ma->mtex[a]->tex;
860 ID_NEW_US(ma->mtex[a]->tex)
861 else ma->mtex[a]->tex= copy_texture(ma->mtex[a]->tex);
867 #if 0 // XXX old animation system
871 else ma->ipo= copy_ipo(ma->ipo);
874 #endif // XXX old animation system
880 #if 0 // XXX old animation system
882 if( dupflag & USER_DUP_IPO) {
883 Lamp *la= G.main->lamp.first;
886 Lamp *lan= (Lamp *)la->id.newid;
890 else lan->ipo= copy_ipo(lan->ipo);
899 ipo= G.main->ipo.first;
901 if(ipo->id.lib==NULL && ipo->id.newid) {
902 Ipo *ipon= (Ipo *)ipo->id.newid;
904 for(icu= ipon->curve.first; icu; icu= icu->next) {
906 ID_NEW(icu->driver->ob);
912 #endif // XXX old animation system
920 static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float *cent)
923 int *index, nr, totvert=0;
925 for(eve= em->verts.first; eve; eve= eve->next) {
926 if(eve->f & SELECT) totvert++;
928 if(totvert==0) return 0;
930 *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
933 cent[0]= cent[1]= cent[2]= 0.0;
935 for(eve= em->verts.first; eve; eve= eve->next) {
936 if(eve->f & SELECT) {
938 VecAddf(cent, cent, eve->co);
943 VecMulf(cent, 1.0f/(float)totvert);
948 static int return_editmesh_vgroup(Object *obedit, EditMesh *em, char *name, float *cent)
954 cent[0]= cent[1]= cent[2]= 0.0;
958 /* find the vertices */
959 for(eve= em->verts.first; eve; eve= eve->next) {
960 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
963 for(i=0; i<dvert->totweight; i++){
964 if(dvert->dw[i].def_nr == (obedit->actdef-1)) {
966 VecAddf(cent, cent, eve->co);
972 bDeformGroup *defGroup = BLI_findlink(&obedit->defbase, obedit->actdef-1);
973 strcpy(name, defGroup->name);
974 VecMulf(cent, 1.0f/(float)totvert);
982 static void select_editmesh_hook(Object *ob, HookModifierData *hmd)
985 EditMesh *em= BKE_mesh_get_editmesh(me);
989 for(eve= em->verts.first; eve; eve= eve->next, nr++) {
990 if(nr==hmd->indexar[index]) {
992 if(index < hmd->totindex-1) index++;
997 BKE_mesh_end_editmesh(me, em);
1000 static int return_editlattice_indexar(Lattice *editlatt, int *tot, int **indexar, float *cent)
1003 int *index, nr, totvert=0, a;
1006 a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
1009 if(bp->f1 & SELECT) {
1010 if(bp->hide==0) 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 a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
1025 if(bp->f1 & SELECT) {
1027 *index= nr; index++;
1028 VecAddf(cent, cent, bp->vec);
1035 VecMulf(cent, 1.0f/(float)totvert);
1040 static void select_editlattice_hook(Object *obedit, HookModifierData *hmd)
1042 Lattice *lt= obedit->data;
1044 int index=0, nr=0, a;
1047 a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
1048 bp= lt->editlatt->def;
1050 if(hmd->indexar[index]==nr) {
1052 if(index < hmd->totindex-1) index++;
1059 static int return_editcurve_indexar(Object *obedit, int *tot, int **indexar, float *cent)
1061 ListBase *editnurb= curve_get_editcurve(obedit);
1065 int *index, a, nr, totvert=0;
1067 for(nu= editnurb->first; nu; nu= nu->next) {
1068 if((nu->type & 7)==CU_BEZIER) {
1072 if(bezt->f1 & SELECT) totvert++;
1073 if(bezt->f2 & SELECT) totvert++;
1074 if(bezt->f3 & SELECT) totvert++;
1080 a= nu->pntsu*nu->pntsv;
1082 if(bp->f1 & SELECT) totvert++;
1087 if(totvert==0) return 0;
1089 *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
1092 cent[0]= cent[1]= cent[2]= 0.0;
1094 for(nu= editnurb->first; nu; nu= nu->next) {
1095 if((nu->type & 7)==CU_BEZIER) {
1099 if(bezt->f1 & SELECT) {
1100 *index= nr; index++;
1101 VecAddf(cent, cent, bezt->vec[0]);
1104 if(bezt->f2 & SELECT) {
1105 *index= nr; index++;
1106 VecAddf(cent, cent, bezt->vec[1]);
1109 if(bezt->f3 & SELECT) {
1110 *index= nr; index++;
1111 VecAddf(cent, cent, bezt->vec[2]);
1119 a= nu->pntsu*nu->pntsv;
1121 if(bp->f1 & SELECT) {
1122 *index= nr; index++;
1123 VecAddf(cent, cent, bp->vec);
1131 VecMulf(cent, 1.0f/(float)totvert);
1136 void ED_object_apply_obmat(Object *ob)
1138 float mat[3][3], imat[3][3], tmat[3][3];
1140 /* from obmat to loc rot size */
1142 if(ob==NULL) return;
1143 Mat3CpyMat4(mat, ob->obmat);
1145 VECCOPY(ob->loc, ob->obmat[3]);
1147 Mat3ToEul(mat, ob->rot);
1148 EulToMat3(ob->rot, tmat);
1150 Mat3Inv(imat, tmat);
1152 Mat3MulMat3(tmat, imat, mat);
1154 ob->size[0]= tmat[0][0];
1155 ob->size[1]= tmat[1][1];
1156 ob->size[2]= tmat[2][2];
1160 int hook_getIndexArray(Object *obedit, int *tot, int **indexar, char *name, float *cent_r)
1166 switch(obedit->type) {
1169 Mesh *me= obedit->data;
1170 EditMesh *em = BKE_mesh_get_editmesh(me);
1172 /* check selected vertices first */
1173 if( return_editmesh_indexar(em, tot, indexar, cent_r)) {
1174 BKE_mesh_end_editmesh(me, em);
1177 int ret = return_editmesh_vgroup(obedit, em, name, cent_r);
1178 BKE_mesh_end_editmesh(me, em);
1184 return return_editcurve_indexar(obedit, tot, indexar, cent_r);
1187 Lattice *lt= obedit->data;
1188 return return_editlattice_indexar(lt->editlatt, tot, indexar, cent_r);
1195 static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
1197 ListBase *editnurb= curve_get_editcurve(obedit);
1201 int index=0, a, nr=0;
1203 for(nu= editnurb->first; nu; nu= nu->next) {
1204 if((nu->type & 7)==CU_BEZIER) {
1208 if(nr == hmd->indexar[index]) {
1210 if(index<hmd->totindex-1) index++;
1213 if(nr == hmd->indexar[index]) {
1215 if(index<hmd->totindex-1) index++;
1218 if(nr == hmd->indexar[index]) {
1220 if(index<hmd->totindex-1) index++;
1229 a= nu->pntsu*nu->pntsv;
1231 if(nr == hmd->indexar[index]) {
1233 if(index<hmd->totindex-1) index++;
1242 void obedit_hook_select(Object *ob, HookModifierData *hmd)
1245 if(ob->type==OB_MESH) select_editmesh_hook(ob, hmd);
1246 else if(ob->type==OB_LATTICE) select_editlattice_hook(ob, hmd);
1247 else if(ob->type==OB_CURVE) select_editcurve_hook(ob, hmd);
1248 else if(ob->type==OB_SURF) select_editcurve_hook(ob, hmd);
1252 void add_hook(Scene *scene, View3D *v3d, int mode)
1254 ModifierData *md = NULL;
1255 HookModifierData *hmd = NULL;
1257 Object *obedit= scene->obedit; // XXX get from context
1259 if(obedit==NULL) return;
1262 if(mode==2) { /* selected object */
1264 for(base= FIRSTBASE; base; base= base->next) {
1265 if(TESTBASELIB(v3d, base)) {
1273 error("Requires selected Object");
1278 int maxlen=0, a, nr;
1281 /* make pupmenu with hooks */
1282 for(md=obedit->modifiers.first; md; md= md->next) {
1283 if (md->type==eModifierType_Hook)
1288 error("Object has no hooks yet");
1292 cp= MEM_callocN(maxlen+32, "temp string");
1293 if(mode==3) strcpy(cp, "Remove %t|");
1294 else if(mode==4) strcpy(cp, "Reassign %t|");
1295 else if(mode==5) strcpy(cp, "Select %t|");
1296 else if(mode==6) strcpy(cp, "Clear Offset %t|");
1298 for(md=obedit->modifiers.first; md; md= md->next) {
1299 if (md->type==eModifierType_Hook) {
1300 strcat(cp, md->name);
1311 for(md=obedit->modifiers.first; md; md=md->next) {
1312 if (md->type==eModifierType_Hook) {
1318 hmd = (HookModifierData*) md;
1322 /* do it, new hooks or reassign */
1323 if(mode==1 || mode==2 || mode==4) {
1325 int tot, ok, *indexar;
1328 ok = hook_getIndexArray(obedit, &tot, &indexar, name, cent);
1331 error("Requires selected vertices or active Vertex Group");
1336 Base *base= BASACT, *newbase;
1338 ob= add_object(scene, OB_EMPTY);
1341 newbase->lay= base->lay;
1342 ob->lay= newbase->lay;
1344 /* transform cent to global coords for loc */
1345 VecMat4MulVecfl(ob->loc, obedit->obmat, cent);
1347 /* restore, add_object sets active */
1350 /* if mode is 2 or 4, ob has been set */
1353 if(mode==1 || mode==2) {
1354 ModifierData *md = obedit->modifiers.first;
1356 while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
1360 hmd = (HookModifierData*) modifier_new(eModifierType_Hook);
1361 BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
1362 sprintf(hmd->modifier.name, "Hook-%s", ob->id.name+2);
1364 else if (hmd->indexar) MEM_freeN(hmd->indexar); /* reassign, hook was set */
1367 hmd->indexar= indexar;
1368 VECCOPY(hmd->cent, cent);
1370 BLI_strncpy(hmd->name, name, 32);
1372 if(mode==1 || mode==2) {
1373 /* matrix calculus */
1374 /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
1377 where_is_object(scene, ob);
1379 Mat4Invert(ob->imat, ob->obmat);
1380 /* apparently this call goes from right to left... */
1381 Mat4MulSerie(hmd->parentinv, ob->imat, obedit->obmat, NULL,
1382 NULL, NULL, NULL, NULL, NULL);
1386 else if(mode==3) { /* remove */
1387 BLI_remlink(&obedit->modifiers, md);
1390 else if(mode==5) { /* select */
1391 obedit_hook_select(obedit, hmd);
1393 else if(mode==6) { /* clear offset */
1394 where_is_object(scene, ob); /* ob is hook->parent */
1396 Mat4Invert(ob->imat, ob->obmat);
1397 /* this call goes from right to left... */
1398 Mat4MulSerie(hmd->parentinv, ob->imat, obedit->obmat, NULL,
1399 NULL, NULL, NULL, NULL, NULL);
1402 DAG_scene_sort(scene);
1406 /* use this when the loc/size/rot of the parent has changed but the children should stay in the same place
1407 * apply-size-rot or object center for eg */
1408 static void ignore_parent_tx(Scene *scene, Object *ob )
1413 /* a change was made, adjust the children to compensate */
1414 for (ob_child=G.main->object.first; ob_child; ob_child=ob_child->id.next) {
1415 if (ob_child->parent == ob) {
1416 ED_object_apply_obmat(ob_child);
1417 what_does_parent(scene, ob_child, &workob);
1418 Mat4Invert(ob_child->parentinv, workob.obmat);
1424 void add_hook_menu(Scene *scene, View3D *v3d)
1426 Object *obedit= scene->obedit; // XXX get from context
1429 if(obedit==NULL) return;
1431 if(modifiers_findByType(obedit, eModifierType_Hook))
1432 mode= pupmenu("Hooks %t|Add, To New Empty %x1|Add, To Selected Object %x2|Remove... %x3|Reassign... %x4|Select... %x5|Clear Offset...%x6");
1434 mode= pupmenu("Hooks %t|Add, New Empty %x1|Add, To Selected Object %x2");
1439 add_hook(scene, v3d, mode);
1442 /* ******************** clear parent operator ******************* */
1444 static EnumPropertyItem prop_clear_parent_types[] = {
1445 {0, "CLEAR", 0, "Clear Parent", ""},
1446 {1, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation (Clear Track)", ""},
1447 {2, "CLEAR_INVERSE", 0, "Clear Parent Inverse", ""},
1448 {0, NULL, 0, NULL, NULL}
1451 /* note, poll should check for editable scene */
1452 static int parent_clear_exec(bContext *C, wmOperator *op)
1454 int type= RNA_enum_get(op->ptr, "type");
1456 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1461 else if(type == 1) {
1464 ED_object_apply_obmat(ob);
1467 Mat4One(ob->parentinv);
1469 ob->recalc |= OB_RECALC;
1473 DAG_scene_sort(CTX_data_scene(C));
1474 ED_anim_dag_flush_update(C);
1475 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
1477 return OPERATOR_FINISHED;
1480 void OBJECT_OT_parent_clear(wmOperatorType *ot)
1483 ot->name= "Clear Parent";
1484 ot->description = "Clear the object's parenting.";
1485 ot->idname= "OBJECT_OT_parent_clear";
1488 ot->invoke= WM_menu_invoke;
1489 ot->exec= parent_clear_exec;
1491 ot->poll= ED_operator_object_active;
1494 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1496 RNA_def_enum(ot->srna, "type", prop_clear_parent_types, 0, "Type", "");
1499 /* ******************** clear track operator ******************* */
1502 static EnumPropertyItem prop_clear_track_types[] = {
1503 {0, "CLEAR", 0, "Clear Track", ""},
1504 {1, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation (Clear Track)", ""},
1505 {0, NULL, 0, NULL, NULL}
1508 /* note, poll should check for editable scene */
1509 static int object_track_clear_exec(bContext *C, wmOperator *op)
1511 int type= RNA_enum_get(op->ptr, "type");
1513 if(CTX_data_edit_object(C)) {
1514 BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in EditMode");
1515 return OPERATOR_CANCELLED;
1517 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1519 ob->recalc |= OB_RECALC;
1522 ED_object_apply_obmat(ob);
1526 DAG_scene_sort(CTX_data_scene(C));
1527 ED_anim_dag_flush_update(C);
1529 return OPERATOR_FINISHED;
1532 void OBJECT_OT_track_clear(wmOperatorType *ot)
1535 ot->name= "Clear track";
1536 ot->description = "Clear tracking constraint or flag from object.";
1537 ot->idname= "OBJECT_OT_track_clear";
1540 ot->invoke= WM_menu_invoke;
1541 ot->exec= object_track_clear_exec;
1543 ot->poll= ED_operator_scene_editable;
1546 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1548 RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
1551 /* *****************Selection Operators******************* */
1552 static EnumPropertyItem prop_select_types[] = {
1553 {0, "EXCLUSIVE", 0, "Exclusive", ""},
1554 {1, "EXTEND", 0, "Extend", ""},
1555 {0, NULL, 0, NULL, NULL}
1558 /* ****** Select by Type ****** */
1560 static int object_select_by_type_exec(bContext *C, wmOperator *op)
1562 short obtype, seltype;
1564 obtype = RNA_enum_get(op->ptr, "type");
1565 seltype = RNA_enum_get(op->ptr, "seltype");
1568 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1569 ED_base_object_select(base, BA_DESELECT);
1574 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1575 if(base->object->type==obtype) {
1576 ED_base_object_select(base, BA_SELECT);
1581 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
1583 return OPERATOR_FINISHED;
1586 void OBJECT_OT_select_by_type(wmOperatorType *ot)
1589 ot->name= "Select By Type";
1590 ot->description = "Select all visible objects that are of a type.";
1591 ot->idname= "OBJECT_OT_select_by_type";
1594 ot->invoke= WM_menu_invoke;
1595 ot->exec= object_select_by_type_exec;
1596 ot->poll= ED_operator_scene_editable;
1599 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1601 RNA_def_enum(ot->srna, "seltype", prop_select_types, 0, "Selection", "Extend selection or clear selection then select");
1602 RNA_def_enum(ot->srna, "type", prop_object_types, 1, "Type", "");
1605 /* ****** selection by links *******/
1607 static EnumPropertyItem prop_select_linked_types[] = {
1608 {1, "IPO", 0, "Object IPO", ""}, // XXX depreceated animation system stuff...
1609 {2, "OBDATA", 0, "Ob Data", ""},
1610 {3, "MATERIAL", 0, "Material", ""},
1611 {4, "TEXTURE", 0, "Texture", ""},
1612 {5, "DUPGROUP", 0, "Dupligroup", ""},
1613 {6, "PARTICLE", 0, "Particle System", ""},
1614 {0, NULL, 0, NULL, NULL}
1617 static int object_select_linked_exec(bContext *C, wmOperator *op)
1619 Scene *scene= CTX_data_scene(C);
1621 void *obdata = NULL;
1622 Material *mat = NULL, *mat1;
1625 int nr = RNA_enum_get(op->ptr, "type");
1626 short changed = 0, seltype;
1630 * Current Material: 3
1631 * Current Texture: 4
1636 seltype = RNA_enum_get(op->ptr, "seltype");
1639 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1640 ED_base_object_select(base, BA_DESELECT);
1647 BKE_report(op->reports, RPT_ERROR, "No Active Object");
1648 return OPERATOR_CANCELLED;
1652 // XXX old animation system
1654 //if(ipo==0) return OPERATOR_CANCELLED;
1655 return OPERATOR_CANCELLED;
1658 if(ob->data==0) return OPERATOR_CANCELLED;
1661 else if(nr==3 || nr==4) {
1662 mat= give_current_material(ob, ob->actcol);
1663 if(mat==0) return OPERATOR_CANCELLED;
1665 if(mat->mtex[ (int)mat->texact ]) tex= mat->mtex[ (int)mat->texact ]->tex;
1666 if(tex==0) return OPERATOR_CANCELLED;
1670 if(ob->dup_group==NULL) return OPERATOR_CANCELLED;
1673 if(ob->particlesystem.first==NULL) return OPERATOR_CANCELLED;
1675 else return OPERATOR_CANCELLED;
1677 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1679 // XXX old animation system
1680 //if(base->object->ipo==ipo) base->flag |= SELECT;
1684 if(base->object->data==obdata) base->flag |= SELECT;
1687 else if(nr==3 || nr==4) {
1690 for(a=1; a<=ob->totcol; a++) {
1691 mat1= give_current_material(ob, a);
1693 if(mat1==mat) base->flag |= SELECT;
1696 else if(mat1 && nr==4) {
1697 for(b=0; b<MAX_MTEX; b++) {
1699 if(tex==mat1->mtex[b]->tex) {
1700 base->flag |= SELECT;
1710 if(base->object->dup_group==ob->dup_group) {
1711 base->flag |= SELECT;
1716 /* loop through other, then actives particles*/
1717 ParticleSystem *psys;
1718 ParticleSystem *psys_act;
1720 for(psys=base->object->particlesystem.first; psys; psys=psys->next) {
1721 for(psys_act=ob->particlesystem.first; psys_act; psys_act=psys_act->next) {
1722 if (psys->part == psys_act->part) {
1723 base->flag |= SELECT;
1729 if (base->flag & SELECT) {
1734 base->object->flag= base->flag;
1739 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
1740 return OPERATOR_FINISHED;
1743 return OPERATOR_CANCELLED;
1746 void OBJECT_OT_select_linked(wmOperatorType *ot)
1749 ot->name= "Select Linked";
1750 ot->description = "Select all visible objects that are linked.";
1751 ot->idname= "OBJECT_OT_select_linked";
1754 ot->invoke= WM_menu_invoke;
1755 ot->exec= object_select_linked_exec;
1756 ot->poll= ED_operator_scene_editable;
1759 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1761 RNA_def_enum(ot->srna, "type", prop_select_linked_types, 0, "Type", "");
1762 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
1766 /* ****** selection grouped *******/
1768 static EnumPropertyItem prop_select_grouped_types[] = {
1769 {1, "CHILDREN_RECURSIVE", 0, "Children", ""}, // XXX depreceated animation system stuff...
1770 {2, "CHILDREN", 0, "Immediate Children", ""},
1771 {3, "PARENT", 0, "Parent", ""},
1772 {4, "SIBLINGS", 0, "Siblings", "Shared Parent"},
1773 {5, "TYPE", 0, "Type", "Shared object type"},
1774 {6, "LAYER", 0, "Layer", "Shared layers"},
1775 {7, "GROUP", 0, "Group", "Shared group"},
1776 {8, "HOOK", 0, "Hook", ""},
1777 {9, "PASS", 0, "Pass", "Render pass Index"},
1778 {10, "COLOR", 0, "Color", "Object Color"},
1779 {11, "PROPERTIES", 0, "Properties", "Game Properties"},
1780 {0, NULL, 0, NULL, NULL}
1784 static short select_grouped_children(bContext *C, Object *ob, int recursive)
1788 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1789 if (ob == base->object->parent) {
1790 if (!(base->flag & SELECT)) {
1791 ED_base_object_select(base, BA_SELECT);
1796 changed |= select_grouped_children(C, base->object, 1);
1803 static short select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */
1805 Scene *scene= CTX_data_scene(C);
1806 View3D *v3d= CTX_wm_view3d(C);
1809 Base *baspar, *basact= CTX_data_active_base(C);
1811 if (!basact || !(basact->object->parent)) return 0; /* we know OBACT is valid */
1813 baspar= object_in_scene(basact->object->parent, scene);
1815 /* can be NULL if parent in other scene */
1816 if(baspar && BASE_SELECTABLE(v3d, baspar)) {
1817 ED_base_object_select(basact, BA_DESELECT);
1818 ED_base_object_select(baspar, BA_SELECT);
1819 ED_base_object_activate(C, baspar);
1826 #define GROUP_MENU_MAX 24
1827 static short select_grouped_group(bContext *C, Object *ob) /* Select objects in the same group as the active */
1830 Group *group, *ob_groups[GROUP_MENU_MAX];
1831 //char str[10 + (24*GROUP_MENU_MAX)];
1833 int group_count=0; //, menu, i;
1835 for ( group=G.main->group.first;
1836 group && group_count < GROUP_MENU_MAX;
1837 group=group->id.next
1839 if (object_in_group (ob, group)) {
1840 ob_groups[group_count] = group;
1848 else if (group_count == 1) {
1849 group = ob_groups[0];
1850 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1851 if (!(base->flag & SELECT) && object_in_group(base->object, group)) {
1852 ED_base_object_select(base, BA_SELECT);
1859 #if 0 // XXX hows this work in 2.5?
1860 /* build the menu. */
1861 p += sprintf(str, "Groups%%t");
1862 for (i=0; i<group_count; i++) {
1863 group = ob_groups[i];
1864 p += sprintf (p, "|%s%%x%i", group->id.name+2, i);
1867 menu = pupmenu (str);
1871 group = ob_groups[menu];
1872 for (base= FIRSTBASE; base; base= base->next) {
1873 if (!(base->flag & SELECT) && object_in_group(base->object, group)) {
1874 ED_base_object_select(base, BA_SELECT);
1882 static short select_grouped_object_hooks(bContext *C, Object *ob)
1884 Scene *scene= CTX_data_scene(C);
1885 View3D *v3d= CTX_wm_view3d(C);
1890 HookModifierData *hmd;
1892 for (md = ob->modifiers.first; md; md=md->next) {
1893 if (md->type==eModifierType_Hook) {
1894 hmd= (HookModifierData*) md;
1895 if (hmd->object && !(hmd->object->flag & SELECT)) {
1896 base= object_in_scene(hmd->object, scene);
1897 if (base && (BASE_SELECTABLE(v3d, base))) {
1898 ED_base_object_select(base, BA_SELECT);
1907 /* Select objects woth the same parent as the active (siblings),
1908 * parent can be NULL also */
1909 static short select_grouped_siblings(bContext *C, Object *ob)
1913 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1914 if ((base->object->parent==ob->parent) && !(base->flag & SELECT)) {
1915 ED_base_object_select(base, BA_SELECT);
1923 static short select_grouped_type(bContext *C, Object *ob)
1927 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1928 if ((base->object->type == ob->type) && !(base->flag & SELECT)) {
1929 ED_base_object_select(base, BA_SELECT);
1937 static short select_grouped_layer(bContext *C, Object *ob)
1941 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1942 if ((base->lay & ob->lay) && !(base->flag & SELECT)) {
1943 ED_base_object_select(base, BA_SELECT);
1951 static short select_grouped_index_object(bContext *C, Object *ob)
1955 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1956 if ((base->object->index == ob->index) && !(base->flag & SELECT)) {
1957 ED_base_object_select(base, BA_SELECT);
1965 static short select_grouped_color(bContext *C, Object *ob)
1969 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1970 if (!(base->flag & SELECT) && (FloatCompare(base->object->col, ob->col, 0.005f))) {
1971 ED_base_object_select(base, BA_SELECT);
1979 static short objects_share_gameprop(Object *a, Object *b)
1982 /*make a copy of all its properties*/
1984 for( prop= a->prop.first; prop; prop = prop->next ) {
1985 if ( get_ob_property(b, prop->name) )
1991 static short select_grouped_gameprops(bContext *C, Object *ob)
1995 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1996 if (!(base->flag & SELECT) && (objects_share_gameprop(base->object, ob))) {
1997 ED_base_object_select(base, BA_SELECT);
2005 static int object_select_grouped_exec(bContext *C, wmOperator *op)
2007 Scene *scene= CTX_data_scene(C);
2009 int nr = RNA_enum_get(op->ptr, "type");
2010 short changed = 0, seltype;
2012 seltype = RNA_enum_get(op->ptr, "seltype");
2015 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2016 ED_base_object_select(base, BA_DESELECT);
2023 BKE_report(op->reports, RPT_ERROR, "No Active Object");
2024 return OPERATOR_CANCELLED;
2027 if(nr==1) changed = select_grouped_children(C, ob, 1);
2028 else if(nr==2) changed = select_grouped_children(C, ob, 0);
2029 else if(nr==3) changed = select_grouped_parent(C);
2030 else if(nr==4) changed = select_grouped_siblings(C, ob);
2031 else if(nr==5) changed = select_grouped_type(C, ob);
2032 else if(nr==6) changed = select_grouped_layer(C, ob);
2033 else if(nr==7) changed = select_grouped_group(C, ob);
2034 else if(nr==8) changed = select_grouped_object_hooks(C, ob);
2035 else if(nr==9) changed = select_grouped_index_object(C, ob);
2036 else if(nr==10) changed = select_grouped_color(C, ob);
2037 else if(nr==11) changed = select_grouped_gameprops(C, ob);
2040 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2041 return OPERATOR_FINISHED;
2044 return OPERATOR_CANCELLED;
2047 void OBJECT_OT_select_grouped(wmOperatorType *ot)
2050 ot->name= "Select Grouped";
2051 ot->description = "Select all visible objects grouped by various properties.";
2052 ot->idname= "OBJECT_OT_select_grouped";
2055 ot->invoke= WM_menu_invoke;
2056 ot->exec= object_select_grouped_exec;
2057 ot->poll= ED_operator_scene_editable;
2060 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2062 RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
2063 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
2067 /* ****** selection by layer *******/
2069 static int object_select_by_layer_exec(bContext *C, wmOperator *op)
2071 unsigned int layernum;
2074 seltype = RNA_enum_get(op->ptr, "seltype");
2075 layernum = RNA_int_get(op->ptr, "layer");
2078 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2079 ED_base_object_select(base, BA_DESELECT);
2084 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2085 if(base->lay == (1<< (layernum -1)))
2086 ED_base_object_select(base, BA_SELECT);
2091 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2093 return OPERATOR_FINISHED;
2096 void OBJECT_OT_select_by_layer(wmOperatorType *ot)
2099 ot->name= "select by layer";
2100 ot->description = "Select all visible objects on a layer.";
2101 ot->idname= "OBJECT_OT_select_by_layer";
2104 /*ot->invoke = XXX - need a int grid popup*/
2105 ot->exec= object_select_by_layer_exec;
2106 ot->poll= ED_operator_scene_editable;
2109 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2111 RNA_def_int(ot->srna, "layer", 1, 1, 20, "Layer", "", 1, 20);
2112 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
2115 /* ****** invert selection *******/
2116 static int object_select_inverse_exec(bContext *C, wmOperator *op)
2118 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2119 if (base->flag & SELECT)
2120 ED_base_object_select(base, BA_DESELECT);
2122 ED_base_object_select(base, BA_SELECT);
2127 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2129 return OPERATOR_FINISHED;
2132 void OBJECT_OT_select_inverse(wmOperatorType *ot)
2136 ot->name= "Select Inverse";
2137 ot->description = "Invert selection of all visible objects.";
2138 ot->idname= "OBJECT_OT_select_inverse";
2141 ot->exec= object_select_inverse_exec;
2142 ot->poll= ED_operator_scene_editable;
2145 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2148 /* ****** (de)select All *******/
2150 static int object_select_de_select_all_exec(bContext *C, wmOperator *op)
2155 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2156 if (base->flag & SELECT) {
2164 if (!ok) return OPERATOR_PASS_THROUGH;
2166 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2167 if (a) ED_base_object_select(base, BA_DESELECT);
2168 else ED_base_object_select(base, BA_SELECT);
2173 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2175 return OPERATOR_FINISHED;
2178 void OBJECT_OT_select_all_toggle(wmOperatorType *ot)
2182 ot->name= "deselect all";
2183 ot->description = "(de)select all visible objects in scene.";
2184 ot->idname= "OBJECT_OT_select_all_toggle";
2187 ot->exec= object_select_de_select_all_exec;
2188 ot->poll= ED_operator_scene_editable;
2191 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2194 /* ****** random selection *******/
2196 static int object_select_random_exec(bContext *C, wmOperator *op)
2201 seltype = RNA_enum_get(op->ptr, "seltype");
2204 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2205 ED_base_object_select(base, BA_DESELECT);
2209 percent = RNA_float_get(op->ptr, "percent");
2211 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2212 if (BLI_frand() < percent) {
2213 ED_base_object_select(base, BA_SELECT);
2218 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2220 return OPERATOR_FINISHED;
2223 void OBJECT_OT_select_random(wmOperatorType *ot)
2226 ot->name= "Random select";
2227 ot->description = "Set select on random visible objects.";
2228 ot->idname= "OBJECT_OT_select_random";
2231 /*ot->invoke= object_select_random_invoke XXX - need a number popup ;*/
2232 ot->exec = object_select_random_exec;
2233 ot->poll= ED_operator_scene_editable;
2236 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2238 RNA_def_float_percentage(ot->srna, "percent", 0.5f, 0.0f, 1.0f, "Percent", "percentage of objects to randomly select", 0.0001f, 1.0f);
2239 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
2242 /* ******** Clear object Translation *********** */
2244 static int object_location_clear_exec(bContext *C, wmOperator *op)
2246 int armature_clear= 0;
2248 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2249 if((G.f & G_WEIGHTPAINT)==0) {
2250 if ((ob->protectflag & OB_LOCK_LOCX)==0)
2251 ob->loc[0]= ob->dloc[0]= 0.0f;
2252 if ((ob->protectflag & OB_LOCK_LOCY)==0)
2253 ob->loc[1]= ob->dloc[1]= 0.0f;
2254 if ((ob->protectflag & OB_LOCK_LOCZ)==0)
2255 ob->loc[2]= ob->dloc[2]= 0.0f;
2257 ob->recalc |= OB_RECALC_OB;
2261 if(armature_clear==0) /* in this case flush was done */
2262 ED_anim_dag_flush_update(C);
2264 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2266 return OPERATOR_FINISHED;
2270 void OBJECT_OT_location_clear(wmOperatorType *ot)
2274 ot->name= "Clear Location";
2275 ot->description = "Clear the object's location.";
2276 ot->idname= "OBJECT_OT_location_clear";
2279 ot->invoke= WM_operator_confirm;
2280 ot->exec= object_location_clear_exec;
2281 ot->poll= ED_operator_object_active;
2284 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2287 static int object_rotation_clear_exec(bContext *C, wmOperator *op)
2289 int armature_clear= 0;
2291 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2292 if((G.f & G_WEIGHTPAINT)==0) {
2293 /* eulers can only get cleared if they are not protected */
2294 if ((ob->protectflag & OB_LOCK_ROTX)==0)
2295 ob->rot[0]= ob->drot[0]= 0.0f;
2296 if ((ob->protectflag & OB_LOCK_ROTY)==0)
2297 ob->rot[1]= ob->drot[1]= 0.0f;
2298 if ((ob->protectflag & OB_LOCK_ROTZ)==0)
2299 ob->rot[2]= ob->drot[2]= 0.0f;
2301 ob->recalc |= OB_RECALC_OB;
2305 if(armature_clear==0) /* in this case flush was done */
2306 ED_anim_dag_flush_update(C);
2308 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2310 return OPERATOR_FINISHED;
2314 void OBJECT_OT_rotation_clear(wmOperatorType *ot)
2318 ot->name= "Clear Rotation";
2319 ot->description = "Clear the object's rotation.";
2320 ot->idname= "OBJECT_OT_rotation_clear";
2323 ot->invoke= WM_operator_confirm;
2324 ot->exec= object_rotation_clear_exec;
2325 ot->poll= ED_operator_object_active;
2328 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2331 static int object_scale_clear_exec(bContext *C, wmOperator *op)
2333 int armature_clear= 0;
2335 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2336 if((G.f & G_WEIGHTPAINT)==0) {
2337 if ((ob->protectflag & OB_LOCK_SCALEX)==0) {
2341 if ((ob->protectflag & OB_LOCK_SCALEY)==0) {
2345 if ((ob->protectflag & OB_LOCK_SCALEZ)==0) {
2350 ob->recalc |= OB_RECALC_OB;
2354 if(armature_clear==0) /* in this case flush was done */
2355 ED_anim_dag_flush_update(C);
2357 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2359 return OPERATOR_FINISHED;
2362 void OBJECT_OT_scale_clear(wmOperatorType *ot)
2366 ot->name= "Clear Scale";
2367 ot->description = "Clear the object's scale.";
2368 ot->idname= "OBJECT_OT_scale_clear";
2371 ot->invoke= WM_operator_confirm;
2372 ot->exec= object_scale_clear_exec;
2373 ot->poll= ED_operator_object_active;
2376 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2379 static int object_origin_clear_exec(bContext *C, wmOperator *op)
2381 float *v1, *v3, mat[3][3];
2382 int armature_clear= 0;
2384 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2387 v3= ob->parentinv[3];
2389 Mat3CpyMat4(mat, ob->parentinv);
2394 Mat3MulVecfl(mat, v3);
2396 ob->recalc |= OB_RECALC_OB;
2400 if(armature_clear==0) /* in this case flush was done */
2401 ED_anim_dag_flush_update(C);
2403 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2405 return OPERATOR_FINISHED;
2408 void OBJECT_OT_origin_clear(wmOperatorType *ot)
2412 ot->name= "Clear Origin";
2413 ot->description = "Clear the object's origin.";
2414 ot->idname= "OBJECT_OT_origin_clear";
2417 ot->invoke= WM_operator_confirm;
2418 ot->exec= object_origin_clear_exec;
2419 ot->poll= ED_operator_object_active;
2422 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2425 /* ********* clear/set restrict view *********/
2426 static int object_restrictview_clear_exec(bContext *C, wmOperator *op)
2428 ScrArea *sa= CTX_wm_area(C);
2429 View3D *v3d= sa->spacedata.first;
2430 Scene *scene= CTX_data_scene(C);
2434 /* XXX need a context loop to handle such cases */
2435 for(base = FIRSTBASE; base; base=base->next){
2436 if((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
2437 base->flag |= SELECT;
2438 base->object->flag = base->flag;
2439 base->object->restrictflag &= ~OB_RESTRICT_VIEW;
2444 DAG_scene_sort(scene);
2445 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
2448 return OPERATOR_FINISHED;
2451 void OBJECT_OT_restrictview_clear(wmOperatorType *ot)
2455 ot->name= "Clear Restrict View";
2456 ot->description = "Reveal the object by setting the restrictview flag.";
2457 ot->idname= "OBJECT_OT_restrictview_clear";
2460 ot->exec= object_restrictview_clear_exec;
2461 ot->poll= ED_operator_view3d_active;
2464 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2467 static int object_restrictview_set_exec(bContext *C, wmOperator *op)
2469 Scene *scene= CTX_data_scene(C);
2471 int unselected= RNA_boolean_get(op->ptr, "unselected");
2473 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2475 if (base->flag & SELECT){
2476 base->flag &= ~SELECT;
2477 base->object->flag = base->flag;
2478 base->object->restrictflag |= OB_RESTRICT_VIEW;
2481 ED_base_object_activate(C, NULL);
2486 if (!(base->flag & SELECT)){
2487 base->object->restrictflag |= OB_RESTRICT_VIEW;
2495 DAG_scene_sort(scene);
2497 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2501 return OPERATOR_FINISHED;
2504 void OBJECT_OT_restrictview_set(wmOperatorType *ot)
2507 ot->name= "Set Restrict View";
2508 ot->description = "Hide the object by setting the restrictview flag.";
2509 ot->idname= "OBJECT_OT_restrictview_set";
2512 ot->exec= object_restrictview_set_exec;
2513 ot->poll= ED_operator_view3d_active;
2516 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2518 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects.");
2521 /* ************* Slow Parent ******************* */
2522 static int object_slowparent_set_exec(bContext *C, wmOperator *op)
2525 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2527 if(base->object->parent) base->object->partype |= PARSLOW;
2528 base->object->recalc |= OB_RECALC_OB;
2533 ED_anim_dag_flush_update(C);
2535 WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
2537 return OPERATOR_FINISHED;
2540 void OBJECT_OT_slowparent_set(wmOperatorType *ot)
2544 ot->name= "Set Slow Parent";
2545 ot->description = "Set the object's slow parent.";
2546 ot->idname= "OBJECT_OT_slow_parent_set";
2549 ot->invoke= WM_operator_confirm;
2550 ot->exec= object_slowparent_set_exec;
2551 ot->poll= ED_operator_view3d_active;
2554 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2557 static int object_slowparent_clear_exec(bContext *C, wmOperator *op)
2559 Scene *scene= CTX_data_scene(C);
2561 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2562 if(base->object->parent) {
2563 if(base->object->partype & PARSLOW) {
2564 base->object->partype -= PARSLOW;
2565 where_is_object(scene, base->object);
2566 base->object->partype |= PARSLOW;
2567 base->object->recalc |= OB_RECALC_OB;
2574 ED_anim_dag_flush_update(C);
2576 WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
2578 return OPERATOR_FINISHED;
2581 void OBJECT_OT_slowparent_clear(wmOperatorType *ot)
2585 ot->name= "Clear Slow Parent";
2586 ot->description = "Clear the object's slow parent.";
2587 ot->idname= "OBJECT_OT_slow_parent_clear";
2590 ot->invoke= WM_operator_confirm;
2591 ot->exec= object_slowparent_clear_exec;
2592 ot->poll= ED_operator_view3d_active;
2595 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2597 /* ******************** **************** */
2600 #define BEZSELECTED_HIDDENHANDLES(bezt) ((G.f & G_HIDDENHANDLES) ? (bezt)->f2 & SELECT : BEZSELECTED(bezt))
2601 /* only in edit mode */
2602 void make_vertex_parent(Scene *scene, Object *obedit, View3D *v3d)
2610 int a, v1=0, v2=0, v3=0, v4=0, nr=1;
2612 /* we need 1 to 3 selected vertices */
2614 if(obedit->type==OB_MESH) {
2615 Mesh *me= obedit->data;
2616 EditMesh *em = BKE_mesh_get_editmesh(me);
2618 eve= em->verts.first;
2622 else if(v2==0) v2= nr;
2623 else if(v3==0) v3= nr;
2624 else if(v4==0) v4= nr;
2631 BKE_mesh_end_editmesh(me, em);
2633 else if(ELEM(obedit->type, OB_SURF, OB_CURVE)) {
2634 ListBase *editnurb= curve_get_editcurve(obedit);
2636 nu= editnurb->first;
2638 if((nu->type & 7)==CU_BEZIER) {
2642 if(BEZSELECTED_HIDDENHANDLES(bezt)) {
2644 else if(v2==0) v2= nr;
2645 else if(v3==0) v3= nr;
2646 else if(v4==0) v4= nr;
2655 a= nu->pntsu*nu->pntsv;
2657 if(bp->f1 & SELECT) {
2659 else if(v2==0) v2= nr;
2660 else if(v3==0) v3= nr;
2661 else if(v4==0) v4= nr;
2671 else if(obedit->type==OB_LATTICE) {
2672 Lattice *lt= obedit->data;
2674 a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
2675 bp= lt->editlatt->def;
2677 if(bp->f1 & SELECT) {
2679 else if(v2==0) v2= nr;
2680 else if(v3==0) v3= nr;
2681 else if(v4==0) v4= nr;
2689 if(v4 || !((v1 && v2==0 && v3==0) || (v1 && v2 && v3)) ) {
2690 error("Select either 1 or 3 vertices to parent to");
2694 if(okee("Make vertex parent")==0) return;
2696 for(base= FIRSTBASE; base; base= base->next) {
2697 if(TESTBASELIB(v3d, base)) {
2701 ob->recalc |= OB_RECALC;
2702 par= BASACT->object->parent;
2709 error("Loop in parents");
2714 ob->parent= BASACT->object;
2716 ob->partype= PARVERT3;
2721 /* inverse parent matrix */
2722 what_does_parent(scene, ob, &workob);
2723 Mat4Invert(ob->parentinv, workob.obmat);
2726 ob->partype= PARVERT1;
2729 /* inverse parent matrix */
2730 what_does_parent(scene, ob, &workob);
2731 Mat4Invert(ob->parentinv, workob.obmat);
2738 DAG_scene_sort(scene);
2742 /* ******************** make proxy operator *********************** */
2744 /* present menu listing the possible objects within the group to proxify */
2745 static void proxy_group_objects_menu (bContext *C, wmOperator *op, Object *ob, Group *group)
2752 /* check if there are any objects within the group to assign for */
2753 for (go= group->gobject.first; go; go= go->next) {
2758 /* now create the menu to draw */
2759 pup= uiPupMenuBegin(C, "Make Proxy For:", 0);
2760 layout= uiPupMenuLayout(pup);
2762 for (go= group->gobject.first; go; go= go->next) {
2764 PointerRNA props_ptr;
2766 /* create operator properties, and assign the relevant pointers to that,
2767 * and add a menu entry which uses these props
2769 WM_operator_properties_create(&props_ptr, op->idname);
2770 RNA_string_set(&props_ptr, "object", go->ob->id.name+2);
2771 RNA_string_set(&props_ptr, "group_object", go->ob->id.name+2);
2772 uiItemFullO(layout, go->ob->id.name+2, 0, op->idname, props_ptr.data, WM_OP_EXEC_REGION_WIN);
2776 /* display the menu, and be done */
2777 uiPupMenuEnd(C, pup);
2780 /* set the object to proxify */
2781 static int make_proxy_invoke (bContext *C, wmOperator *op, wmEvent *evt)
2783 Scene *scene= CTX_data_scene(C);
2784 Object *ob= CTX_data_active_object(C);
2787 if (!scene || scene->id.lib || !ob)
2788 return OPERATOR_CANCELLED;
2790 /* Get object to work on - use a menu if we need to... */
2791 if (ob->dup_group && ob->dup_group->id.lib) {
2792 /* gives menu with list of objects in group */
2793 proxy_group_objects_menu(C, op, ob, ob->dup_group);
2795 else if (ob->id.lib) {
2796 uiPopupMenu *pup= uiPupMenuBegin(C, "OK?", ICON_QUESTION);
2797 uiLayout *layout= uiPupMenuLayout(pup);
2798 PointerRNA props_ptr;
2800 /* create operator properties, and assign the relevant pointers to that,
2801 * and add a menu entry which uses these props
2803 WM_operator_properties_create(&props_ptr, op->idname);
2804 RNA_string_set(&props_ptr, "object", ob->id.name+2);
2805 uiItemFullO(layout, op->type->name, 0, op->idname, props_ptr.data, WM_OP_EXEC_REGION_WIN);
2807 /* present the menu and be done... */
2808 uiPupMenuEnd(C, pup);
2811 /* error.. cannot continue */
2812 BKE_report(op->reports, RPT_ERROR, "Can only make proxy for a referenced object or group");
2815 /* this invoke just calls another instance of this operator... */
2816 return OPERATOR_CANCELLED;
2819 static int make_proxy_exec (bContext *C, wmOperator *op)
2821 Object *ob=NULL, *gob=NULL;
2822 Scene *scene= CTX_data_scene(C);
2823 char ob_name[21], gob_name[21];
2825 /* get object and group object
2827 * - then pointers from context
2829 RNA_string_get(op->ptr, "object", ob_name);
2830 RNA_string_get(op->ptr, "group_object", gob_name);
2836 /* active object is group object... */
2837 // FIXME: we should get the nominated name instead
2838 gob= CTX_data_active_object(C);
2839 group= gob->dup_group;
2841 /* find the object to affect */
2842 for (go= group->gobject.first; go; go= go->next) {
2843 if ((go->ob) && strcmp(go->ob->id.name+2, gob_name)==0) {
2850 /* just use the active object for now */
2851 // FIXME: we should get the nominated name instead
2852 ob= CTX_data_active_object(C);
2857 Base *newbase, *oldbase= BASACT;
2860 /* Add new object for the proxy */
2861 newob= add_object(scene, OB_EMPTY);
2863 strcpy(name, gob->id.name+2);
2865 strcpy(name, ob->id.name+2);
2866 strcat(name, "_proxy");
2867 rename_id(&newob->id, name);
2870 newbase= BASACT; /* add_object sets active... */
2871 newbase->lay= oldbase->lay;
2872 newob->lay= newbase->lay;
2874 /* remove base, leave user count of object, it gets linked in object_make_proxy */
2876 BLI_remlink(&scene->base, oldbase);
2880 object_make_proxy(newob, ob, gob);
2882 /* depsgraph flushes are needed for the new data */
2883 DAG_scene_sort(scene);
2884 DAG_object_flush_update(scene, newob, OB_RECALC);
2886 WM_event_add_notifier(C, NC_OBJECT, NULL);
2889 BKE_report(op->reports, RPT_ERROR, "No object to make proxy for");
2890 return OPERATOR_CANCELLED;
2893 return OPERATOR_FINISHED;
2896 void OBJECT_OT_proxy_make (wmOperatorType *ot)
2899 ot->name= "Make Proxy";
2900 ot->idname= "OBJECT_OT_proxy_make";
2901 ot->description= "Add empty object to become local replacement data of a library-linked object";
2904 ot->invoke= make_proxy_invoke;
2905 ot->exec= make_proxy_exec;
2906 ot->poll= ED_operator_object_active;
2909 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2912 RNA_def_string(ot->srna, "object", "", 19, "Proxy Object", "Name of lib-linked/grouped object to make a proxy for.");
2913 RNA_def_string(ot->srna, "group_object", "", 19, "Group Object", "Name of group instancer (if applicable).");
2916 /* ******************** make parent operator *********************** */
2918 #define PAR_OBJECT 0
2919 #define PAR_ARMATURE 1
2920 #define PAR_ARMATURE_NAME 2
2921 #define PAR_ARMATURE_ENVELOPE 3
2922 #define PAR_ARMATURE_AUTO 4
2925 #define PAR_FOLLOW 7
2926 #define PAR_PATH_CONST 8
2927 #define PAR_LATTICE 9
2928 #define PAR_VERTEX 10
2931 static EnumPropertyItem prop_make_parent_types[] = {
2932 {PAR_OBJECT, "OBJECT", 0, "Object", ""},
2933 {PAR_ARMATURE, "ARMATURE", 0, "Armature Deform", ""},
2934 {PAR_ARMATURE_NAME, "ARMATURE_NAME", 0, " With Empty Groups", ""},
2935 {PAR_ARMATURE_AUTO, "ARMATURE_AUTO", 0, " With Automatic Weights", ""},
2936 {PAR_ARMATURE_ENVELOPE, "ARMATURE_ENVELOPE", 0, " With Envelope Weights", ""},
2937 {PAR_BONE, "BONE", 0, "Bone", ""},
2938 {PAR_CURVE, "CURVE", 0, "Curve Deform", ""},
2939 {PAR_FOLLOW, "FOLLOW", 0, "Follow Path", ""},
2940 {PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""},
2941 {PAR_LATTICE, "LATTICE", 0, "Lattice Deform", ""},
2942 {PAR_VERTEX, "VERTEX", 0, "Vertex", ""},
2943 {PAR_TRIA, "TRIA", 0, "Triangle", ""},
2944 {0, NULL, 0, NULL, NULL}
2947 static int test_parent_loop(Object *par, Object *ob)
2949 /* test if 'ob' is a parent somewhere in par's parents */
2951 if(par == NULL) return 0;
2952 if(ob == par) return 1;
2954 return test_parent_loop(par->parent, ob);
2957 void ED_object_parent(Object *ob, Object *par, int type, const char *substr)
2959 if(!par || test_parent_loop(par, ob)) {
2961 ob->partype= PAROBJECT;
2962 ob->parsubstr[0]= 0;
2966 /* this could use some more checks */
2969 ob->partype &= ~PARTYPE;
2970 ob->partype |= type;
2971 BLI_strncpy(ob->parsubstr, substr, sizeof(ob->parsubstr));
2974 static int parent_set_exec(bContext *C, wmOperator *op)
2976 Scene *scene= CTX_data_scene(C);
2977 Object *par= CTX_data_active_object(C);
2978 bPoseChannel *pchan= NULL;
2979 int partype= RNA_enum_get(op->ptr, "type");
2980 int pararm= ELEM4(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
2982 par->recalc |= OB_RECALC_OB;
2985 if(partype==PAR_FOLLOW || partype==PAR_PATH_CONST) {
2986 if(par->type!=OB_CURVE)
2987 return OPERATOR_CANCELLED;
2989 Curve *cu= par->data;
2991 if((cu->flag & CU_PATH)==0) {
2992 cu->flag |= CU_PATH|CU_FOLLOW;
2993 makeDispListCurveTypes(scene, par, 0); /* force creation of path data */
2995 else cu->flag |= CU_FOLLOW;
2997 /* fall back on regular parenting now */
2998 partype= PAR_OBJECT;
3001 else if(partype==PAR_BONE) {
3002 pchan= get_active_posechannel(par);
3005 error("No active Bone");
3006 return OPERATOR_CANCELLED;
3010 /* context itterator */
3011 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
3015 if( test_parent_loop(par, ob) ) {
3016 error("Loop in parents");
3021 /* apply transformation of previous parenting */
3022 ED_object_apply_obmat(ob);
3028 strcpy (ob->parsubstr, pchan->name);
3030 ob->parsubstr[0]= 0;
3033 if(partype==PAR_PATH_CONST) {
3035 bFollowPathConstraint *data;
3036 float cmat[4][4], vec[3];
3038 con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
3039 strcpy (con->name, "AutoPath");
3044 add_constraint_to_object(con, ob);
3046 get_constraint_target_matrix(con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra - give_timeoffset(ob));
3047 VecSubf(vec, ob->obmat[3], cmat[3]);
3049 ob->loc[0] = vec[0];
3050 ob->loc[1] = vec[1];
3052 else if(pararm && ob->type==OB_MESH && par->type == OB_ARMATURE) {
3053 if(partype == PAR_ARMATURE_NAME)
3054 create_vgroups_from_armature(scene, ob, par, ARM_GROUPS_NAME);
3055 else if(partype == PAR_ARMATURE_ENVELOPE)
3056 create_vgroups_from_armature(scene, ob, par, ARM_GROUPS_ENVELOPE);
3057 else if(partype == PAR_ARMATURE_AUTO)
3058 create_vgroups_from_armature(scene, ob, par, ARM_GROUPS_AUTO);
3060 /* get corrected inverse */
3061 ob->partype= PAROBJECT;
3062 what_does_parent(scene, ob, &workob);
3064 ob->partype= PARSKEL;
3066 Mat4Invert(ob->parentinv, workob.obmat);
3069 /* calculate inverse parent matrix */
3070 what_does_parent(scene, ob, &workob);
3071 Mat4Invert(ob->parentinv, workob.obmat);
3074 ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
3076 if( ELEM(partype, PAR_CURVE, PAR_LATTICE) || pararm )
3077 ob->partype= PARSKEL; /* note, dna define, not operator property */
3079 ob->partype= PAROBJECT; /* note, dna define, not operator property */
3085 DAG_scene_sort(CTX_data_scene(C));
3086 ED_anim_dag_flush_update(C);
3087 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
3089 return OPERATOR_FINISHED;
3092 static int parent_set_invoke(bContext *C, wmOperator *op, wmEvent *event)
3094 Object *ob= CTX_data_active_object(C);
3095 uiPopupMenu *pup= uiPupMenuBegin(C, "Set Parent To", 0);
3096 uiLayout *layout= uiPupMenuLayout(pup);
3098 uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
3099 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_OBJECT);
3101 /* ob becomes parent, make the associated menus */
3102 if(ob->type==OB_ARMATURE) {
3103 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE);
3104 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE_NAME);
3105 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE_ENVELOPE);
3106 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE_AUTO);
3107 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_BONE);
3109 else if(ob->type==OB_CURVE) {
3110 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_CURVE);
3111 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_FOLLOW);
3112 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_PATH_CONST);
3114 else if(ob->type == OB_LATTICE) {
3115 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_LATTICE);
3118 uiPupMenuEnd(C, pup);
3120 return OPERATOR_CANCELLED;
3124 void OBJECT_OT_parent_set(wmOperatorType *ot)
3127 ot->name= "Make Parent";
3128 ot->description = "Set the object's parenting.";
3129 ot->idname= "OBJECT_OT_parent_set";
3132 ot->invoke= parent_set_invoke;
3133 ot->exec= parent_set_exec;
3135 ot->poll= ED_operator_object_active;
3138 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
3140 RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
3143 /* *** make track ***** */
3144 static EnumPropertyItem prop_make_track_types[] = {
3145 {1, "TRACKTO", 0, "TrackTo Constraint", ""},
3146 {2, "LOCKTRACK", 0, "LockTrack Constraint", ""},
3147 {3, "OLDTRACK", 0, "Old Track", ""},
3148 {0, NULL, 0, NULL, NULL}
3151 static int track_set_exec(bContext *C, wmOperator *op)
3153 Scene *scene= CTX_data_scene(C);
3154 int type= RNA_enum_get(op->ptr, "type");
3158 bTrackToConstraint *data;
3160 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
3162 con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
3163 strcpy (con->name, "AutoTrack");
3166 data->tar = BASACT->object;
3167 base->object->recalc |= OB_RECALC;
3169 /* Lamp and Camera track differently by default */
3170 if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
3171 data->reserved1 = TRACK_nZ;
3172 data->reserved2 = UP_Y;
3175 add_constraint_to_object(con, base->object);
3180 else if(type == 2) {
3182 bLockTrackConstraint *data;
3184 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
3186 con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
3187 strcpy (con->name, "AutoTrack");
3190 data->tar = BASACT->object;
3191 base->object->recalc |= OB_RECALC;
3193 /* Lamp and Camera track differently by default */
3194 if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
3195 data->trackflag = TRACK_nZ;
3196 data->lockflag = LOCK_Y;