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 object_hook_select(obedit, hmd);
1389 else if(mode==6) { /* clear offset */
1390 where_is_object(scene, ob); /* ob is hook->parent */
1392 Mat4Invert(ob->imat, ob->obmat);
1393 /* this call goes from right to left... */
1394 Mat4MulSerie(hmd->parentinv, ob->imat, obedit->obmat, NULL,
1395 NULL, NULL, NULL, NULL, NULL);
1398 DAG_scene_sort(scene);
1402 /* use this when the loc/size/rot of the parent has changed but the children should stay in the same place
1403 * apply-size-rot or object center for eg */
1404 static void ignore_parent_tx(Scene *scene, Object *ob )
1409 /* a change was made, adjust the children to compensate */
1410 for (ob_child=G.main->object.first; ob_child; ob_child=ob_child->id.next) {
1411 if (ob_child->parent == ob) {
1412 ED_object_apply_obmat(ob_child);
1413 what_does_parent(scene, ob_child, &workob);
1414 Mat4Invert(ob_child->parentinv, workob.obmat);
1420 void add_hook_menu(Scene *scene, View3D *v3d)
1422 Object *obedit= scene->obedit; // XXX get from context
1425 if(obedit==NULL) return;
1427 if(modifiers_findByType(obedit, eModifierType_Hook))
1428 mode= pupmenu("Hooks %t|Add, To New Empty %x1|Add, To Selected Object %x2|Remove... %x3|Reassign... %x4|Select... %x5|Clear Offset...%x6");
1430 mode= pupmenu("Hooks %t|Add, New Empty %x1|Add, To Selected Object %x2");
1435 add_hook(scene, v3d, mode);
1438 /* ******************** clear parent operator ******************* */
1440 static EnumPropertyItem prop_clear_parent_types[] = {
1441 {0, "CLEAR", 0, "Clear Parent", ""},
1442 {1, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation (Clear Track)", ""},
1443 {2, "CLEAR_INVERSE", 0, "Clear Parent Inverse", ""},
1444 {0, NULL, 0, NULL, NULL}
1447 /* note, poll should check for editable scene */
1448 static int parent_clear_exec(bContext *C, wmOperator *op)
1450 int type= RNA_enum_get(op->ptr, "type");
1452 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1457 else if(type == 1) {
1460 ED_object_apply_obmat(ob);
1463 Mat4One(ob->parentinv);
1465 ob->recalc |= OB_RECALC;
1469 DAG_scene_sort(CTX_data_scene(C));
1470 ED_anim_dag_flush_update(C);
1471 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
1473 return OPERATOR_FINISHED;
1476 void OBJECT_OT_parent_clear(wmOperatorType *ot)
1479 ot->name= "Clear Parent";
1480 ot->description = "Clear the object's parenting.";
1481 ot->idname= "OBJECT_OT_parent_clear";
1484 ot->invoke= WM_menu_invoke;
1485 ot->exec= parent_clear_exec;
1487 ot->poll= ED_operator_object_active;
1490 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1492 RNA_def_enum(ot->srna, "type", prop_clear_parent_types, 0, "Type", "");
1495 /* ******************** clear track operator ******************* */
1498 static EnumPropertyItem prop_clear_track_types[] = {
1499 {0, "CLEAR", 0, "Clear Track", ""},
1500 {1, "CLEAR_KEEP_TRANSFORM", 0, "Clear and Keep Transformation (Clear Track)", ""},
1501 {0, NULL, 0, NULL, NULL}
1504 /* note, poll should check for editable scene */
1505 static int object_track_clear_exec(bContext *C, wmOperator *op)
1507 int type= RNA_enum_get(op->ptr, "type");
1509 if(CTX_data_edit_object(C)) {
1510 BKE_report(op->reports, RPT_ERROR, "Operation cannot be performed in EditMode");
1511 return OPERATOR_CANCELLED;
1513 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
1515 ob->recalc |= OB_RECALC;
1518 ED_object_apply_obmat(ob);
1522 DAG_scene_sort(CTX_data_scene(C));
1523 ED_anim_dag_flush_update(C);
1525 return OPERATOR_FINISHED;
1528 void OBJECT_OT_track_clear(wmOperatorType *ot)
1531 ot->name= "Clear track";
1532 ot->description = "Clear tracking constraint or flag from object.";
1533 ot->idname= "OBJECT_OT_track_clear";
1536 ot->invoke= WM_menu_invoke;
1537 ot->exec= object_track_clear_exec;
1539 ot->poll= ED_operator_scene_editable;
1542 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1544 RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", "");
1547 /* *****************Selection Operators******************* */
1548 static EnumPropertyItem prop_select_types[] = {
1549 {0, "EXCLUSIVE", 0, "Exclusive", ""},
1550 {1, "EXTEND", 0, "Extend", ""},
1551 {0, NULL, 0, NULL, NULL}
1554 /* ****** Select by Type ****** */
1556 static int object_select_by_type_exec(bContext *C, wmOperator *op)
1558 short obtype, seltype;
1560 obtype = RNA_enum_get(op->ptr, "type");
1561 seltype = RNA_enum_get(op->ptr, "seltype");
1564 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1565 ED_base_object_select(base, BA_DESELECT);
1570 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1571 if(base->object->type==obtype) {
1572 ED_base_object_select(base, BA_SELECT);
1577 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
1579 return OPERATOR_FINISHED;
1582 void OBJECT_OT_select_by_type(wmOperatorType *ot)
1585 ot->name= "Select By Type";
1586 ot->description = "Select all visible objects that are of a type.";
1587 ot->idname= "OBJECT_OT_select_by_type";
1590 ot->invoke= WM_menu_invoke;
1591 ot->exec= object_select_by_type_exec;
1592 ot->poll= ED_operator_scene_editable;
1595 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1597 RNA_def_enum(ot->srna, "seltype", prop_select_types, 0, "Selection", "Extend selection or clear selection then select");
1598 RNA_def_enum(ot->srna, "type", prop_object_types, 1, "Type", "");
1601 /* ****** selection by links *******/
1603 static EnumPropertyItem prop_select_linked_types[] = {
1604 {1, "IPO", 0, "Object IPO", ""}, // XXX depreceated animation system stuff...
1605 {2, "OBDATA", 0, "Ob Data", ""},
1606 {3, "MATERIAL", 0, "Material", ""},
1607 {4, "TEXTURE", 0, "Texture", ""},
1608 {5, "DUPGROUP", 0, "Dupligroup", ""},
1609 {6, "PARTICLE", 0, "Particle System", ""},
1610 {0, NULL, 0, NULL, NULL}
1613 static int object_select_linked_exec(bContext *C, wmOperator *op)
1615 Scene *scene= CTX_data_scene(C);
1617 void *obdata = NULL;
1618 Material *mat = NULL, *mat1;
1621 int nr = RNA_enum_get(op->ptr, "type");
1622 short changed = 0, seltype;
1626 * Current Material: 3
1627 * Current Texture: 4
1632 seltype = RNA_enum_get(op->ptr, "seltype");
1635 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1636 ED_base_object_select(base, BA_DESELECT);
1643 BKE_report(op->reports, RPT_ERROR, "No Active Object");
1644 return OPERATOR_CANCELLED;
1648 // XXX old animation system
1650 //if(ipo==0) return OPERATOR_CANCELLED;
1651 return OPERATOR_CANCELLED;
1654 if(ob->data==0) return OPERATOR_CANCELLED;
1657 else if(nr==3 || nr==4) {
1658 mat= give_current_material(ob, ob->actcol);
1659 if(mat==0) return OPERATOR_CANCELLED;
1661 if(mat->mtex[ (int)mat->texact ]) tex= mat->mtex[ (int)mat->texact ]->tex;
1662 if(tex==0) return OPERATOR_CANCELLED;
1666 if(ob->dup_group==NULL) return OPERATOR_CANCELLED;
1669 if(ob->particlesystem.first==NULL) return OPERATOR_CANCELLED;
1671 else return OPERATOR_CANCELLED;
1673 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1675 // XXX old animation system
1676 //if(base->object->ipo==ipo) base->flag |= SELECT;
1680 if(base->object->data==obdata) base->flag |= SELECT;
1683 else if(nr==3 || nr==4) {
1686 for(a=1; a<=ob->totcol; a++) {
1687 mat1= give_current_material(ob, a);
1689 if(mat1==mat) base->flag |= SELECT;
1692 else if(mat1 && nr==4) {
1693 for(b=0; b<MAX_MTEX; b++) {
1695 if(tex==mat1->mtex[b]->tex) {
1696 base->flag |= SELECT;
1706 if(base->object->dup_group==ob->dup_group) {
1707 base->flag |= SELECT;
1712 /* loop through other, then actives particles*/
1713 ParticleSystem *psys;
1714 ParticleSystem *psys_act;
1716 for(psys=base->object->particlesystem.first; psys; psys=psys->next) {
1717 for(psys_act=ob->particlesystem.first; psys_act; psys_act=psys_act->next) {
1718 if (psys->part == psys_act->part) {
1719 base->flag |= SELECT;
1725 if (base->flag & SELECT) {
1730 base->object->flag= base->flag;
1735 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
1736 return OPERATOR_FINISHED;
1739 return OPERATOR_CANCELLED;
1742 void OBJECT_OT_select_linked(wmOperatorType *ot)
1745 ot->name= "Select Linked";
1746 ot->description = "Select all visible objects that are linked.";
1747 ot->idname= "OBJECT_OT_select_linked";
1750 ot->invoke= WM_menu_invoke;
1751 ot->exec= object_select_linked_exec;
1752 ot->poll= ED_operator_scene_editable;
1755 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1757 RNA_def_enum(ot->srna, "type", prop_select_linked_types, 0, "Type", "");
1758 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
1762 /* ****** selection grouped *******/
1764 static EnumPropertyItem prop_select_grouped_types[] = {
1765 {1, "CHILDREN_RECURSIVE", 0, "Children", ""}, // XXX depreceated animation system stuff...
1766 {2, "CHILDREN", 0, "Immediate Children", ""},
1767 {3, "PARENT", 0, "Parent", ""},
1768 {4, "SIBLINGS", 0, "Siblings", "Shared Parent"},
1769 {5, "TYPE", 0, "Type", "Shared object type"},
1770 {6, "LAYER", 0, "Layer", "Shared layers"},
1771 {7, "GROUP", 0, "Group", "Shared group"},
1772 {8, "HOOK", 0, "Hook", ""},
1773 {9, "PASS", 0, "Pass", "Render pass Index"},
1774 {10, "COLOR", 0, "Color", "Object Color"},
1775 {11, "PROPERTIES", 0, "Properties", "Game Properties"},
1776 {0, NULL, 0, NULL, NULL}
1780 static short select_grouped_children(bContext *C, Object *ob, int recursive)
1784 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1785 if (ob == base->object->parent) {
1786 if (!(base->flag & SELECT)) {
1787 ED_base_object_select(base, BA_SELECT);
1792 changed |= select_grouped_children(C, base->object, 1);
1799 static short select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */
1801 Scene *scene= CTX_data_scene(C);
1802 View3D *v3d= CTX_wm_view3d(C);
1805 Base *baspar, *basact= CTX_data_active_base(C);
1807 if (!basact || !(basact->object->parent)) return 0; /* we know OBACT is valid */
1809 baspar= object_in_scene(basact->object->parent, scene);
1811 /* can be NULL if parent in other scene */
1812 if(baspar && BASE_SELECTABLE(v3d, baspar)) {
1813 ED_base_object_select(basact, BA_DESELECT);
1814 ED_base_object_select(baspar, BA_SELECT);
1815 ED_base_object_activate(C, baspar);
1822 #define GROUP_MENU_MAX 24
1823 static short select_grouped_group(bContext *C, Object *ob) /* Select objects in the same group as the active */
1826 Group *group, *ob_groups[GROUP_MENU_MAX];
1827 //char str[10 + (24*GROUP_MENU_MAX)];
1829 int group_count=0; //, menu, i;
1831 for ( group=G.main->group.first;
1832 group && group_count < GROUP_MENU_MAX;
1833 group=group->id.next
1835 if (object_in_group (ob, group)) {
1836 ob_groups[group_count] = group;
1844 else if (group_count == 1) {
1845 group = ob_groups[0];
1846 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
1847 if (!(base->flag & SELECT) && object_in_group(base->object, group)) {
1848 ED_base_object_select(base, BA_SELECT);
1855 #if 0 // XXX hows this work in 2.5?
1856 /* build the menu. */
1857 p += sprintf(str, "Groups%%t");
1858 for (i=0; i<group_count; i++) {
1859 group = ob_groups[i];
1860 p += sprintf (p, "|%s%%x%i", group->id.name+2, i);
1863 menu = pupmenu (str);
1867 group = ob_groups[menu];
1868 for (base= FIRSTBASE; base; base= base->next) {
1869 if (!(base->flag & SELECT) && object_in_group(base->object, group)) {
1870 ED_base_object_select(base, BA_SELECT);
1878 static short select_grouped_object_hooks(bContext *C, Object *ob)
1880 Scene *scene= CTX_data_scene(C);
1881 View3D *v3d= CTX_wm_view3d(C);
1886 HookModifierData *hmd;
1888 for (md = ob->modifiers.first; md; md=md->next) {
1889 if (md->type==eModifierType_Hook) {
1890 hmd= (HookModifierData*) md;
1891 if (hmd->object && !(hmd->object->flag & SELECT)) {
1892 base= object_in_scene(hmd->object, scene);
1893 if (base && (BASE_SELECTABLE(v3d, base))) {
1894 ED_base_object_select(base, BA_SELECT);
1903 /* Select objects woth the same parent as the active (siblings),
1904 * parent can be NULL also */
1905 static short select_grouped_siblings(bContext *C, Object *ob)
1909 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1910 if ((base->object->parent==ob->parent) && !(base->flag & SELECT)) {
1911 ED_base_object_select(base, BA_SELECT);
1919 static short select_grouped_type(bContext *C, Object *ob)
1923 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1924 if ((base->object->type == ob->type) && !(base->flag & SELECT)) {
1925 ED_base_object_select(base, BA_SELECT);
1933 static short select_grouped_layer(bContext *C, Object *ob)
1937 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1938 if ((base->lay & ob->lay) && !(base->flag & SELECT)) {
1939 ED_base_object_select(base, BA_SELECT);
1947 static short select_grouped_index_object(bContext *C, Object *ob)
1951 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1952 if ((base->object->index == ob->index) && !(base->flag & SELECT)) {
1953 ED_base_object_select(base, BA_SELECT);
1961 static short select_grouped_color(bContext *C, Object *ob)
1965 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1966 if (!(base->flag & SELECT) && (FloatCompare(base->object->col, ob->col, 0.005f))) {
1967 ED_base_object_select(base, BA_SELECT);
1975 static short objects_share_gameprop(Object *a, Object *b)
1978 /*make a copy of all its properties*/
1980 for( prop= a->prop.first; prop; prop = prop->next ) {
1981 if ( get_ob_property(b, prop->name) )
1987 static short select_grouped_gameprops(bContext *C, Object *ob)
1991 CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
1992 if (!(base->flag & SELECT) && (objects_share_gameprop(base->object, ob))) {
1993 ED_base_object_select(base, BA_SELECT);
2001 static int object_select_grouped_exec(bContext *C, wmOperator *op)
2003 Scene *scene= CTX_data_scene(C);
2005 int nr = RNA_enum_get(op->ptr, "type");
2006 short changed = 0, seltype;
2008 seltype = RNA_enum_get(op->ptr, "seltype");
2011 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2012 ED_base_object_select(base, BA_DESELECT);
2019 BKE_report(op->reports, RPT_ERROR, "No Active Object");
2020 return OPERATOR_CANCELLED;
2023 if(nr==1) changed = select_grouped_children(C, ob, 1);
2024 else if(nr==2) changed = select_grouped_children(C, ob, 0);
2025 else if(nr==3) changed = select_grouped_parent(C);
2026 else if(nr==4) changed = select_grouped_siblings(C, ob);
2027 else if(nr==5) changed = select_grouped_type(C, ob);
2028 else if(nr==6) changed = select_grouped_layer(C, ob);
2029 else if(nr==7) changed = select_grouped_group(C, ob);
2030 else if(nr==8) changed = select_grouped_object_hooks(C, ob);
2031 else if(nr==9) changed = select_grouped_index_object(C, ob);
2032 else if(nr==10) changed = select_grouped_color(C, ob);
2033 else if(nr==11) changed = select_grouped_gameprops(C, ob);
2036 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2037 return OPERATOR_FINISHED;
2040 return OPERATOR_CANCELLED;
2043 void OBJECT_OT_select_grouped(wmOperatorType *ot)
2046 ot->name= "Select Grouped";
2047 ot->description = "Select all visible objects grouped by various properties.";
2048 ot->idname= "OBJECT_OT_select_grouped";
2051 ot->invoke= WM_menu_invoke;
2052 ot->exec= object_select_grouped_exec;
2053 ot->poll= ED_operator_scene_editable;
2056 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2058 RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
2059 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
2063 /* ****** selection by layer *******/
2065 static int object_select_by_layer_exec(bContext *C, wmOperator *op)
2067 unsigned int layernum;
2070 seltype = RNA_enum_get(op->ptr, "seltype");
2071 layernum = RNA_int_get(op->ptr, "layer");
2074 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2075 ED_base_object_select(base, BA_DESELECT);
2080 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2081 if(base->lay == (1<< (layernum -1)))
2082 ED_base_object_select(base, BA_SELECT);
2087 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2089 return OPERATOR_FINISHED;
2092 void OBJECT_OT_select_by_layer(wmOperatorType *ot)
2095 ot->name= "select by layer";
2096 ot->description = "Select all visible objects on a layer.";
2097 ot->idname= "OBJECT_OT_select_by_layer";
2100 /*ot->invoke = XXX - need a int grid popup*/
2101 ot->exec= object_select_by_layer_exec;
2102 ot->poll= ED_operator_scene_editable;
2105 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2107 RNA_def_int(ot->srna, "layer", 1, 1, 20, "Layer", "", 1, 20);
2108 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
2111 /* ****** invert selection *******/
2112 static int object_select_inverse_exec(bContext *C, wmOperator *op)
2114 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2115 if (base->flag & SELECT)
2116 ED_base_object_select(base, BA_DESELECT);
2118 ED_base_object_select(base, BA_SELECT);
2123 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2125 return OPERATOR_FINISHED;
2128 void OBJECT_OT_select_inverse(wmOperatorType *ot)
2132 ot->name= "Select Inverse";
2133 ot->description = "Invert selection of all visible objects.";
2134 ot->idname= "OBJECT_OT_select_inverse";
2137 ot->exec= object_select_inverse_exec;
2138 ot->poll= ED_operator_scene_editable;
2141 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2144 /* ****** (de)select All *******/
2146 static int object_select_de_select_all_exec(bContext *C, wmOperator *op)
2151 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2152 if (base->flag & SELECT) {
2160 if (!ok) return OPERATOR_PASS_THROUGH;
2162 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2163 if (a) ED_base_object_select(base, BA_DESELECT);
2164 else ED_base_object_select(base, BA_SELECT);
2169 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2171 return OPERATOR_FINISHED;
2174 void OBJECT_OT_select_all_toggle(wmOperatorType *ot)
2178 ot->name= "deselect all";
2179 ot->description = "(de)select all visible objects in scene.";
2180 ot->idname= "OBJECT_OT_select_all_toggle";
2183 ot->exec= object_select_de_select_all_exec;
2184 ot->poll= ED_operator_scene_editable;
2187 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2190 /* ****** random selection *******/
2192 static int object_select_random_exec(bContext *C, wmOperator *op)
2197 seltype = RNA_enum_get(op->ptr, "seltype");
2200 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2201 ED_base_object_select(base, BA_DESELECT);
2205 percent = RNA_float_get(op->ptr, "percent");
2207 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2208 if (BLI_frand() < percent) {
2209 ED_base_object_select(base, BA_SELECT);
2214 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2216 return OPERATOR_FINISHED;
2219 void OBJECT_OT_select_random(wmOperatorType *ot)
2222 ot->name= "Random select";
2223 ot->description = "Set select on random visible objects.";
2224 ot->idname= "OBJECT_OT_select_random";
2227 /*ot->invoke= object_select_random_invoke XXX - need a number popup ;*/
2228 ot->exec = object_select_random_exec;
2229 ot->poll= ED_operator_scene_editable;
2232 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2234 RNA_def_float_percentage(ot->srna, "percent", 0.5f, 0.0f, 1.0f, "Percent", "percentage of objects to randomly select", 0.0001f, 1.0f);
2235 RNA_def_enum(ot->srna, "seltype", prop_select_types, 1, "Selection", "Extend selection or clear selection then select");
2238 /* ******** Clear object Translation *********** */
2240 static int object_location_clear_exec(bContext *C, wmOperator *op)
2242 int armature_clear= 0;
2244 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2245 if(!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
2246 if ((ob->protectflag & OB_LOCK_LOCX)==0)
2247 ob->loc[0]= ob->dloc[0]= 0.0f;
2248 if ((ob->protectflag & OB_LOCK_LOCY)==0)
2249 ob->loc[1]= ob->dloc[1]= 0.0f;
2250 if ((ob->protectflag & OB_LOCK_LOCZ)==0)
2251 ob->loc[2]= ob->dloc[2]= 0.0f;
2253 ob->recalc |= OB_RECALC_OB;
2257 if(armature_clear==0) /* in this case flush was done */
2258 ED_anim_dag_flush_update(C);
2260 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2262 return OPERATOR_FINISHED;
2266 void OBJECT_OT_location_clear(wmOperatorType *ot)
2270 ot->name= "Clear Location";
2271 ot->description = "Clear the object's location.";
2272 ot->idname= "OBJECT_OT_location_clear";
2275 ot->invoke= WM_operator_confirm;
2276 ot->exec= object_location_clear_exec;
2277 ot->poll= ED_operator_object_active;
2280 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2283 static int object_rotation_clear_exec(bContext *C, wmOperator *op)
2285 int armature_clear= 0;
2287 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2288 if(!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
2289 /* eulers can only get cleared if they are not protected */
2290 if ((ob->protectflag & OB_LOCK_ROTX)==0)
2291 ob->rot[0]= ob->drot[0]= 0.0f;
2292 if ((ob->protectflag & OB_LOCK_ROTY)==0)
2293 ob->rot[1]= ob->drot[1]= 0.0f;
2294 if ((ob->protectflag & OB_LOCK_ROTZ)==0)
2295 ob->rot[2]= ob->drot[2]= 0.0f;
2297 ob->recalc |= OB_RECALC_OB;
2301 if(armature_clear==0) /* in this case flush was done */
2302 ED_anim_dag_flush_update(C);
2304 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2306 return OPERATOR_FINISHED;
2310 void OBJECT_OT_rotation_clear(wmOperatorType *ot)
2314 ot->name= "Clear Rotation";
2315 ot->description = "Clear the object's rotation.";
2316 ot->idname= "OBJECT_OT_rotation_clear";
2319 ot->invoke= WM_operator_confirm;
2320 ot->exec= object_rotation_clear_exec;
2321 ot->poll= ED_operator_object_active;
2324 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2327 static int object_scale_clear_exec(bContext *C, wmOperator *op)
2329 int armature_clear= 0;
2331 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2332 if(!(ob->mode & OB_MODE_WEIGHT_PAINT)) {
2333 if ((ob->protectflag & OB_LOCK_SCALEX)==0) {
2337 if ((ob->protectflag & OB_LOCK_SCALEY)==0) {
2341 if ((ob->protectflag & OB_LOCK_SCALEZ)==0) {
2346 ob->recalc |= OB_RECALC_OB;
2350 if(armature_clear==0) /* in this case flush was done */
2351 ED_anim_dag_flush_update(C);
2353 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2355 return OPERATOR_FINISHED;
2358 void OBJECT_OT_scale_clear(wmOperatorType *ot)
2362 ot->name= "Clear Scale";
2363 ot->description = "Clear the object's scale.";
2364 ot->idname= "OBJECT_OT_scale_clear";
2367 ot->invoke= WM_operator_confirm;
2368 ot->exec= object_scale_clear_exec;
2369 ot->poll= ED_operator_object_active;
2372 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2375 static int object_origin_clear_exec(bContext *C, wmOperator *op)
2377 float *v1, *v3, mat[3][3];
2378 int armature_clear= 0;
2380 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
2383 v3= ob->parentinv[3];
2385 Mat3CpyMat4(mat, ob->parentinv);
2390 Mat3MulVecfl(mat, v3);
2392 ob->recalc |= OB_RECALC_OB;
2396 if(armature_clear==0) /* in this case flush was done */
2397 ED_anim_dag_flush_update(C);
2399 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
2401 return OPERATOR_FINISHED;
2404 void OBJECT_OT_origin_clear(wmOperatorType *ot)
2408 ot->name= "Clear Origin";
2409 ot->description = "Clear the object's origin.";
2410 ot->idname= "OBJECT_OT_origin_clear";
2413 ot->invoke= WM_operator_confirm;
2414 ot->exec= object_origin_clear_exec;
2415 ot->poll= ED_operator_object_active;
2418 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2421 /* ********* clear/set restrict view *********/
2422 static int object_restrictview_clear_exec(bContext *C, wmOperator *op)
2424 ScrArea *sa= CTX_wm_area(C);
2425 View3D *v3d= sa->spacedata.first;
2426 Scene *scene= CTX_data_scene(C);
2430 /* XXX need a context loop to handle such cases */
2431 for(base = FIRSTBASE; base; base=base->next){
2432 if((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
2433 base->flag |= SELECT;
2434 base->object->flag = base->flag;
2435 base->object->restrictflag &= ~OB_RESTRICT_VIEW;
2440 DAG_scene_sort(scene);
2441 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
2444 return OPERATOR_FINISHED;
2447 void OBJECT_OT_restrictview_clear(wmOperatorType *ot)
2451 ot->name= "Clear Restrict View";
2452 ot->description = "Reveal the object by setting the restrictview flag.";
2453 ot->idname= "OBJECT_OT_restrictview_clear";
2456 ot->exec= object_restrictview_clear_exec;
2457 ot->poll= ED_operator_view3d_active;
2460 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2463 static int object_restrictview_set_exec(bContext *C, wmOperator *op)
2465 Scene *scene= CTX_data_scene(C);
2467 int unselected= RNA_boolean_get(op->ptr, "unselected");
2469 CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
2471 if (base->flag & SELECT){
2472 base->flag &= ~SELECT;
2473 base->object->flag = base->flag;
2474 base->object->restrictflag |= OB_RESTRICT_VIEW;
2477 ED_base_object_activate(C, NULL);
2482 if (!(base->flag & SELECT)){
2483 base->object->restrictflag |= OB_RESTRICT_VIEW;
2491 DAG_scene_sort(scene);
2493 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
2497 return OPERATOR_FINISHED;
2500 void OBJECT_OT_restrictview_set(wmOperatorType *ot)
2503 ot->name= "Set Restrict View";
2504 ot->description = "Hide the object by setting the restrictview flag.";
2505 ot->idname= "OBJECT_OT_restrictview_set";
2508 ot->exec= object_restrictview_set_exec;
2509 ot->poll= ED_operator_view3d_active;
2512 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2514 RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects.");
2517 /* ************* Slow Parent ******************* */
2518 static int object_slowparent_set_exec(bContext *C, wmOperator *op)
2521 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2523 if(base->object->parent) base->object->partype |= PARSLOW;
2524 base->object->recalc |= OB_RECALC_OB;
2529 ED_anim_dag_flush_update(C);
2531 WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
2533 return OPERATOR_FINISHED;
2536 void OBJECT_OT_slowparent_set(wmOperatorType *ot)
2540 ot->name= "Set Slow Parent";
2541 ot->description = "Set the object's slow parent.";
2542 ot->idname= "OBJECT_OT_slow_parent_set";
2545 ot->invoke= WM_operator_confirm;
2546 ot->exec= object_slowparent_set_exec;
2547 ot->poll= ED_operator_view3d_active;
2550 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2553 static int object_slowparent_clear_exec(bContext *C, wmOperator *op)
2555 Scene *scene= CTX_data_scene(C);
2557 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
2558 if(base->object->parent) {
2559 if(base->object->partype & PARSLOW) {
2560 base->object->partype -= PARSLOW;
2561 where_is_object(scene, base->object);
2562 base->object->partype |= PARSLOW;
2563 base->object->recalc |= OB_RECALC_OB;
2570 ED_anim_dag_flush_update(C);
2572 WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
2574 return OPERATOR_FINISHED;
2577 void OBJECT_OT_slowparent_clear(wmOperatorType *ot)
2581 ot->name= "Clear Slow Parent";
2582 ot->description = "Clear the object's slow parent.";
2583 ot->idname= "OBJECT_OT_slow_parent_clear";
2586 ot->invoke= WM_operator_confirm;
2587 ot->exec= object_slowparent_clear_exec;
2588 ot->poll= ED_operator_view3d_active;
2591 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2593 /* ******************** **************** */
2596 #define BEZSELECTED_HIDDENHANDLES(bezt) ((G.f & G_HIDDENHANDLES) ? (bezt)->f2 & SELECT : BEZSELECTED(bezt))
2597 /* only in edit mode */
2598 void make_vertex_parent(Scene *scene, Object *obedit, View3D *v3d)
2606 int a, v1=0, v2=0, v3=0, v4=0, nr=1;
2608 /* we need 1 to 3 selected vertices */
2610 if(obedit->type==OB_MESH) {
2611 Mesh *me= obedit->data;
2612 EditMesh *em = BKE_mesh_get_editmesh(me);
2614 eve= em->verts.first;
2618 else if(v2==0) v2= nr;
2619 else if(v3==0) v3= nr;
2620 else if(v4==0) v4= nr;
2627 BKE_mesh_end_editmesh(me, em);
2629 else if(ELEM(obedit->type, OB_SURF, OB_CURVE)) {
2630 ListBase *editnurb= curve_get_editcurve(obedit);
2632 nu= editnurb->first;
2634 if((nu->type & 7)==CU_BEZIER) {
2638 if(BEZSELECTED_HIDDENHANDLES(bezt)) {
2640 else if(v2==0) v2= nr;
2641 else if(v3==0) v3= nr;
2642 else if(v4==0) v4= nr;
2651 a= nu->pntsu*nu->pntsv;
2653 if(bp->f1 & SELECT) {
2655 else if(v2==0) v2= nr;
2656 else if(v3==0) v3= nr;
2657 else if(v4==0) v4= nr;
2667 else if(obedit->type==OB_LATTICE) {
2668 Lattice *lt= obedit->data;
2670 a= lt->editlatt->pntsu*lt->editlatt->pntsv*lt->editlatt->pntsw;
2671 bp= lt->editlatt->def;
2673 if(bp->f1 & SELECT) {
2675 else if(v2==0) v2= nr;
2676 else if(v3==0) v3= nr;
2677 else if(v4==0) v4= nr;
2685 if(v4 || !((v1 && v2==0 && v3==0) || (v1 && v2 && v3)) ) {
2686 error("Select either 1 or 3 vertices to parent to");
2690 if(okee("Make vertex parent")==0) return;
2692 for(base= FIRSTBASE; base; base= base->next) {
2693 if(TESTBASELIB(v3d, base)) {
2697 ob->recalc |= OB_RECALC;
2698 par= BASACT->object->parent;
2705 error("Loop in parents");
2710 ob->parent= BASACT->object;
2712 ob->partype= PARVERT3;
2717 /* inverse parent matrix */
2718 what_does_parent(scene, ob, &workob);
2719 Mat4Invert(ob->parentinv, workob.obmat);
2722 ob->partype= PARVERT1;
2725 /* inverse parent matrix */
2726 what_does_parent(scene, ob, &workob);
2727 Mat4Invert(ob->parentinv, workob.obmat);
2734 DAG_scene_sort(scene);
2738 /* ******************** make proxy operator *********************** */
2740 /* present menu listing the possible objects within the group to proxify */
2741 static void proxy_group_objects_menu (bContext *C, wmOperator *op, Object *ob, Group *group)
2748 /* check if there are any objects within the group to assign for */
2749 for (go= group->gobject.first; go; go= go->next) {
2754 /* now create the menu to draw */
2755 pup= uiPupMenuBegin(C, "Make Proxy For:", 0);
2756 layout= uiPupMenuLayout(pup);
2758 for (go= group->gobject.first; go; go= go->next) {
2760 PointerRNA props_ptr;
2762 /* create operator menu item with relevant properties filled in */
2763 props_ptr= uiItemFullO(layout, go->ob->id.name+2, 0, op->idname, NULL, WM_OP_EXEC_REGION_WIN, UI_ITEM_O_RETURN_PROPS);
2764 RNA_string_set(&props_ptr, "object", go->ob->id.name+2);
2765 RNA_string_set(&props_ptr, "group_object", go->ob->id.name+2);
2769 /* display the menu, and be done */
2770 uiPupMenuEnd(C, pup);
2773 /* set the object to proxify */
2774 static int make_proxy_invoke (bContext *C, wmOperator *op, wmEvent *evt)
2776 Scene *scene= CTX_data_scene(C);
2777 Object *ob= CTX_data_active_object(C);
2780 if (!scene || scene->id.lib || !ob)
2781 return OPERATOR_CANCELLED;
2783 /* Get object to work on - use a menu if we need to... */
2784 if (ob->dup_group && ob->dup_group->id.lib) {
2785 /* gives menu with list of objects in group */
2786 proxy_group_objects_menu(C, op, ob, ob->dup_group);
2788 else if (ob->id.lib) {
2789 uiPopupMenu *pup= uiPupMenuBegin(C, "OK?", ICON_QUESTION);
2790 uiLayout *layout= uiPupMenuLayout(pup);
2791 PointerRNA props_ptr;
2793 /* create operator menu item with relevant properties filled in */
2794 props_ptr= uiItemFullO(layout, op->type->name, 0, op->idname, props_ptr.data, WM_OP_EXEC_REGION_WIN, UI_ITEM_O_RETURN_PROPS);
2795 RNA_string_set(&props_ptr, "object", ob->id.name+2);
2797 /* present the menu and be done... */
2798 uiPupMenuEnd(C, pup);
2801 /* error.. cannot continue */
2802 BKE_report(op->reports, RPT_ERROR, "Can only make proxy for a referenced object or group");
2805 /* this invoke just calls another instance of this operator... */
2806 return OPERATOR_CANCELLED;
2809 static int make_proxy_exec (bContext *C, wmOperator *op)
2811 Object *ob=NULL, *gob=NULL;
2812 Scene *scene= CTX_data_scene(C);
2813 char ob_name[21], gob_name[21];
2815 /* get object and group object
2817 * - then pointers from context
2819 RNA_string_get(op->ptr, "object", ob_name);
2820 RNA_string_get(op->ptr, "group_object", gob_name);
2826 /* active object is group object... */
2827 // FIXME: we should get the nominated name instead
2828 gob= CTX_data_active_object(C);
2829 group= gob->dup_group;
2831 /* find the object to affect */
2832 for (go= group->gobject.first; go; go= go->next) {
2833 if ((go->ob) && strcmp(go->ob->id.name+2, gob_name)==0) {
2840 /* just use the active object for now */
2841 // FIXME: we should get the nominated name instead
2842 ob= CTX_data_active_object(C);
2847 Base *newbase, *oldbase= BASACT;
2850 /* Add new object for the proxy */
2851 newob= add_object(scene, OB_EMPTY);
2853 strcpy(name, gob->id.name+2);
2855 strcpy(name, ob->id.name+2);
2856 strcat(name, "_proxy");
2857 rename_id(&newob->id, name);
2860 newbase= BASACT; /* add_object sets active... */
2861 newbase->lay= oldbase->lay;
2862 newob->lay= newbase->lay;
2864 /* remove base, leave user count of object, it gets linked in object_make_proxy */
2866 BLI_remlink(&scene->base, oldbase);
2870 object_make_proxy(newob, ob, gob);
2872 /* depsgraph flushes are needed for the new data */
2873 DAG_scene_sort(scene);
2874 DAG_object_flush_update(scene, newob, OB_RECALC);
2876 WM_event_add_notifier(C, NC_OBJECT, NULL);
2879 BKE_report(op->reports, RPT_ERROR, "No object to make proxy for");
2880 return OPERATOR_CANCELLED;
2883 return OPERATOR_FINISHED;
2886 void OBJECT_OT_proxy_make (wmOperatorType *ot)
2889 ot->name= "Make Proxy";
2890 ot->idname= "OBJECT_OT_proxy_make";
2891 ot->description= "Add empty object to become local replacement data of a library-linked object";
2894 ot->invoke= make_proxy_invoke;
2895 ot->exec= make_proxy_exec;
2896 ot->poll= ED_operator_object_active;
2899 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2902 RNA_def_string(ot->srna, "object", "", 19, "Proxy Object", "Name of lib-linked/grouped object to make a proxy for.");
2903 RNA_def_string(ot->srna, "group_object", "", 19, "Group Object", "Name of group instancer (if applicable).");
2906 /* ******************** make parent operator *********************** */
2908 #define PAR_OBJECT 0
2909 #define PAR_ARMATURE 1
2910 #define PAR_ARMATURE_NAME 2
2911 #define PAR_ARMATURE_ENVELOPE 3
2912 #define PAR_ARMATURE_AUTO 4
2915 #define PAR_FOLLOW 7
2916 #define PAR_PATH_CONST 8
2917 #define PAR_LATTICE 9
2918 #define PAR_VERTEX 10
2921 static EnumPropertyItem prop_make_parent_types[] = {
2922 {PAR_OBJECT, "OBJECT", 0, "Object", ""},
2923 {PAR_ARMATURE, "ARMATURE", 0, "Armature Deform", ""},
2924 {PAR_ARMATURE_NAME, "ARMATURE_NAME", 0, " With Empty Groups", ""},
2925 {PAR_ARMATURE_AUTO, "ARMATURE_AUTO", 0, " With Automatic Weights", ""},
2926 {PAR_ARMATURE_ENVELOPE, "ARMATURE_ENVELOPE", 0, " With Envelope Weights", ""},
2927 {PAR_BONE, "BONE", 0, "Bone", ""},
2928 {PAR_CURVE, "CURVE", 0, "Curve Deform", ""},
2929 {PAR_FOLLOW, "FOLLOW", 0, "Follow Path", ""},
2930 {PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""},
2931 {PAR_LATTICE, "LATTICE", 0, "Lattice Deform", ""},
2932 {PAR_VERTEX, "VERTEX", 0, "Vertex", ""},
2933 {PAR_TRIA, "TRIA", 0, "Triangle", ""},
2934 {0, NULL, 0, NULL, NULL}
2937 static int test_parent_loop(Object *par, Object *ob)
2939 /* test if 'ob' is a parent somewhere in par's parents */
2941 if(par == NULL) return 0;
2942 if(ob == par) return 1;
2944 return test_parent_loop(par->parent, ob);
2947 void ED_object_parent(Object *ob, Object *par, int type, const char *substr)
2949 if(!par || test_parent_loop(par, ob)) {
2951 ob->partype= PAROBJECT;
2952 ob->parsubstr[0]= 0;
2956 /* this could use some more checks */
2959 ob->partype &= ~PARTYPE;
2960 ob->partype |= type;
2961 BLI_strncpy(ob->parsubstr, substr, sizeof(ob->parsubstr));
2964 static int parent_set_exec(bContext *C, wmOperator *op)
2966 Scene *scene= CTX_data_scene(C);
2967 Object *par= CTX_data_active_object(C);
2968 bPoseChannel *pchan= NULL;
2969 int partype= RNA_enum_get(op->ptr, "type");
2970 int pararm= ELEM4(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO);
2972 par->recalc |= OB_RECALC_OB;
2975 if(partype==PAR_FOLLOW || partype==PAR_PATH_CONST) {
2976 if(par->type!=OB_CURVE)
2977 return OPERATOR_CANCELLED;
2979 Curve *cu= par->data;
2981 if((cu->flag & CU_PATH)==0) {
2982 cu->flag |= CU_PATH|CU_FOLLOW;
2983 makeDispListCurveTypes(scene, par, 0); /* force creation of path data */
2985 else cu->flag |= CU_FOLLOW;
2987 /* fall back on regular parenting now */
2988 partype= PAR_OBJECT;
2991 else if(partype==PAR_BONE) {
2992 pchan= get_active_posechannel(par);
2995 error("No active Bone");
2996 return OPERATOR_CANCELLED;
3000 /* context itterator */
3001 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
3005 if( test_parent_loop(par, ob) ) {
3006 error("Loop in parents");
3011 /* apply transformation of previous parenting */
3012 ED_object_apply_obmat(ob);
3018 strcpy (ob->parsubstr, pchan->name);
3020 ob->parsubstr[0]= 0;
3023 if(partype==PAR_PATH_CONST) {
3025 bFollowPathConstraint *data;
3026 float cmat[4][4], vec[3];
3028 con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
3029 strcpy (con->name, "AutoPath");
3034 add_constraint_to_object(con, ob);
3036 get_constraint_target_matrix(con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra - give_timeoffset(ob));
3037 VecSubf(vec, ob->obmat[3], cmat[3]);
3039 ob->loc[0] = vec[0];
3040 ob->loc[1] = vec[1];
3042 else if(pararm && ob->type==OB_MESH && par->type == OB_ARMATURE) {
3043 if(partype == PAR_ARMATURE_NAME)
3044 create_vgroups_from_armature(scene, ob, par, ARM_GROUPS_NAME);
3045 else if(partype == PAR_ARMATURE_ENVELOPE)
3046 create_vgroups_from_armature(scene, ob, par, ARM_GROUPS_ENVELOPE);
3047 else if(partype == PAR_ARMATURE_AUTO)
3048 create_vgroups_from_armature(scene, ob, par, ARM_GROUPS_AUTO);
3050 /* get corrected inverse */
3051 ob->partype= PAROBJECT;
3052 what_does_parent(scene, ob, &workob);
3054 ob->partype= PARSKEL;
3056 Mat4Invert(ob->parentinv, workob.obmat);
3059 /* calculate inverse parent matrix */
3060 what_does_parent(scene, ob, &workob);
3061 Mat4Invert(ob->parentinv, workob.obmat);
3064 ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
3066 if( ELEM(partype, PAR_CURVE, PAR_LATTICE) || pararm )
3067 ob->partype= PARSKEL; /* note, dna define, not operator property */
3069 ob->partype= PAROBJECT; /* note, dna define, not operator property */
3075 DAG_scene_sort(CTX_data_scene(C));
3076 ED_anim_dag_flush_update(C);
3077 WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
3079 return OPERATOR_FINISHED;
3082 static int parent_set_invoke(bContext *C, wmOperator *op, wmEvent *event)
3084 Object *ob= CTX_data_active_object(C);
3085 uiPopupMenu *pup= uiPupMenuBegin(C, "Set Parent To", 0);
3086 uiLayout *layout= uiPupMenuLayout(pup);
3088 uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
3089 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_OBJECT);
3091 /* ob becomes parent, make the associated menus */
3092 if(ob->type==OB_ARMATURE) {
3093 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE);
3094 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE_NAME);
3095 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE_ENVELOPE);
3096 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_ARMATURE_AUTO);
3097 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_BONE);
3099 else if(ob->type==OB_CURVE) {
3100 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_CURVE);
3101 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_FOLLOW);
3102 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_PATH_CONST);
3104 else if(ob->type == OB_LATTICE) {
3105 uiItemEnumO(layout, NULL, 0, "OBJECT_OT_parent_set", "type", PAR_LATTICE);
3108 uiPupMenuEnd(C, pup);
3110 return OPERATOR_CANCELLED;
3114 void OBJECT_OT_parent_set(wmOperatorType *ot)
3117 ot->name= "Make Parent";
3118 ot->description = "Set the object's parenting.";
3119 ot->idname= "OBJECT_OT_parent_set";
3122 ot->invoke= parent_set_invoke;
3123 ot->exec= parent_set_exec;
3125 ot->poll= ED_operator_object_active;
3128 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
3130 RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
3133 /* *** make track ***** */
3134 static EnumPropertyItem prop_make_track_types[] = {
3135 {1, "TRACKTO", 0, "TrackTo Constraint", ""},
3136 {2, "LOCKTRACK", 0, "LockTrack Constraint", ""},
3137 {3, "OLDTRACK", 0, "Old Track", ""},
3138 {0, NULL, 0, NULL, NULL}
3141 static int track_set_exec(bContext *C, wmOperator *op)
3143 Scene *scene= CTX_data_scene(C);
3144 int type= RNA_enum_get(op->ptr, "type");
3148 bTrackToConstraint *data;
3150 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
3152 con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
3153 strcpy (con->name, "AutoTrack");
3156 data->tar = BASACT->object;
3157 base->object->recalc |= OB_RECALC;
3159 /* Lamp and Camera track differently by default */
3160 if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
3161 data->reserved1 = TRACK_nZ;
3162 data->reserved2 = UP_Y;
3165 add_constraint_to_object(con, base->object);
3170 else if(type == 2) {
3172 bLockTrackConstraint *data;
3174 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
3176 con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
3177 strcpy (con->name, "AutoTrack");
3180 data->tar = BASACT->object;
3181 base->object->recalc |= OB_RECALC;
3183 /* Lamp and Camera track differently by default */
3184 if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
3185 data->trackflag = TRACK_nZ;
3186 data->lockflag = LOCK_Y;
3189 add_constraint_to_object(con, base->object);
3195 CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
3197 base->object->track= BASACT->object;