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_paint.h"
102 #include "BKE_particle.h"
103 #include "BKE_property.h"
104 #include "BKE_report.h"
106 #include "BKE_scene.h"
107 #include "BKE_softbody.h"
108 #include "BKE_subsurf.h"
109 #include "BKE_texture.h"
110 #include "BKE_utildefines.h"
111 #include "BKE_modifier.h"
113 #include "ED_anim_api.h"
114 #include "ED_armature.h"
115 #include "ED_curve.h"
116 #include "ED_particle.h"
118 #include "ED_mball.h"
119 #include "ED_object.h"
120 #include "ED_screen.h"
121 #include "ED_transform.h"
122 #include "ED_types.h"
124 #include "ED_view3d.h"
126 #include "UI_interface.h"
128 #include "RNA_access.h"
129 #include "RNA_define.h"
130 #include "RNA_enum_types.h"
132 /* for menu/popup icons etc etc*/
133 #include "UI_interface.h"
134 #include "UI_resources.h"
137 #include "WM_types.h"
139 #include "object_intern.h" // own include
141 /* ************* XXX **************** */
142 static void error() {}
143 static void waitcursor(int val) {}
144 static int pupmenu(const char *msg) {return 0;}
145 static int pupmenu_col(const char *msg, int val) {return 0;}
146 static int okee(const char *msg) {return 0;}
150 static void error_libdata() {}
152 /* ********************************** */
154 /* --------------------------------- */
156 /* simple API for object selection, rather than just using the flag
157 * this takes into account the 'restrict selection in 3d view' flag.
158 * deselect works always, the restriction just prevents selection */
160 /* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! */
162 void ED_base_object_select(Base *base, short mode)
165 if (mode==BA_SELECT) {
166 if (!(base->object->restrictflag & OB_RESTRICT_SELECT))
167 if (mode==BA_SELECT) base->flag |= SELECT;
169 else if (mode==BA_DESELECT) {
170 base->flag &= ~SELECT;
172 base->object->flag= base->flag;
176 /* also to set active NULL */
177 void ED_base_object_activate(bContext *C, Base *base)
179 Scene *scene= CTX_data_scene(C);
182 /* sets scene->basact */
187 /* XXX old signals, remember to handle notifiers now! */
188 // select_actionchannel_by_name(base->object->action, "Object", 1);
190 /* disable temporal locks */
191 for(tbase=FIRSTBASE; tbase; tbase= tbase->next) {
192 if(base!=tbase && (tbase->object->shapeflag & OB_SHAPE_TEMPLOCK)) {
193 tbase->object->shapeflag &= ~OB_SHAPE_TEMPLOCK;
194 DAG_object_flush_update(scene, tbase->object, OB_RECALC_DATA);
197 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
200 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, NULL);
205 void ED_object_base_init_from_view(bContext *C, Base *base)
207 View3D *v3d= CTX_wm_view3d(C);
208 Scene *scene= CTX_data_scene(C);
209 Object *ob= base->object;
215 base->lay = scene->lay;
216 VECCOPY(ob->loc, scene->cursor);
219 if (v3d->localview) {
220 base->lay= ob->lay= v3d->layact | v3d->lay;
221 VECCOPY(ob->loc, v3d->cursor);
224 base->lay= ob->lay= v3d->layact;
225 VECCOPY(ob->loc, scene->cursor);
228 if (U.flag & USER_ADD_VIEWALIGNED) {
229 ARegion *ar= CTX_wm_region(C);
231 RegionView3D *rv3d= ar->regiondata;
233 rv3d->viewquat[0]= -rv3d->viewquat[0];
234 QuatToEul(rv3d->viewquat, ob->rot);
235 rv3d->viewquat[0]= -rv3d->viewquat[0];
239 where_is_object(scene, ob);
242 /* ******************* add object operator ****************** */
244 static EnumPropertyItem prop_object_types[] = {
245 {OB_MESH, "MESH", 0, "Mesh", ""},
246 {OB_CURVE, "CURVE", 0, "Curve", ""},
247 {OB_SURF, "SURFACE", 0, "Surface", ""},
248 {OB_MBALL, "META", 0, "Meta", ""},
249 {OB_FONT, "TEXT", 0, "Text", ""},
250 {0, "", 0, NULL, NULL},
251 {OB_ARMATURE, "ARMATURE", 0, "Armature", ""},
252 {OB_LATTICE, "LATTICE", 0, "Lattice", ""},
253 {OB_EMPTY, "EMPTY", 0, "Empty", ""},
254 {0, "", 0, NULL, NULL},
255 {OB_CAMERA, "CAMERA", 0, "Camera", ""},
256 {OB_LAMP, "LAMP", 0, "Lamp", ""},
257 {0, NULL, 0, NULL, NULL}
262 void add_object_draw(Scene *scene, View3D *v3d, int type) /* for toolbox or menus, only non-editmode stuff */
264 /* keep here to get things compile, remove later */
267 /* for object add primitive operators */
268 static Object *object_add_type(bContext *C, int type)
270 Scene *scene= CTX_data_scene(C);
273 /* for as long scene has editmode... */
274 if (CTX_data_edit_object(C))
275 ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* freedata, and undo */
277 /* deselects all, sets scene->basact */
278 ob= add_object(scene, type);
279 /* editor level activate, notifiers */
280 ED_base_object_activate(C, BASACT);
282 /* more editor stuff */
283 ED_object_base_init_from_view(C, BASACT);
285 DAG_scene_sort(scene);
290 /* for object add operator */
291 static int object_add_exec(bContext *C, wmOperator *op)
293 object_add_type(C, RNA_int_get(op->ptr, "type"));
295 return OPERATOR_FINISHED;
298 void OBJECT_OT_object_add(wmOperatorType *ot)
301 ot->name= "Add Object";
302 ot->description = "Add an object to the scene.";
303 ot->idname= "OBJECT_OT_object_add";
306 ot->invoke= WM_menu_invoke;
307 ot->exec= object_add_exec;
309 ot->poll= ED_operator_scene_editable;
312 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
314 RNA_def_enum(ot->srna, "type", prop_object_types, 0, "Type", "");
317 /* ***************** add primitives *************** */
318 /* ****** work both in and outside editmode ****** */
320 static EnumPropertyItem prop_mesh_types[] = {
321 {0, "PLANE", ICON_MESH_PLANE, "Plane", ""},
322 {1, "CUBE", ICON_MESH_CUBE, "Cube", ""},
323 {2, "CIRCLE", ICON_MESH_CIRCLE, "Circle", ""},
324 {3, "UVSPHERE", ICON_MESH_UVSPHERE, "UVsphere", ""},
325 {4, "ICOSPHERE", ICON_MESH_ICOSPHERE, "Icosphere", ""},
326 {5, "CYLINDER", ICON_MESH_TUBE, "Cylinder", ""},
327 {6, "CONE", ICON_MESH_CONE, "Cone", ""},
328 {0, "", 0, NULL, NULL},
329 {7, "GRID", ICON_MESH_GRID, "Grid", ""},
330 {8, "MONKEY", ICON_MESH_MONKEY, "Monkey", ""},
331 {0, NULL, 0, NULL, NULL}
334 static int object_add_mesh_exec(bContext *C, wmOperator *op)
336 Object *obedit= CTX_data_edit_object(C);
339 if(obedit==NULL || obedit->type!=OB_MESH) {
340 object_add_type(C, OB_MESH);
341 ED_object_enter_editmode(C, EM_DO_UNDO);
344 else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
346 switch(RNA_enum_get(op->ptr, "type")) {
348 WM_operator_name_call(C, "MESH_OT_primitive_plane_add", WM_OP_INVOKE_REGION_WIN, NULL);
351 WM_operator_name_call(C, "MESH_OT_primitive_cube_add", WM_OP_INVOKE_REGION_WIN, NULL);
354 WM_operator_name_call(C, "MESH_OT_primitive_circle_add", WM_OP_INVOKE_REGION_WIN, NULL);
357 WM_operator_name_call(C, "MESH_OT_primitive_uv_sphere_add", WM_OP_INVOKE_REGION_WIN, NULL);
360 WM_operator_name_call(C, "MESH_OT_primitive_ico_sphere_add", WM_OP_INVOKE_REGION_WIN, NULL);
363 WM_operator_name_call(C, "MESH_OT_primitive_cylinder_add", WM_OP_INVOKE_REGION_WIN, NULL);
366 WM_operator_name_call(C, "MESH_OT_primitive_cone_add", WM_OP_INVOKE_REGION_WIN, NULL);
369 WM_operator_name_call(C, "MESH_OT_primitive_grid_add", WM_OP_INVOKE_REGION_WIN, NULL);
372 WM_operator_name_call(C, "MESH_OT_primitive_monkey_add", WM_OP_INVOKE_REGION_WIN, NULL);
376 if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
377 ED_object_exit_editmode(C, EM_FREEDATA);
380 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
382 return OPERATOR_FINISHED;
386 void OBJECT_OT_mesh_add(wmOperatorType *ot)
389 ot->name= "Add Mesh";
390 ot->description = "Add a mesh object to the scene.";
391 ot->idname= "OBJECT_OT_mesh_add";
394 ot->invoke= WM_menu_invoke;
395 ot->exec= object_add_mesh_exec;
397 ot->poll= ED_operator_scene_editable;
399 /* flags: no register or undo, this operator calls operators */
400 ot->flag= 0; //OPTYPE_REGISTER|OPTYPE_UNDO;
402 RNA_def_enum(ot->srna, "type", prop_mesh_types, 0, "Primitive", "");
405 static EnumPropertyItem prop_curve_types[] = {
406 {CU_BEZIER|CU_2D|CU_PRIM_CURVE, "BEZIER_CURVE", ICON_CURVE_BEZCURVE, "Bezier Curve", ""},
407 {CU_BEZIER|CU_2D|CU_PRIM_CIRCLE, "BEZIER_CIRCLE", ICON_CURVE_BEZCIRCLE, "Bezier Circle", ""},
408 {CU_NURBS|CU_2D|CU_PRIM_CURVE, "NURBS_CURVE", ICON_CURVE_NCURVE, "NURBS Curve", ""},
409 {CU_NURBS|CU_2D|CU_PRIM_CIRCLE, "NURBS_CIRCLE", ICON_CURVE_NCIRCLE, "NURBS Circle", ""},
410 {CU_NURBS|CU_2D|CU_PRIM_PATH, "PATH", ICON_CURVE_PATH, "Path", ""},
411 {0, NULL, 0, NULL, NULL}
414 static int object_add_curve_exec(bContext *C, wmOperator *op)
416 Object *obedit= CTX_data_edit_object(C);
421 if(obedit==NULL || obedit->type!=OB_CURVE) {
422 object_add_type(C, OB_CURVE);
423 ED_object_enter_editmode(C, 0);
426 else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
428 obedit= CTX_data_edit_object(C);
429 nu= add_nurbs_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
430 editnurb= curve_get_editcurve(obedit);
431 BLI_addtail(editnurb, nu);
434 if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
435 ED_object_exit_editmode(C, EM_FREEDATA);
438 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
440 return OPERATOR_FINISHED;
443 static int object_add_curve_invoke(bContext *C, wmOperator *op, wmEvent *event)
445 Object *obedit= CTX_data_edit_object(C);
449 pup= uiPupMenuBegin(C, op->type->name, 0);
450 layout= uiPupMenuLayout(pup);
451 if(!obedit || obedit->type == OB_CURVE)
452 uiItemsEnumO(layout, op->type->idname, "type");
454 uiItemsEnumO(layout, "OBJECT_OT_surface_add", "type");
455 uiPupMenuEnd(C, pup);
457 return OPERATOR_CANCELLED;
460 void OBJECT_OT_curve_add(wmOperatorType *ot)
463 ot->name= "Add Curve";
464 ot->description = "Add a curve object to the scene.";
465 ot->idname= "OBJECT_OT_curve_add";
468 ot->invoke= object_add_curve_invoke;
469 ot->exec= object_add_curve_exec;
471 ot->poll= ED_operator_scene_editable;
474 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
476 RNA_def_enum(ot->srna, "type", prop_curve_types, 0, "Primitive", "");
479 static EnumPropertyItem prop_surface_types[]= {
480 {CU_PRIM_CURVE|CU_NURBS, "NURBS_CURVE", ICON_SURFACE_NCURVE, "NURBS Curve", ""},
481 {CU_PRIM_CIRCLE|CU_NURBS, "NURBS_CIRCLE", ICON_SURFACE_NCIRCLE, "NURBS Circle", ""},
482 {CU_PRIM_PATCH|CU_NURBS, "NURBS_SURFACE", ICON_SURFACE_NSURFACE, "NURBS Surface", ""},
483 {CU_PRIM_TUBE|CU_NURBS, "NURBS_TUBE", ICON_SURFACE_NTUBE, "NURBS Tube", ""},
484 {CU_PRIM_SPHERE|CU_NURBS, "NURBS_SPHERE", ICON_SURFACE_NSPHERE, "NURBS Sphere", ""},
485 {CU_PRIM_DONUT|CU_NURBS, "NURBS_DONUT", ICON_SURFACE_NDONUT, "NURBS Donut", ""},
486 {0, NULL, 0, NULL, NULL}
489 static int object_add_surface_exec(bContext *C, wmOperator *op)
491 Object *obedit= CTX_data_edit_object(C);
496 if(obedit==NULL || obedit->type!=OB_SURF) {
497 object_add_type(C, OB_SURF);
498 ED_object_enter_editmode(C, 0);
501 else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
503 obedit= CTX_data_edit_object(C);
504 nu= add_nurbs_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
505 editnurb= curve_get_editcurve(obedit);
506 BLI_addtail(editnurb, nu);
509 if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
510 ED_object_exit_editmode(C, EM_FREEDATA);
513 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
515 return OPERATOR_FINISHED;
518 void OBJECT_OT_surface_add(wmOperatorType *ot)
521 ot->name= "Add Surface";
522 ot->description = "Add a surface object to the scene.";
523 ot->idname= "OBJECT_OT_surface_add";
526 ot->invoke= WM_menu_invoke;
527 ot->exec= object_add_surface_exec;
529 ot->poll= ED_operator_scene_editable;
532 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
534 RNA_def_enum(ot->srna, "type", prop_surface_types, 0, "Primitive", "");
537 static EnumPropertyItem prop_metaball_types[]= {
538 {MB_BALL, "MBALL_BALL", ICON_META_BALL, "Meta Ball", ""},
539 {MB_TUBE, "MBALL_TUBE", ICON_META_TUBE, "Meta Tube", ""},
540 {MB_PLANE, "MBALL_PLANE", ICON_META_PLANE, "Meta Plane", ""},
541 {MB_CUBE, "MBALL_CUBE", ICON_META_CUBE, "Meta Cube", ""},
542 {MB_ELIPSOID, "MBALL_ELLIPSOID", ICON_META_ELLIPSOID, "Meta Ellipsoid", ""},
543 {0, NULL, 0, NULL, NULL}
546 static int object_metaball_add_exec(bContext *C, wmOperator *op)
548 Object *obedit= CTX_data_edit_object(C);
553 if(obedit==NULL || obedit->type!=OB_MBALL) {
554 object_add_type(C, OB_MBALL);
555 ED_object_enter_editmode(C, 0);
558 else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
560 obedit= CTX_data_edit_object(C);
561 elem= (MetaElem*)add_metaball_primitive(C, RNA_enum_get(op->ptr, "type"), newob);
562 mball= (MetaBall*)obedit->data;
563 BLI_addtail(mball->editelems, elem);
566 if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
567 ED_object_exit_editmode(C, EM_FREEDATA);
570 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
572 return OPERATOR_FINISHED;
575 static int object_metaball_add_invoke(bContext *C, wmOperator *op, wmEvent *event)
577 Object *obedit= CTX_data_edit_object(C);
581 pup= uiPupMenuBegin(C, op->type->name, 0);
582 layout= uiPupMenuLayout(pup);
583 if(!obedit || obedit->type == OB_MBALL)
584 uiItemsEnumO(layout, op->type->idname, "type");
586 uiItemsEnumO(layout, "OBJECT_OT_metaball_add", "type");
587 uiPupMenuEnd(C, pup);
589 return OPERATOR_CANCELLED;
592 void OBJECT_OT_metaball_add(wmOperatorType *ot)
595 ot->name= "Metaball";
596 ot->description= "Add an metaball object to the scene.";
597 ot->idname= "OBJECT_OT_metaball_add";
600 ot->invoke= object_metaball_add_invoke;
601 ot->exec= object_metaball_add_exec;
602 ot->poll= ED_operator_scene_editable;
605 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
607 RNA_def_enum(ot->srna, "type", prop_metaball_types, 0, "Primitive", "");
609 static int object_add_text_exec(bContext *C, wmOperator *op)
611 Object *obedit= CTX_data_edit_object(C);
613 if(obedit && obedit->type==OB_FONT)
614 return OPERATOR_CANCELLED;
616 object_add_type(C, OB_FONT);
617 obedit= CTX_data_active_object(C);
619 if(U.flag & USER_ADD_EDITMODE)
620 ED_object_enter_editmode(C, 0);
622 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
624 return OPERATOR_FINISHED;
627 void OBJECT_OT_text_add(wmOperatorType *ot)
630 ot->name= "Add Text";
631 ot->description = "Add a text object to the scene";
632 ot->idname= "OBJECT_OT_text_add";
635 ot->exec= object_add_text_exec;
636 ot->poll= ED_operator_scene_editable;
639 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
642 static int object_armature_add_exec(bContext *C, wmOperator *op)
644 Object *obedit= CTX_data_edit_object(C);
645 View3D *v3d= CTX_wm_view3d(C);
646 RegionView3D *rv3d= NULL;
649 if ((obedit==NULL) || (obedit->type != OB_ARMATURE)) {
650 object_add_type(C, OB_ARMATURE);
651 ED_object_enter_editmode(C, 0);
654 else DAG_object_flush_update(CTX_data_scene(C), obedit, OB_RECALC_DATA);
657 rv3d= CTX_wm_region(C)->regiondata;
659 /* v3d and rv3d are allowed to be NULL */
660 add_primitive_bone(CTX_data_scene(C), v3d, rv3d);
663 if (newob && (U.flag & USER_ADD_EDITMODE)==0) {
664 ED_object_exit_editmode(C, EM_FREEDATA);
667 WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
669 return OPERATOR_FINISHED;
672 void OBJECT_OT_armature_add(wmOperatorType *ot)
675 ot->name= "Add Armature";
676 ot->description = "Add an armature object to the scene.";
677 ot->idname= "OBJECT_OT_armature_add";
680 ot->exec= object_armature_add_exec;
681 ot->poll= ED_operator_scene_editable;
684 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
687 static int object_primitive_add_invoke(bContext *C, wmOperator *op, wmEvent *event)
689 uiPopupMenu *pup= uiPupMenuBegin(C, "Add Object", 0);
690 uiLayout *layout= uiPupMenuLayout(pup);
692 uiItemMenuEnumO(layout, "Mesh", ICON_OUTLINER_OB_MESH, "OBJECT_OT_mesh_add", "type");
693 uiItemMenuEnumO(layout, "Curve", ICON_OUTLINER_OB_CURVE, "OBJECT_OT_curve_add", "type");
694 uiItemMenuEnumO(layout, "Surface", ICON_OUTLINER_OB_SURFACE, "OBJECT_OT_surface_add", "type");
695 uiItemMenuEnumO(layout, NULL, ICON_OUTLINER_OB_META, "OBJECT_OT_metaball_add", "type");
696 uiItemO(layout, "Text", ICON_OUTLINER_OB_FONT, "OBJECT_OT_text_add");
698 uiItemO(layout, "Armature", ICON_OUTLINER_OB_ARMATURE, "OBJECT_OT_armature_add");
699 uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_LATTICE, "OBJECT_OT_object_add", "type", OB_LATTICE);
700 uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_EMPTY, "OBJECT_OT_object_add", "type", OB_EMPTY);
702 uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_CAMERA, "OBJECT_OT_object_add", "type", OB_CAMERA);
703 uiItemEnumO(layout, NULL, ICON_OUTLINER_OB_LAMP, "OBJECT_OT_object_add", "type", OB_LAMP);
705 uiPupMenuEnd(C, pup);
707 /* this operator is only for a menu, not used further */
708 return OPERATOR_CANCELLED;
711 /* only used as menu */
712 void OBJECT_OT_primitive_add(wmOperatorType *ot)
715 ot->name= "Add Primitive";
716 ot->description = "Add a primitive object.";
717 ot->idname= "OBJECT_OT_primitive_add";
720 ot->invoke= object_primitive_add_invoke;
722 ot->poll= ED_operator_scene_editable;
729 /* ******************************* */
731 /* remove base from a specific scene */
732 /* note: now unlinks constraints as well */
733 void ED_base_object_free_and_unlink(Scene *scene, Base *base)
735 BLI_remlink(&scene->base, base);
736 free_libblock_us(&G.main->object, base->object);
737 if(scene->basact==base) scene->basact= NULL;
741 static int object_delete_exec(bContext *C, wmOperator *op)
743 Scene *scene= CTX_data_scene(C);
746 if(CTX_data_edit_object(C))
747 return OPERATOR_CANCELLED;
749 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
751 if(base->object->type==OB_LAMP) islamp= 1;
753 /* remove from current scene only */
754 ED_base_object_free_and_unlink(scene, base);
758 if(islamp) reshadeall_displist(scene); /* only frees displist */
760 DAG_scene_sort(scene);
761 ED_anim_dag_flush_update(C);
763 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, CTX_data_scene(C));
765 return OPERATOR_FINISHED;
768 void OBJECT_OT_delete(wmOperatorType *ot)
773 ot->description = "Delete selected objects.";
774 ot->idname= "OBJECT_OT_delete";
777 ot->invoke= WM_operator_confirm;
778 ot->exec= object_delete_exec;
779 ot->poll= ED_operator_scene_editable;
782 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
787 static void single_object_users__forwardModifierLinks(void *userData, Object *ob, Object **obpoin)
792 static void copy_object__forwardModifierLinks(void *userData, Object *ob,
795 /* this is copied from ID_NEW; it might be better to have a macro */
796 if(*idpoin && (*idpoin)->newid) *idpoin = (*idpoin)->newid;
800 /* after copying objects, copied data should get new pointers */
801 static void copy_object_set_idnew(Scene *scene, View3D *v3d, int dupflag)
807 #if 0 // XXX old animation system
810 #endif // XXX old animation system
813 /* XXX check object pointers */
814 for(base= FIRSTBASE; base; base= base->next) {
815 if(TESTBASELIB_BGMODE(v3d, base)) {
817 relink_constraints(&ob->constraints);
820 for (chan = ob->pose->chanbase.first; chan; chan=chan->next){
821 relink_constraints(&chan->constraints);
824 modifiers_foreachIDLink(ob, copy_object__forwardModifierLinks, NULL);
828 ID_NEW(ob->proxy_group);
830 #if 0 // XXX old animation system
831 for(strip= ob->nlastrips.first; strip; strip= strip->next) {
832 bActionModifier *amod;
833 for(amod= strip->modifiers.first; amod; amod= amod->next)
836 #endif // XXX old animation system
841 if( dupflag & USER_DUP_MAT) {
842 mao= G.main->mat.first;
846 ma= (Material *)mao->id.newid;
848 if(dupflag & USER_DUP_TEX) {
849 for(a=0; a<MAX_MTEX; a++) {
851 id= (ID *)ma->mtex[a]->tex;
853 ID_NEW_US(ma->mtex[a]->tex)
854 else ma->mtex[a]->tex= copy_texture(ma->mtex[a]->tex);
860 #if 0 // XXX old animation system
864 else ma->ipo= copy_ipo(ma->ipo);
867 #endif // XXX old animation system
873 #if 0 // XXX old animation system
875 if( dupflag & USER_DUP_IPO) {
876 Lamp *la= G.main->lamp.first;
879 Lamp *lan= (Lamp *)la->id.newid;
883 else lan->ipo= copy_ipo(lan->ipo);
892 ipo= G.main->ipo.first;
894 if(ipo->id.lib==NULL && ipo->id.newid) {
895 Ipo *ipon= (Ipo *)ipo->id.newid;
897 for(icu= ipon->curve.first; icu; icu= icu->next) {
899 ID_NEW(icu->driver->ob);
905 #endif // XXX old animation system
913 static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float *cent)
916 int *index, nr, totvert=0;
918 for(eve= em->verts.first; eve; eve= eve->next) {
919 if(eve->f & SELECT) totvert++;
921 if(totvert==0) return 0;
923 *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
926 cent[0]= cent[1]= cent[2]= 0.0;
928 for(eve= em->verts.first; eve; eve= eve->next) {
929 if(eve->f & SELECT) {
931 VecAddf(cent, cent, eve->co);
936 VecMulf(cent, 1.0f/(float)totvert);
941 static int return_editmesh_vgroup(Object *obedit, EditMesh *em, char *name, float *cent)
947 cent[0]= cent[1]= cent[2]= 0.0;
951 /* find the vertices */
952 for(eve= em->verts.first; eve; eve= eve->next) {
953 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
956 for(i=0; i<dvert->totweight; i++){
957 if(dvert->dw[i].def_nr == (obedit->actdef-1)) {
959 VecAddf(cent, cent, eve->co);
965 bDeformGroup *defGroup = BLI_findlink(&obedit->defbase, obedit->actdef-1);
966 strcpy(name, defGroup->name);
967 VecMulf(cent, 1.0f/(float)totvert);
975 static void select_editmesh_hook(Object *ob, HookModifierData *hmd)
978 EditMesh *em= BKE_mesh_get_editmesh(me);
982 if (hmd->indexar == NULL)
985 for(eve= em->verts.first; eve; eve= eve->next, nr++) {
986 if(nr==hmd->indexar[index]) {
988 if(index < hmd->totindex-1) index++;
993 BKE_mesh_end_editmesh(me, em);
996 static int return_editlattice_indexar(Lattice *editlatt, int *tot, int **indexar, float *cent)
999 int *index, nr, totvert=0, a;
1002 a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
1005 if(bp->f1 & SELECT) {
1006 if(bp->hide==0) totvert++;
1011 if(totvert==0) return 0;
1013 *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
1016 cent[0]= cent[1]= cent[2]= 0.0;
1018 a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
1021 if(bp->f1 & SELECT) {
1023 *index= nr; index++;
1024 VecAddf(cent, cent, bp->vec);
1031 VecMulf(cent, 1.0f/(float)totvert);
1036 static void select_editlattice_hook(Object *obedit, HookModifierData *hmd)
1038 Lattice *lt= obedit->data;
1040 int index=0, nr=0, a;
1043 a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
1044 bp= lt->editlatt->def;
1046 if(hmd->indexar[index]==nr) {
1048 if(index < hmd->totindex-1) index++;
1055 static int return_editcurve_indexar(Object *obedit, int *tot, int **indexar, float *cent)
1057 ListBase *editnurb= curve_get_editcurve(obedit);
1061 int *index, a, nr, totvert=0;
1063 for(nu= editnurb->first; nu; nu= nu->next) {
1064 if((nu->type & 7)==CU_BEZIER) {
1068 if(bezt->f1 & SELECT) totvert++;
1069 if(bezt->f2 & SELECT) totvert++;
1070 if(bezt->f3 & SELECT) totvert++;
1076 a= nu->pntsu*nu->pntsv;
1078 if(bp->f1 & SELECT) totvert++;
1083 if(totvert==0) return 0;
1085 *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
1088 cent[0]= cent[1]= cent[2]= 0.0;
1090 for(nu= editnurb->first; nu; nu= nu->next) {
1091 if((nu->type & 7)==CU_BEZIER) {
1095 if(bezt->f1 & SELECT) {
1096 *index= nr; index++;
1097 VecAddf(cent, cent, bezt->vec[0]);
1100 if(bezt->f2 & SELECT) {
1101 *index= nr; index++;
1102 VecAddf(cent, cent, bezt->vec[1]);
1105 if(bezt->f3 & SELECT) {
1106 *index= nr; index++;
1107 VecAddf(cent, cent, bezt->vec[2]);
1115 a= nu->pntsu*nu->pntsv;
1117 if(bp->f1 & SELECT) {
1118 *index= nr; index++;
1119 VecAddf(cent, cent, bp->vec);
1127 VecMulf(cent, 1.0f/(float)totvert);
1132 void ED_object_apply_obmat(Object *ob)
1134 float mat[3][3], imat[3][3], tmat[3][3];
1136 /* from obmat to loc rot size */
1138 if(ob==NULL) return;
1139 Mat3CpyMat4(mat, ob->obmat);
1141 VECCOPY(ob->loc, ob->obmat[3]);
1143 Mat3ToEul(mat, ob->rot);
1144 EulToMat3(ob->rot, tmat);
1146 Mat3Inv(imat, tmat);
1148 Mat3MulMat3(tmat, imat, mat);
1150 ob->size[0]= tmat[0][0];
1151 ob->size[1]= tmat[1][1];
1152 ob->size[2]= tmat[2][2];
1156 int object_hook_index_array(Object *obedit, int *tot, int **indexar, char *name, float *cent_r)
1162 switch(obedit->type) {
1165 Mesh *me= obedit->data;
1166 EditMesh *em = BKE_mesh_get_editmesh(me);
1168 /* check selected vertices first */
1169 if( return_editmesh_indexar(em, tot, indexar, cent_r)) {
1170 BKE_mesh_end_editmesh(me, em);
1173 int ret = return_editmesh_vgroup(obedit, em, name, cent_r);
1174 BKE_mesh_end_editmesh(me, em);
1180 return return_editcurve_indexar(obedit, tot, indexar, cent_r);
1183 Lattice *lt= obedit->data;
1184 return return_editlattice_indexar(lt->editlatt, tot, indexar, cent_r);
1191 static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
1193 ListBase *editnurb= curve_get_editcurve(obedit);
1197 int index=0, a, nr=0;
1199 for(nu= editnurb->first; nu; nu= nu->next) {
1200 if((nu->type & 7)==CU_BEZIER) {
1204 if(nr == hmd->indexar[index]) {
1206 if(index<hmd->totindex-1) index++;
1209 if(nr == hmd->indexar[index]) {
1211 if(index<hmd->totindex-1) index++;
1214 if(nr == hmd->indexar[index]) {
1216 if(index<hmd->totindex-1) index++;
1225 a= nu->pntsu*nu->pntsv;
1227 if(nr == hmd->indexar[index]) {
1229 if(index<hmd->totindex-1) index++;
1238 void object_hook_select(Object *ob, HookModifierData *hmd)
1240 if(ob->type==OB_MESH) select_editmesh_hook(ob, hmd);
1241 else if(ob->type==OB_LATTICE) select_editlattice_hook(ob, hmd);
1242 else if(ob->type==OB_CURVE) select_editcurve_hook(ob, hmd);
1243 else if(ob->type==OB_SURF) select_editcurve_hook(ob, hmd);
1247 void add_hook(Scene *scene, View3D *v3d, int mode)
1249 ModifierData *md = NULL;
1250 HookModifierData *hmd = NULL;
1252 Object *obedit= scene->obedit; // XXX get from context
1254 if(obedit==NULL) return;
1257 if(mode==2) { /* selected object */
1259 for(base= FIRSTBASE; base; base= base->next) {
1260 if(TESTBASELIB(v3d, base)) {
1268 error("Requires selected Object");
1273 int maxlen=0, a, nr;
1276 /* make pupmenu with hooks */
1277 for(md=obedit->modifiers.first; md; md= md->next) {
1278 if (md->type==eModifierType_Hook)
1283 error("Object has no hooks yet");
1287 cp= MEM_callocN(maxlen+32, "temp string");
1288 if(mode==3) strcpy(cp, "Remove %t|");
1289 else if(mode==4) strcpy(cp, "Reassign %t|");
1290 else if(mode==5) strcpy(cp, "Select %t|");
1291 else if(mode==6) strcpy(cp, "Clear Offset %t|");
1293 for(md=obedit->modifiers.first; md; md= md->next) {
1294 if (md->type==eModifierType_Hook) {
1295 strcat(cp, md->name);
1306 for(md=obedit->modifiers.first; md; md=md->next) {
1307 if (md->type==eModifierType_Hook) {
1313 hmd = (HookModifierData*) md;
1317 /* do it, new hooks or reassign */
1318 if(mode==1 || mode==2 || mode==4) {
1320 int tot, ok, *indexar;
1323 ok = object_hook_index_array(obedit, &tot, &indexar, name, cent);
1326 error("Requires selected vertices or active Vertex Group");
1331 Base *base= BASACT, *newbase;
1333 ob= add_object(scene, OB_EMPTY);
1336 newbase->lay= base->lay;
1337 ob->lay= newbase->lay;
1339 /* transform cent to global coords for loc */
1340 VecMat4MulVecfl(ob->loc, obedit->obmat, cent);
1342 /* restore, add_object sets active */
1345 /* if mode is 2 or 4, ob has been set */
1348 if(mode==1 || mode==2) {
1349 ModifierData *md = obedit->modifiers.first;
1351 while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
1355 hmd = (HookModifierData*) modifier_new(eModifierType_Hook);
1356 BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
1357 sprintf(hmd->modifier.name, "Hook-%s", ob->id.name+2);
1359 else if (hmd->indexar) MEM_freeN(hmd->indexar); /* reassign, hook was set */
1362 hmd->indexar= indexar;
1363 VECCOPY(hmd->cent, cent);
1365 BLI_strncpy(hmd->name, name, 32);
1367 // TODO: need to take into account bone targets here too now...
1368 if(mode==1 || mode==2) {
1369 /* matrix calculus */
1370 /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
1373 where_is_object(scene, ob);
1375 Mat4Invert(ob->imat, ob->obmat);
1376 /* apparently this call goes from right to left... */
1377 Mat4MulSerie(hmd->parentinv, ob->imat, obedit->obmat, NULL,
1378 NULL, NULL, NULL, NULL, NULL);
1382 else if(mode==3) { /* remove */
1383 BLI_remlink(&obedit->modifiers, md);
1386 else if(mode==5) { /* select */
1387 // FIXME: this is now OBJECT_OT_hook_select
1388 object_hook_select(obedit, hmd);
1390 else if(mode==6) { /* clear offset */
1391 // FIXME: this is now OBJECT_OT_hook_reset operator
1392 where_is_object(scene, ob); /* ob is hook->parent */
1394 Mat4Invert(ob->imat, ob->obmat);
1395 /* this call goes from right to left... */
1396 Mat4MulSerie(hmd->parentinv, ob->imat, obedit->obmat, NULL,
1397 NULL, NULL, NULL, NULL, NULL);
1400 DAG_scene_sort(scene);
1403 void add_hook_menu(Scene *scene, View3D *v3d)
1405 Object *obedit= scene->obedit; // XXX get from context
1408 if(obedit==NULL) return;
1410 if(modifiers_findByType(obedit, eModifierType_Hook))
1411 mode= pupmenu("Hooks %t|Add, To New Empty %x1|Add, To Selected Object %x2|Remove... %x3|Reassign... %x4|Select... %x5|Clear Offset...%x6");
1413 mode= pupmenu("Hooks %t|Add, New Empty %x1|Add, To Selected Object %x2");
1418 add_hook(scene, v3d, mode);
1423 /* use this when the loc/size/rot of the parent has changed but the children should stay in the same place
1424 * apply-size-rot or object center for eg */
1425 static void ignore_parent_tx(Scene *scene, Object *ob )
1430 /* a change was made, adjust the children to compensate */
1431 for (ob_child=G.main->object.first; ob_child; ob_child=ob_child->id.next) {
1432 if (ob_child->parent == ob) {
1433 ED_object_apply_obmat(ob_child);
1434 what_does_parent(scene, ob_child, &workob);
1435 Mat4Invert(ob_child->parentinv, workob.obmat);
1440 /* ******************** clear parent operator ******************* */
1442 static EnumPropertyItem prop_clear_parent_types[] = {
1443 {0, "CLEAR", 0, "Clear Parent", ""},
1444 {1, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation (Clear Track)", ""},
1445 {2, "CLEAR_INVERSE", 0, "Clear Parent Inverse", ""},
1446 {0, NULL, 0, NULL, NULL}
1449 /* note, poll should check for editable scene */
1450 static int parent_clear_exec(bContext *C, wmOperator *op)
1452 int type= RNA_enum_get(op->ptr, "type");
1454 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1459 else if(type == 1) {
1462 ED_object_apply_obmat(ob);
1465 Mat4One(ob->parentinv);
1467 ob->recalc |= OB_RECALC;
1471 DAG_scene_sort(CTX_data_scene(C));
1472 ED_anim_dag_flush_update(C);
1473 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
1475 return OPERATOR_FINISHED;
1478 void OBJECT_OT_parent_clear(wmOperatorType *ot)
1481 ot->name= "Clear Parent";
1482 ot->description = "Clear the object's parenting.";
1483 ot->idname= "OBJECT_OT_parent_clear";
1486 ot->invoke= WM_menu_invoke;
1487 ot->exec= parent_clear_exec;
1489 ot->poll= ED_operator_object_active;
1492 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1494 RNA_def_enum(ot->srna, "type", prop_clear_parent_types, 0, "Type", "");
1497 /* ******************** clear track operator ******************* */
1500 static EnumPropertyItem prop_clear_track_types[] = {
1501 {0, "CLEAR", 0, "Clear Track", ""},
1502 {1, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation (Clear Track)", ""},
1503 {0, NULL, 0, NULL, NULL}
1506 /* note, poll should check for editable scene */
1507 static int object_track_clear_exec(bContext *C, wmOperator *op)
1509 int type= RNA_enum_get(op->ptr, "type");
1511 if(CTX_data_edit_object(C)) {
1512 BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in EditMode");
1513 return OPERATOR_CANCELLED;
1515 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1517 ob->recalc |= OB_RECALC;
1520 ED_object_apply_obmat(ob);
1524 DAG_scene_sort(CTX_data_scene(C));
1525 ED_anim_dag_flush_update(C);
1527 return OPERATOR_FINISHED;
1530 void OBJECT_OT_track_clear(wmOperatorType *ot)
1533 ot->name= "Clear track";
1534 ot->description = "Clear tracking constraint or flag from object.";
1535 ot->idname= "OBJECT_OT_track_clear";
1538 ot->invoke= WM_menu_invoke;
1539 ot->exec= object_track_clear_exec;
1541 ot->poll= ED_operator_scene_editable;
1544 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1546 RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
1549 /* *****************Selection Operators******************* */
1550 static EnumPropertyItem prop_select_types[] = {
1551 {0, "EXCLUSIVE", 0, "Exclusive", ""},
1552 {1, "EXTEND", 0, "Extend", ""},
1553 {0, NULL, 0, NULL, NULL}
1556 /* ****** Select by Type ****** */
1558 static int object_select_by_type_exec(bContext *C, wmOperator *op)
1560 short obtype, seltype;
1562 obtype = RNA_enum_get(op->ptr, "type");
1563 seltype = RNA_enum_get(op->ptr, "seltype");
1566 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1567 ED_base_object_select(base, BA_DESELECT);
1572 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1573 if(base->object->type==obtype) {
1574 ED_base_object_select(base, BA_SELECT);
1579 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
1581 return OPERATOR_FINISHED;
1584 void OBJECT_OT_select_by_type(wmOperatorType *ot)
1587 ot->name= "Select By Type";
1588 ot->description = "Select all visible objects that are of a type.";
1589 ot->idname= "OBJECT_OT_select_by_type";
1592 ot->invoke= WM_menu_invoke;
1593 ot->exec= object_select_by_type_exec;
1594 ot->poll= ED_operator_scene_editable;
1597 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1599 RNA_def_enum(ot->srna, "seltype", prop_select_types, 0, "Selection", "Extend selection or clear selection then select");
1600 RNA_def_enum(ot->srna, "type", prop_object_types, 1, "Type", "");
1603 /* ****** selection by links *******/
1605 static EnumPropertyItem prop_select_linked_types[] = {
1606 {1, "IPO", 0, "Object IPO", ""}, // XXX depreceated animation system stuff...
1607 {2, "OBDATA", 0, "Ob Data", ""},
1608 {3, "MATERIAL", 0, "Material", ""},
1609 {4, "TEXTURE", 0, "Texture", ""},
1610 {5, "DUPGROUP", 0, "Dupligroup", ""},
1611 {6, "PARTICLE", 0, "Particle System", ""},
1612 {0, NULL, 0, NULL, NULL}
1615 static int object_select_linked_exec(bContext *C, wmOperator *op)
1617 Scene *scene= CTX_data_scene(C);
1619 void *obdata = NULL;
1620 Material *mat = NULL, *mat1;
1623 int nr = RNA_enum_get(op->ptr, "type");
1624 short changed = 0, seltype;
1628 * Current Material: 3
1629 * Current Texture: 4
1634 seltype = RNA_enum_get(op->ptr, "seltype");
1637 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1638 ED_base_object_select(base, BA_DESELECT);
1645 BKE_report(op->reports, RPT_ERROR, "No Active Object");
1646 return OPERATOR_CANCELLED;
1650 // XXX old animation system
1652 //if(ipo==0) return OPERATOR_CANCELLED;
1653 return OPERATOR_CANCELLED;
1656 if(ob->data==0) return OPERATOR_CANCELLED;
1659 else if(nr==3 || nr==4) {
1660 mat= give_current_material(ob, ob->actcol);
1661 if(mat==0) return OPERATOR_CANCELLED;
1663 if(mat->mtex[ (int)mat->texact ]) tex= mat->mtex[ (int)mat->texact ]->tex;
1664 if(tex==0) return OPERATOR_CANCELLED;
1668 if(ob->dup_group==NULL) return OPERATOR_CANCELLED;
1671 if(ob->particlesystem.first==NULL) return OPERATOR_CANCELLED;
1673 else return OPERATOR_CANCELLED;
1675 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1677 // XXX old animation system
1678 //if(base->object->ipo==ipo) base->flag |= SELECT;
1682 if(base->object->data==obdata) base->flag |= SELECT;
1685 else if(nr==3 || nr==4) {
1688 for(a=1; a<=ob->totcol; a++) {
1689 mat1= give_current_material(ob, a);
1691 if(mat1==mat) base->flag |= SELECT;
1694 else if(mat1 && nr==4) {
1695 for(b=0; b<MAX_MTEX; b++) {
1697 if(tex==mat1->mtex[b]->tex) {
1698 base->flag |= SELECT;
1708 if(base->object->dup_group==ob->dup_group) {
1709 base->flag |= SELECT;
1714 /* loop through other, then actives particles*/
1715 ParticleSystem *psys;
1716 ParticleSystem *psys_act;
1718 for(psys=base->object->particlesystem.first; psys; psys=psys->next) {
1719 for(psys_act=ob->particlesystem.first; psys_act; psys_act=psys_act->next) {
1720 if (psys->part == psys_act->part) {
1721 base->flag |= SELECT;
1727 if (base->flag & SELECT) {
1732 base->object->flag= base->flag;
1737 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
1738 return OPERATOR_FINISHED;
1741 return OPERATOR_CANCELLED;
1744 void OBJECT_OT_select_linked(wmOperatorType *ot)
1747 ot->name= "Select Linked";
1748 ot->description = "Select all visible objects that are linked.";
1749 ot->idname= "OBJECT_OT_select_linked";
1752 ot->invoke= WM_menu_invoke;
1753 ot->exec= object_select_linked_exec;
1754 ot->poll= ED_operator_scene_editable;
1757 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1759 RNA_def_enum(ot->srna, "type", prop_select_linked_types, 0, "Type", "");
1760 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
1764 /* ****** selection grouped *******/
1766 static EnumPropertyItem prop_select_grouped_types[] = {
1767 {1, "CHILDREN_RECURSIVE", 0, "Children", ""}, // XXX depreceated animation system stuff...
1768 {2, "CHILDREN", 0, "Immediate Children", ""},
1769 {3, "PARENT", 0, "Parent", ""},
1770 {4, "SIBLINGS", 0, "Siblings", "Shared Parent"},
1771 {5, "TYPE", 0, "Type", "Shared object type"},
1772 {6, "LAYER", 0, "Layer", "Shared layers"},
1773 {7, "GROUP", 0, "Group", "Shared group"},
1774 {8, "HOOK", 0, "Hook", ""},
1775 {9, "PASS", 0, "Pass", "Render pass Index"},
1776 {10, "COLOR", 0, "Color", "Object Color"},
1777 {11, "PROPERTIES", 0, "Properties", "Game Properties"},
1778 {0, NULL, 0, NULL, NULL}
1782 static short select_grouped_children(bContext *C, Object *ob, int recursive)
1786 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1787 if (ob == base->object->parent) {
1788 if (!(base->flag & SELECT)) {
1789 ED_base_object_select(base, BA_SELECT);
1794 changed |= select_grouped_children(C, base->object, 1);
1801 static short select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */
1803 Scene *scene= CTX_data_scene(C);
1804 View3D *v3d= CTX_wm_view3d(C);
1807 Base *baspar, *basact= CTX_data_active_base(C);
1809 if (!basact || !(basact->object->parent)) return 0; /* we know OBACT is valid */
1811 baspar= object_in_scene(basact->object->parent, scene);
1813 /* can be NULL if parent in other scene */
1814 if(baspar && BASE_SELECTABLE(v3d, baspar)) {
1815 ED_base_object_select(basact, BA_DESELECT);
1816 ED_base_object_select(baspar, BA_SELECT);
1817 ED_base_object_activate(C, baspar);
1824 #define GROUP_MENU_MAX 24
1825 static short select_grouped_group(bContext *C, Object *ob) /* Select objects in the same group as the active */
1828 Group *group, *ob_groups[GROUP_MENU_MAX];
1829 //char str[10 + (24*GROUP_MENU_MAX)];
1831 int group_count=0; //, menu, i;
1833 for ( group=G.main->group.first;
1834 group && group_count < GROUP_MENU_MAX;
1835 group=group->id.next
1837 if (object_in_group (ob, group)) {
1838 ob_groups[group_count] = group;
1846 else if (group_count == 1) {
1847 group = ob_groups[0];
1848 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1849 if (!(base->flag & SELECT) && object_in_group(base->object, group)) {
1850 ED_base_object_select(base, BA_SELECT);
1857 #if 0 // XXX hows this work in 2.5?
1858 /* build the menu. */
1859 p += sprintf(str, "Groups%%t");
1860 for (i=0; i<group_count; i++) {
1861 group = ob_groups[i];
1862 p += sprintf (p, "|%s%%x%i", group->id.name+2, i);
1865 menu = pupmenu (str);
1869 group = ob_groups[menu];
1870 for (base= FIRSTBASE; base; base= base->next) {
1871 if (!(base->flag & SELECT) && object_in_group(base->object, group)) {
1872 ED_base_object_select(base, BA_SELECT);
1880 static short select_grouped_object_hooks(bContext *C, Object *ob)
1882 Scene *scene= CTX_data_scene(C);
1883 View3D *v3d= CTX_wm_view3d(C);
1888 HookModifierData *hmd;
1890 for (md = ob->modifiers.first; md; md=md->next) {
1891 if (md->type==eModifierType_Hook) {
1892 hmd= (HookModifierData*) md;
1893 if (hmd->object && !(hmd->object->flag & SELECT)) {
1894 base= object_in_scene(hmd->object, scene);
1895 if (base && (BASE_SELECTABLE(v3d, base))) {
1896 ED_base_object_select(base, BA_SELECT);
1905 /* Select objects woth the same parent as the active (siblings),
1906 * parent can be NULL also */
1907 static short select_grouped_siblings(bContext *C, Object *ob)
1911 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1912 if ((base->object->parent==ob->parent) && !(base->flag & SELECT)) {
1913 ED_base_object_select(base, BA_SELECT);
1921 static short select_grouped_type(bContext *C, Object *ob)
1925 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1926 if ((base->object->type == ob->type) && !(base->flag & SELECT)) {
1927 ED_base_object_select(base, BA_SELECT);
1935 static short select_grouped_layer(bContext *C, Object *ob)
1939 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1940 if ((base->lay & ob->lay) && !(base->flag & SELECT)) {
1941 ED_base_object_select(base, BA_SELECT);
1949 static short select_grouped_index_object(bContext *C, Object *ob)
1953 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1954 if ((base->object->index == ob->index) && !(base->flag & SELECT)) {
1955 ED_base_object_select(base, BA_SELECT);
1963 static short select_grouped_color(bContext *C, Object *ob)
1967 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1968 if (!(base->flag & SELECT) && (FloatCompare(base->object->col, ob->col, 0.005f))) {
1969 ED_base_object_select(base, BA_SELECT);
1977 static short objects_share_gameprop(Object *a, Object *b)
1980 /*make a copy of all its properties*/
1982 for( prop= a->prop.first; prop; prop = prop->next ) {
1983 if ( get_ob_property(b, prop->name) )
1989 static short select_grouped_gameprops(bContext *C, Object *ob)
1993 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1994 if (!(base->flag & SELECT) && (objects_share_gameprop(base->object, ob))) {
1995 ED_base_object_select(base, BA_SELECT);
2003 static int object_select_grouped_exec(bContext *C, wmOperator *op)
2005 Scene *scene= CTX_data_scene(C);
2007 int nr = RNA_enum_get(op->ptr, "type");
2008 short changed = 0, seltype;
2010 seltype = RNA_enum_get(op->ptr, "seltype");
2013 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2014 ED_base_object_select(base, BA_DESELECT);
2021 BKE_report(op->reports, RPT_ERROR, "No Active Object");
2022 return OPERATOR_CANCELLED;
2025 if(nr==1) changed = select_grouped_children(C, ob, 1);
2026 else if(nr==2) changed = select_grouped_children(C, ob, 0);
2027 else if(nr==3) changed = select_grouped_parent(C);
2028 else if(nr==4) changed = select_grouped_siblings(C, ob);
2029 else if(nr==5) changed = select_grouped_type(C, ob);
2030 else if(nr==6) changed = select_grouped_layer(C, ob);
2031 else if(nr==7) changed = select_grouped_group(C, ob);
2032 else if(nr==8) changed = select_grouped_object_hooks(C, ob);
2033 else if(nr==9) changed = select_grouped_index_object(C, ob);
2034 else if(nr==10) changed = select_grouped_color(C, ob);
2035 else if(nr==11) changed = select_grouped_gameprops(C, ob);
2038 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2039 return OPERATOR_FINISHED;
2042 return OPERATOR_CANCELLED;
2045 void OBJECT_OT_select_grouped(wmOperatorType *ot)
2048 ot->name= "Select Grouped";
2049 ot->description = "Select all visible objects grouped by various properties.";
2050 ot->idname= "OBJECT_OT_select_grouped";
2053 ot->invoke= WM_menu_invoke;
2054 ot->exec= object_select_grouped_exec;
2055 ot->poll= ED_operator_scene_editable;
2058 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2060 RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
2061 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
2065 /* ****** selection by layer *******/
2067 static int object_select_by_layer_exec(bContext *C, wmOperator *op)
2069 unsigned int layernum;
2072 seltype = RNA_enum_get(op->ptr, "seltype");
2073 layernum = RNA_int_get(op->ptr, "layer");
2076 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2077 ED_base_object_select(base, BA_DESELECT);
2082 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2083 if(base->lay == (1<< (layernum -1)))
2084 ED_base_object_select(base, BA_SELECT);
2089 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2091 return OPERATOR_FINISHED;
2094 void OBJECT_OT_select_by_layer(wmOperatorType *ot)
2097 ot->name= "select by layer";
2098 ot->description = "Select all visible objects on a layer.";
2099 ot->idname= "OBJECT_OT_select_by_layer";
2102 /*ot->invoke = XXX - need a int grid popup*/
2103 ot->exec= object_select_by_layer_exec;
2104 ot->poll= ED_operator_scene_editable;
2107 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2109 RNA_def_int(ot->srna, "layer", 1, 1, 20, "Layer", "", 1, 20);
2110 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
2113 /* ****** invert selection *******/
2114 static int object_select_inverse_exec(bContext *C, wmOperator *op)
2116 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2117 if (base->flag & SELECT)
2118 ED_base_object_select(base, BA_DESELECT);
2120 ED_base_object_select(base, BA_SELECT);
2125 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2127 return OPERATOR_FINISHED;
2130 void OBJECT_OT_select_inverse(wmOperatorType *ot)
2134 ot->name= "Select Inverse";
2135 ot->description = "Invert selection of all visible objects.";
2136 ot->idname= "OBJECT_OT_select_inverse";
2139 ot->exec= object_select_inverse_exec;
2140 ot->poll= ED_operator_scene_editable;
2143 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2146 /* ****** (de)select All *******/
2148 static int object_select_de_select_all_exec(bContext *C, wmOperator *op)
2153 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2154 if (base->flag & SELECT) {
2162 if (!ok) return OPERATOR_PASS_THROUGH;
2164 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2165 if (a) ED_base_object_select(base, BA_DESELECT);
2166 else ED_base_object_select(base, BA_SELECT);
2171 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2173 return OPERATOR_FINISHED;
2176 void OBJECT_OT_select_all_toggle(wmOperatorType *ot)
2180 ot->name= "deselect all";
2181 ot->description = "(de)select all visible objects in scene.";
2182 ot->idname= "OBJECT_OT_select_all_toggle";
2185 ot->exec= object_select_de_select_all_exec;
2186 ot->poll= ED_operator_scene_editable;
2189 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2192 /* ****** random selection *******/
2194 static int object_select_random_exec(bContext *C, wmOperator *op)
2199 seltype = RNA_enum_get(op->ptr, "seltype");
2202 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2203 ED_base_object_select(base, BA_DESELECT);
2207 percent = RNA_float_get(op->ptr, "percent");
2209 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2210 if (BLI_frand() < percent) {
2211 ED_base_object_select(base, BA_SELECT);
2216 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2218 return OPERATOR_FINISHED;
2221 void OBJECT_OT_select_random(wmOperatorType *ot)
2224 ot->name= "Random select";
2225 ot->description = "Set select on random visible objects.";
2226 ot->idname= "OBJECT_OT_select_random";
2229 /*ot->invoke= object_select_random_invoke XXX - need a number popup ;*/
2230 ot->exec = object_select_random_exec;
2231 ot->poll= ED_operator_scene_editable;
2234 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2236 RNA_def_float_percentage(ot->srna, "percent", 0.5f, 0.0f, 1.0f, "Percent", "percentage of objects to randomly select", 0.0001f, 1.0f);
2237 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
2240 /* ******** Clear object Translation *********** */
2242 static int object_location_clear_exec(bContext *C, wmOperator *op)
2244 int armature_clear= 0;
2246 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2247 if(!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
2248 if ((ob->protectflag & OB_LOCK_LOCX)==0)
2249 ob->loc[0]= ob->dloc[0]= 0.0f;
2250 if ((ob->protectflag & OB_LOCK_LOCY)==0)
2251 ob->loc[1]= ob->dloc[1]= 0.0f;
2252 if ((ob->protectflag & OB_LOCK_LOCZ)==0)
2253 ob->loc[2]= ob->dloc[2]= 0.0f;
2255 ob->recalc |= OB_RECALC_OB;
2259 if(armature_clear==0) /* in this case flush was done */
2260 ED_anim_dag_flush_update(C);
2262 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2264 return OPERATOR_FINISHED;
2268 void OBJECT_OT_location_clear(wmOperatorType *ot)
2272 ot->name= "Clear Location";
2273 ot->description = "Clear the object's location.";
2274 ot->idname= "OBJECT_OT_location_clear";
2277 ot->invoke= WM_operator_confirm;
2278 ot->exec= object_location_clear_exec;
2279 ot->poll= ED_operator_object_active;
2282 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2285 static int object_rotation_clear_exec(bContext *C, wmOperator *op)
2287 int armature_clear= 0;
2289 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2290 if(!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
2291 /* eulers can only get cleared if they are not protected */
2292 if ((ob->protectflag & OB_LOCK_ROTX)==0)
2293 ob->rot[0]= ob->drot[0]= 0.0f;
2294 if ((ob->protectflag & OB_LOCK_ROTY)==0)
2295 ob->rot[1]= ob->drot[1]= 0.0f;
2296 if ((ob->protectflag & OB_LOCK_ROTZ)==0)
2297 ob->rot[2]= ob->drot[2]= 0.0f;
2299 ob->recalc |= OB_RECALC_OB;
2303 if(armature_clear==0) /* in this case flush was done */
2304 ED_anim_dag_flush_update(C);
2306 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2308 return OPERATOR_FINISHED;
2312 void OBJECT_OT_rotation_clear(wmOperatorType *ot)
2316 ot->name= "Clear Rotation";
2317 ot->description = "Clear the object's rotation.";
2318 ot->idname= "OBJECT_OT_rotation_clear";
2321 ot->invoke= WM_operator_confirm;
2322 ot->exec= object_rotation_clear_exec;
2323 ot->poll= ED_operator_object_active;
2326 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2329 static int object_scale_clear_exec(bContext *C, wmOperator *op)
2331 int armature_clear= 0;
2333 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2334 if(!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
2335 if ((ob->protectflag & OB_LOCK_SCALEX)==0) {
2339 if ((ob->protectflag & OB_LOCK_SCALEY)==0) {
2343 if ((ob->protectflag & OB_LOCK_SCALEZ)==0) {
2348 ob->recalc |= OB_RECALC_OB;
2352 if(armature_clear==0) /* in this case flush was done */
2353 ED_anim_dag_flush_update(C);
2355 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2357 return OPERATOR_FINISHED;
2360 void OBJECT_OT_scale_clear(wmOperatorType *ot)
2364 ot->name= "Clear Scale";
2365 ot->description = "Clear the object's scale.";
2366 ot->idname= "OBJECT_OT_scale_clear";
2369 ot->invoke= WM_operator_confirm;
2370 ot->exec= object_scale_clear_exec;
2371 ot->poll= ED_operator_object_active;
2374 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2377 static int object_origin_clear_exec(bContext *C, wmOperator *op)
2379 float *v1, *v3, mat[3][3];
2380 int armature_clear= 0;
2382 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2385 v3= ob->parentinv[3];
2387 Mat3CpyMat4(mat, ob->parentinv);
2392 Mat3MulVecfl(mat, v3);
2394 ob->recalc |= OB_RECALC_OB;
2398 if(armature_clear==0) /* in this case flush was done */
2399 ED_anim_dag_flush_update(C);
2401 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2403 return OPERATOR_FINISHED;
2406 void OBJECT_OT_origin_clear(wmOperatorType *ot)
2410 ot->name= "Clear Origin";
2411 ot->description = "Clear the object's origin.";
2412 ot->idname= "OBJECT_OT_origin_clear";
2415 ot->invoke= WM_operator_confirm;
2416 ot->exec= object_origin_clear_exec;
2417 ot->poll= ED_operator_object_active;
2420 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2423 /* ********* clear/set restrict view *********/
2424 static int object_restrictview_clear_exec(bContext *C, wmOperator *op)
2426 ScrArea *sa= CTX_wm_area(C);
2427 View3D *v3d= sa->spacedata.first;
2428 Scene *scene= CTX_data_scene(C);
2432 /* XXX need a context loop to handle such cases */
2433 for(base = FIRSTBASE; base; base=base->next){
2434 if((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
2435 base->flag |= SELECT;
2436 base->object->flag = base->flag;
2437 base->object->restrictflag &= ~OB_RESTRICT_VIEW;
2442 DAG_scene_sort(scene);
2443 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
2446 return OPERATOR_FINISHED;
2449 void OBJECT_OT_restrictview_clear(wmOperatorType *ot)
2453 ot->name= "Clear Restrict View";
2454 ot->description = "Reveal the object by setting the restrictview flag.";
2455 ot->idname= "OBJECT_OT_restrictview_clear";
2458 ot->exec= object_restrictview_clear_exec;
2459 ot->poll= ED_operator_view3d_active;
2462 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2465 static int object_restrictview_set_exec(bContext *C, wmOperator *op)
2467 Scene *scene= CTX_data_scene(C);
2469 int unselected= RNA_boolean_get(op->ptr, "unselected");
2471 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2473 if (base->flag & SELECT){
2474 base->flag &= ~SELECT;
2475 base->object->flag = base->flag;
2476 base->object->restrictflag |= OB_RESTRICT_VIEW;
2479 ED_base_object_activate(C, NULL);
2484 if (!(base->flag & SELECT)){
2485 base->object->restrictflag |= OB_RESTRICT_VIEW;
2493 DAG_scene_sort(scene);
2495 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2499 return OPERATOR_FINISHED;
2502 void OBJECT_OT_restrictview_set(wmOperatorType *ot)
2505 ot->name= "Set Restrict View";
2506 ot->description = "Hide the object by setting the restrictview flag.";
2507 ot->idname= "OBJECT_OT_restrictview_set";
2510 ot->exec= object_restrictview_set_exec;
2511 ot->poll= ED_operator_view3d_active;
2514 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2516 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects.");
2519 /* ************* Slow Parent ******************* */
2520 static int object_slowparent_set_exec(bContext *C, wmOperator *op)
2523 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2525 if(base->object->parent) base->object->partype |= PARSLOW;
2526 base->object->recalc |= OB_RECALC_OB;
2531 ED_anim_dag_flush_update(C);
2533 WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
2535 return OPERATOR_FINISHED;
2538 void OBJECT_OT_slowparent_set(wmOperatorType *ot)
2542 ot->name= "Set Slow Parent";
2543 ot->description = "Set the object's slow parent.";
2544 ot->idname= "OBJECT_OT_slow_parent_set";
2547 ot->invoke= WM_operator_confirm;
2548 ot->exec= object_slowparent_set_exec;
2549 ot->poll= ED_operator_view3d_active;
2552 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2555 static int object_slowparent_clear_exec(bContext *C, wmOperator *op)
2557 Scene *scene= CTX_data_scene(C);
2559 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2560 if(base->object->parent) {
2561 if(base->object->partype & PARSLOW) {
2562 base->object->partype -= PARSLOW;
2563 where_is_object(scene, base->object);
2564 base->object->partype |= PARSLOW;
2565 base->object->recalc |= OB_RECALC_OB;
2572 ED_anim_dag_flush_update(C);
2574 WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
2576 return OPERATOR_FINISHED;
2579 void OBJECT_OT_slowparent_clear(wmOperatorType *ot)
2583 ot->name= "Clear Slow Parent";
2584 ot->description = "Clear the object's slow parent.";
2585 ot->idname= "OBJECT_OT_slow_parent_clear";
2588 ot->invoke= WM_operator_confirm;
2589 ot->exec= object_slowparent_clear_exec;
2590 ot->poll= ED_operator_view3d_active;
2593 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2595 /* ******************** **************** */
2598 #define BEZSELECTED_HIDDENHANDLES(bezt) ((G.f & G_HIDDENHANDLES) ? (bezt)->f2 & SELECT : BEZSELECTED(bezt))
2599 /* only in edit mode */
2600 void make_vertex_parent(Scene *scene, Object *obedit, View3D *v3d)
2608 int a, v1=0, v2=0, v3=0, v4=0, nr=1;
2610 /* we need 1 to 3 selected vertices */
2612 if(obedit->type==OB_MESH) {
2613 Mesh *me= obedit->data;
2614 EditMesh *em = BKE_mesh_get_editmesh(me);
2616 eve= em->verts.first;
2620 else if(v2==0) v2= nr;
2621 else if(v3==0) v3= nr;
2622 else if(v4==0) v4= nr;
2629 BKE_mesh_end_editmesh(me, em);
2631 else if(ELEM(obedit->type, OB_SURF, OB_CURVE)) {
2632 ListBase *editnurb= curve_get_editcurve(obedit);
2634 nu= editnurb->first;
2636 if((nu->type & 7)==CU_BEZIER) {
2640 if(BEZSELECTED_HIDDENHANDLES(bezt)) {
2642 else if(v2==0) v2= nr;
2643 else if(v3==0) v3= nr;
2644 else if(v4==0) v4= nr;
2653 a= nu->pntsu*nu->pntsv;
2655 if(bp->f1 & SELECT) {
2657 else if(v2==0) v2= nr;
2658 else if(v3==0) v3= nr;
2659 else if(v4==0) v4= nr;
2669 else if(obedit->type==OB_LATTICE) {
2670 Lattice *lt= obedit->data;
2672 a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
2673 bp= lt->editlatt->def;
2675 if(bp->f1 & SELECT) {
2677 else if(v2==0) v2= nr;
2678 else if(v3==0) v3= nr;
2679 else if(v4==0) v4= nr;
2687 if(v4 || !((v1 && v2==0 && v3==0) || (v1 && v2 && v3)) ) {
2688 error("Select either 1 or 3 vertices to parent to");
2692 if(okee("Make vertex parent")==0) return;
2694 for(base= FIRSTBASE; base; base= base->next) {
2695 if(TESTBASELIB(v3d, base)) {
2699 ob->recalc |= OB_RECALC;
2700 par= BASACT->object->parent;
2707 error("Loop in parents");
2712 ob->parent= BASACT->object;
2714 ob->partype= PARVERT3;
2719 /* inverse parent matrix */
2720 what_does_parent(scene, ob, &workob);
2721 Mat4Invert(ob->parentinv, workob.obmat);
2724 ob->partype= PARVERT1;
2727 /* inverse parent matrix */
2728 what_does_parent(scene, ob, &workob);
2729 Mat4Invert(ob->parentinv, workob.obmat);
2736 DAG_scene_sort(scene);
2740 /* ******************** make proxy operator *********************** */
2742 /* present menu listing the possible objects within the group to proxify */
2743 static void proxy_group_objects_menu (bContext *C, wmOperator *op, Object *ob, Group *group)
2750 /* check if there are any objects within the group to assign for */
2751 for (go= group->gobject.first; go; go= go->next) {
2756 /* now create the menu to draw */
2757 pup= uiPupMenuBegin(C, "Make Proxy For:", 0);
2758 layout= uiPupMenuLayout(pup);
2760 for (go= group->gobject.first; go; go= go->next) {
2762 PointerRNA props_ptr;
2764 /* create operator menu item with relevant properties filled in */
2765 props_ptr= uiItemFullO(layout, go->ob->id.name+2, 0, op->idname, NULL, WM_OP_EXEC_REGION_WIN, UI_ITEM_O_RETURN_PROPS);
2766 RNA_string_set(&props_ptr, "object", go->ob->id.name+2);
2767 RNA_string_set(&props_ptr, "group_object", go->ob->id.name+2);
2771 /* display the menu, and be done */
2772 uiPupMenuEnd(C, pup);
2775 /* set the object to proxify */
2776 static int make_proxy_invoke (bContext *C, wmOperator *op, wmEvent *evt)
2778 Scene *scene= CTX_data_scene(C);
2779 Object *ob= CTX_data_active_object(C);
2782 if (!scene || scene->id.lib || !ob)
2783 return OPERATOR_CANCELLED;
2785 /* Get object to work on - use a menu if we need to... */
2786 if (ob->dup_group && ob->dup_group->id.lib) {
2787 /* gives menu with list of objects in group */
2788 proxy_group_objects_menu(C, op, ob, ob->dup_group);
2790 else if (ob->id.lib) {
2791 uiPopupMenu *pup= uiPupMenuBegin(C, "OK?", ICON_QUESTION);
2792 uiLayout *layout= uiPupMenuLayout(pup);
2793 PointerRNA props_ptr;
2795 /* create operator menu item with relevant properties filled in */
2796 props_ptr= uiItemFullO(layout, op->type->name, 0, op->idname, props_ptr.data, WM_OP_EXEC_REGION_WIN, UI_ITEM_O_RETURN_PROPS);
2797 RNA_string_set(&props_ptr, "object", ob->id.name+2);
2799 /* present the menu and be done... */
2800 uiPupMenuEnd(C, pup);
2803 /* error.. cannot continue */
2804 BKE_report(op->reports, RPT_ERROR, "Can only make proxy for a referenced object or group");
2807 /* this invoke just calls another instance of this operator... */
2808 return OPERATOR_CANCELLED;
2811 static int make_proxy_exec (bContext *C, wmOperator *op)
2813 Object *ob=NULL, *gob=NULL;
2814 Scene *scene= CTX_data_scene(C);
2815 char ob_name[21], gob_name[21];
2817 /* get object and group object
2819 * - then pointers from context
2821 RNA_string_get(op->ptr, "object", ob_name);
2822 RNA_string_get(op->ptr, "group_object", gob_name);
2828 /* active object is group object... */
2829 // FIXME: we should get the nominated name instead
2830 gob= CTX_data_active_object(C);
2831 group= gob->dup_group;
2833 /* find the object to affect */
2834 for (go= group->gobject.first; go; go= go->next) {
2835 if ((go->ob) && strcmp(go->ob->id.name+2, gob_name)==0) {
2842 /* just use the active object for now */
2843 // FIXME: we should get the nominated name instead
2844 ob= CTX_data_active_object(C);
2849 Base *newbase, *oldbase= BASACT;
2852 /* Add new object for the proxy */
2853 newob= add_object(scene, OB_EMPTY);
2855 strcpy(name, gob->id.name+2);
2857 strcpy(name, ob->id.name+2);
2858 strcat(name, "_proxy");
2859 rename_id(&newob->id, name);
2862 newbase= BASACT; /* add_object sets active... */
2863 newbase->lay= oldbase->lay;
2864 newob->lay= newbase->lay;
2866 /* remove base, leave user count of object, it gets linked in object_make_proxy */
2868 BLI_remlink(&scene->base, oldbase);
2872 object_make_proxy(newob, ob, gob);
2874 /* depsgraph flushes are needed for the new data */
2875 DAG_scene_sort(scene);
2876 DAG_object_flush_update(scene, newob, OB_RECALC);
2878 WM_event_add_notifier(C, NC_OBJECT, NULL);
2881 BKE_report(op->reports, RPT_ERROR, "No object to make proxy for");
2882 return OPERATOR_CANCELLED;
2885 return OPERATOR_FINISHED;
2888 void OBJECT_OT_proxy_make (wmOperatorType *ot)
2891 ot->name= "Make Proxy";
2892 ot->idname= "OBJECT_OT_proxy_make";
2893 ot->description= "Add empty object to become local replacement data of a library-linked object";
2896 ot->invoke= make_proxy_invoke;
2897 ot->exec= make_proxy_exec;
2898 ot->poll= ED_operator_object_active;
2901 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2904 RNA_def_string(ot->srna, "object", "", 19, "Proxy Object", "Name of lib-linked/grouped object to make a proxy for.");
2905 RNA_def_string(ot->srna, "group_object", "", 19, "Group Object", "Name of group instancer (if applicable).");
2908 /* ******************** make parent operator *********************** */
2910 #define PAR_OBJECT 0
2911 #define PAR_ARMATURE 1
2912 #define PAR_ARMATURE_NAME 2
2913 #define PAR_ARMATURE_ENVELOPE 3
2914 #define PAR_ARMATURE_AUTO 4
2917 #define PAR_FOLLOW 7
2918 #define PAR_PATH_CONST 8
2919 #define PAR_LATTICE 9
2920 #define PAR_VERTEX 10
2923 static EnumPropertyItem prop_make_parent_types[] = {
2924 {PAR_OBJECT, "OBJECT", 0, "Object", ""},
2925 {PAR_ARMATURE, "ARMATURE", 0, "Armature Deform", ""},
2926 {PAR_ARMATURE_NAME, "ARMATURE_NAME", 0, " With Empty Groups", ""},
2927 {PAR_ARMATURE_AUTO, "ARMATURE_AUTO", 0, " With Automatic Weights", ""},
2928 {PAR_ARMATURE_ENVELOPE, "ARMATURE_ENVELOPE", 0, " With Envelope Weights", ""},
2929 {PAR_BONE, "BONE", 0, "Bone", ""},
2930 {PAR_CURVE, "CURVE", 0, "Curve Deform", ""},
2931 {PAR_FOLLOW, "FOLLOW", 0, "Follow Path", ""},
2932 {PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""},
2933 {PAR_LATTICE, "LATTICE", 0, "Lattice Deform", ""},
2934 {PAR_VERTEX, "VERTEX", 0, "Vertex", ""},
2935 {PAR_TRIA, "TRIA", 0, "Triangle", ""},
2936 {0, NULL, 0, NULL, NULL}
2939 static int test_parent_loop(Object *par, Object *ob)
2941 /* test if 'ob' is a parent somewhere in par's parents */
2943 if(par == NULL) return 0;
2944 if(ob == par) return 1;
2946 return test_parent_loop(par->parent, ob);
2949 void ED_object_parent(Object *ob, Object *par, int type, const char *substr)
2951 if(!par || test_parent_loop(par, ob)) {
2953 ob->partype= PAROBJECT;
2954 ob->parsubstr[0]= 0;
2958 /* this could use some more checks */
2961 ob->partype &= ~PARTYPE;
2962 ob->partype |= type;
2963 BLI_strncpy(ob->parsubstr, substr, sizeof(ob->parsubstr));
2966 static int parent_set_exec(bContext *C, wmOperator *op)
2968 Scene *scene= CTX_data_scene(C);
2969 Object *par= CTX_data_active_object(C);
2970 bPoseChannel *pchan= NULL;
2971 int partype= RNA_enum_get(op->ptr, "type");
2972 int pararm= ELEM4(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
2974 par->recalc |= OB_RECALC_OB;
2977 if(partype==PAR_FOLLOW || partype==PAR_PATH_CONST) {
2978 if(par->type!=OB_CURVE)
2979 return OPERATOR_CANCELLED;
2981 Curve *cu= par->data;
2983 if((cu->flag & CU_PATH)==0) {
2984 cu->flag |= CU_PATH|CU_FOLLOW;
2985 makeDispListCurveTypes(scene, par, 0); /* force creation of path data */
2987 else cu->flag |= CU_FOLLOW;
2989 /* fall back on regular parenting now */
2990 partype= PAR_OBJECT;
2993 else if(partype==PAR_BONE) {
2994 pchan= get_active_posechannel(par);
2997 error("No active Bone");
2998 return OPERATOR_CANCELLED;
3002 /* context itterator */
3003 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
3007 if( test_parent_loop(par, ob) ) {
3008 error("Loop in parents");
3013 /* apply transformation of previous parenting */
3014 ED_object_apply_obmat(ob);
3020 strcpy (ob->parsubstr, pchan->name);
3022 ob->parsubstr[0]= 0;
3025 if(partype==PAR_PATH_CONST) {
3027 bFollowPathConstraint *data;
3028 float cmat[4][4], vec[3];
3030 con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
3031 strcpy (con->name, "AutoPath");
3036 add_constraint_to_object(con, ob);
3038 get_constraint_target_matrix(con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra - give_timeoffset(ob));
3039 VecSubf(vec, ob->obmat[3], cmat[3]);
3041 ob->loc[0] = vec[0];
3042 ob->loc[1] = vec[1];
3044 else if(pararm && ob->type==OB_MESH && par->type == OB_ARMATURE) {
3045 if(partype == PAR_ARMATURE_NAME)
3046 create_vgroups_from_armature(scene, ob, par, ARM_GROUPS_NAME);
3047 else if(partype == PAR_ARMATURE_ENVELOPE)
3048 create_vgroups_from_armature(scene, ob, par, ARM_GROUPS_ENVELOPE);
3049 else if(partype == PAR_ARMATURE_AUTO)
3050 create_vgroups_from_armature(scene, ob, par, ARM_GROUPS_AUTO);
3052 /* get corrected inverse */
3053 ob->partype= PAROBJECT;
3054 what_does_parent(scene, ob, &workob);
3056 ob->partype= PARSKEL;
3058 Mat4Invert(ob->parentinv, workob.obmat);
3061 /* calculate inverse parent matrix */
3062 what_does_parent(scene, ob, &workob);
3063 Mat4Invert(ob->parentinv, workob.obmat);
3066 ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
3068 if( ELEM(partype, PAR_CURVE, PAR_LATTICE) || pararm )
3069 ob->partype= PARSKEL; /* note, dna define, not operator property */
3071 ob->partype= PAROBJECT; /* note, dna define, not operator property */
3077 DAG_scene_sort(CTX_data_scene(C));
3078 ED_anim_dag_flush_update(C);
3079 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
3081 return OPERATOR_FINISHED;
3084 static int parent_set_invoke(bContext *C, wmOperator *op, wmEvent *event)
3086 Object *ob= CTX_data_active_object(C);
3087 uiPopupMenu *pup= uiPupMenuBegin(C, "Set Parent To", 0);
3088 uiLayout *layout= uiPupMenuLayout(pup);
3090 uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
3091 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_OBJECT);
3093 /* ob becomes parent, make the associated menus */
3094 if(ob->type==OB_ARMATURE) {
3095 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE);
3096 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE_NAME);
3097 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE_ENVELOPE);
3098 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE_AUTO);
3099 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_BONE);
3101 else if(ob->type==OB_CURVE) {
3102 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_CURVE);
3103 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_FOLLOW);
3104 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_PATH_CONST);
3106 else if(ob->type == OB_LATTICE) {
3107 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_LATTICE);
3110 uiPupMenuEnd(C, pup);
3112 return OPERATOR_CANCELLED;
3116 void OBJECT_OT_parent_set(wmOperatorType *ot)
3119 ot->name= "Make Parent";
3120 ot->description = "Set the object's parenting.";
3121 ot->idname= "OBJECT_OT_parent_set";
3124 ot->invoke= parent_set_invoke;
3125 ot->exec= parent_set_exec;
3127 ot->poll= ED_operator_object_active;
3130 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
3132 RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
3135 /* *** make track ***** */
3136 static EnumPropertyItem prop_make_track_types[] = {
3137 {1, "TRACKTO", 0, "TrackTo Constraint", ""},
3138 {2, "LOCKTRACK", 0, "LockTrack Constraint", ""},
3139 {3, "OLDTRACK", 0, "Old Track", ""},
3140 {0, NULL, 0, NULL, NULL}
3143 static int track_set_exec(bContext *C, wmOperator *op)
3145 Scene *scene= CTX_data_scene(C);
3146 int type= RNA_enum_get(op->ptr, "type");
3150 bTrackToConstraint *data;
3152 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
3154 con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
3155 strcpy (con->name, "AutoTrack");
3158 data->tar = BASACT->object;
3159 base->object->recalc |= OB_RECALC;
3161 /* Lamp and Camera track differently by default */
3162 if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
3163 data->reserved1 = TRACK_nZ;
3164 data->reserved2 = UP_Y;
3167 add_constraint_to_object(con, base->object);
3172 else if(type == 2) {
3174 bLockTrackConstraint *data;
3176 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
3178 con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
3179 strcpy (con->name, "AutoTrack");
3182 data->tar = BASACT->object;
3183 base->object->recalc |= OB_RECALC;
3185 /* Lamp and Camera track differently by default */
3186 if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
3187 data->trackflag = TRACK_nZ;
3188 data->lockflag = LOCK_Y;
3191 add_constraint_to_object(con, base->object);
3197 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {