diff options
Diffstat (limited to 'source/blender/editors/object/object_add.c')
-rw-r--r-- | source/blender/editors/object/object_add.c | 688 |
1 files changed, 347 insertions, 341 deletions
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 43a32cd662e..4942b9e4390 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -43,7 +43,6 @@ #include "DNA_meta_types.h" #include "DNA_object_fluidsim.h" #include "DNA_object_force.h" -#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_speaker_types.h" #include "DNA_vfont_types.h" @@ -111,7 +110,7 @@ #include "object_intern.h" /* this is an exact copy of the define in rna_lamp.c - * kept here because of linking order. + * kept here because of linking order. * Icons are only defined here */ EnumPropertyItem lamp_type_items[] = { {LA_LOCAL, "POINT", ICON_LAMP_POINT, "Point", "Omnidirectional point light source"}, @@ -122,23 +121,6 @@ EnumPropertyItem lamp_type_items[] = { {0, NULL, 0, NULL, NULL} }; -/* copy from rna_object_force.c */ -static EnumPropertyItem field_type_items[] = { - {PFIELD_FORCE, "FORCE", ICON_FORCE_FORCE, "Force", ""}, - {PFIELD_WIND, "WIND", ICON_FORCE_WIND, "Wind", ""}, - {PFIELD_VORTEX, "VORTEX", ICON_FORCE_VORTEX, "Vortex", ""}, - {PFIELD_MAGNET, "MAGNET", ICON_FORCE_MAGNETIC, "Magnetic", ""}, - {PFIELD_HARMONIC, "HARMONIC", ICON_FORCE_HARMONIC, "Harmonic", ""}, - {PFIELD_CHARGE, "CHARGE", ICON_FORCE_CHARGE, "Charge", ""}, - {PFIELD_LENNARDJ, "LENNARDJ", ICON_FORCE_LENNARDJONES, "Lennard-Jones", ""}, - {PFIELD_TEXTURE, "TEXTURE", ICON_FORCE_TEXTURE, "Texture", ""}, - {PFIELD_GUIDE, "GUIDE", ICON_FORCE_CURVE, "Curve Guide", ""}, - {PFIELD_BOID, "BOID", ICON_FORCE_BOID, "Boid", ""}, - {PFIELD_TURBULENCE, "TURBULENCE", ICON_FORCE_TURBULENCE, "Turbulence", ""}, - {PFIELD_DRAG, "DRAG", ICON_FORCE_DRAG, "Drag", ""}, - {0, NULL, 0, NULL, NULL} -}; - /************************** Exported *****************************/ void ED_object_location_from_view(bContext *C, float loc[3]) @@ -146,7 +128,7 @@ void ED_object_location_from_view(bContext *C, float loc[3]) View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); float *cursor; - + cursor = give_cursor(scene, v3d); copy_v3_v3(loc, cursor); @@ -170,44 +152,44 @@ void ED_object_base_init_transform(bContext *C, Base *base, const float loc[3], { Object *ob = base->object; Scene *scene = CTX_data_scene(C); - + if (!scene) return; - + if (loc) copy_v3_v3(ob->loc, loc); - + if (rot) copy_v3_v3(ob->rot, rot); - + BKE_object_where_is_calc(scene, ob); } -/* Uses context to figure out transform for primitive. - * Returns standard diameter. */ +/* uses context to figure out transform for primitive */ +/* returns standard diameter */ float ED_object_new_primitive_matrix(bContext *C, Object *obedit, const float loc[3], const float rot[3], float primmat[][4]) { Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3]; - + unit_m4(primmat); - + eul_to_mat3(rmat, rot); invert_m3(rmat); - + /* inverse transform for initial rotation and object */ copy_m3_m4(mat, obedit->obmat); mul_m3_m3m3(cmat, rmat, mat); invert_m3_m3(imat, cmat); copy_m4_m3(primmat, imat); - + /* center */ copy_v3_v3(primmat[3], loc); sub_v3_v3v3(primmat[3], primmat[3], obedit->obmat[3]); invert_m3_m3(imat, mat); mul_m3_v3(imat, primmat[3]); - + if (v3d) return ED_view3d_grid_scale(scene, v3d, NULL); @@ -224,7 +206,7 @@ static void view_align_update(struct Main *UNUSED(main), struct Scene *UNUSED(sc void ED_object_add_generic_props(wmOperatorType *ot, int do_editmode) { PropertyRNA *prop; - + /* note: this property gets hidden for add-camera operator */ prop = RNA_def_boolean(ot->srna, "view_align", 0, "Align to View", "Align the new object to the view"); RNA_def_property_update_runtime(prop, view_align_update); @@ -234,112 +216,112 @@ void ED_object_add_generic_props(wmOperatorType *ot, int do_editmode) "Enter editmode when adding this object"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } - + prop = RNA_def_float_vector_xyz(ot->srna, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", "Location for the newly added object", -FLT_MAX, FLT_MAX); RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_float_rotation(ot->srna, "rotation", 3, NULL, -FLT_MAX, FLT_MAX, "Rotation", "Rotation for the newly added object", (float)-M_PI * 2.0f, (float)M_PI * 2.0f); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - + prop = RNA_def_boolean_layer_member(ot->srna, "layers", 20, NULL, "Layer", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -int ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float loc[3], float rot[3], - int *enter_editmode, unsigned int *layer, int *is_view_aligned) +static void object_add_generic_invoke_options(bContext *C, wmOperator *op) { - View3D *v3d = CTX_wm_view3d(C); - - /* Switch to Edit mode? */ - if (RNA_struct_find_property(op->ptr, "enter_editmode")) { /* optional */ - int _enter_editmode; - if (!enter_editmode) - enter_editmode = &_enter_editmode; - - if (RNA_struct_property_is_set(op->ptr, "enter_editmode") && enter_editmode) - *enter_editmode = RNA_boolean_get(op->ptr, "enter_editmode"); - else { - *enter_editmode = U.flag & USER_ADD_EDITMODE; - RNA_boolean_set(op->ptr, "enter_editmode", *enter_editmode); - } + if (RNA_struct_find_property(op->ptr, "enter_editmode")) /* optional */ + if (!RNA_struct_property_is_set(op->ptr, "enter_editmode")) + RNA_boolean_set(op->ptr, "enter_editmode", U.flag & USER_ADD_EDITMODE); + + if (!RNA_struct_property_is_set(op->ptr, "location")) { + float loc[3]; + + ED_object_location_from_view(C, loc); + RNA_float_set_array(op->ptr, "location", loc); } + + if (!RNA_struct_property_is_set(op->ptr, "layers")) { + View3D *v3d = CTX_wm_view3d(C); + Scene *scene = CTX_data_scene(C); + int a, values[20], layer; - /* Get layers! */ - { - int a, layer_values[20]; - unsigned int _layer; - if (!layer) - layer = &_layer; - - if (RNA_struct_property_is_set(op->ptr, "layers")) { - RNA_boolean_get_array(op->ptr, "layers", layer_values); - *layer = 0; - for (a = 0; a < 20; a++) { - if (layer_values[a]) - *layer |= (1 << a); - } + if (v3d) { + layer = (v3d->scenelock && !v3d->localvd) ? scene->layact : v3d->layact; } else { - Scene *scene = CTX_data_scene(C); - if (v3d) - *layer = (v3d->scenelock && !v3d->localvd) ? scene->layact : v3d->layact; - else - *layer = scene->layact; - for (a = 0; a < 20; a++) { - layer_values[a] = *layer & (1 << a); - } - RNA_boolean_set_array(op->ptr, "layers", layer_values); + layer = scene->layact; + } + + for (a = 0; a < 20; a++) { + values[a] = (layer & (1 << a)); } - /* in local view we additionally add local view layers, - * not part of operator properties */ - if (v3d && v3d->localvd) - *layer |= v3d->lay; + RNA_boolean_set_array(op->ptr, "layers", values); } +} - /* Location! */ - { - float _loc[3]; - if (!loc) - loc = _loc; +int ED_object_add_generic_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + object_add_generic_invoke_options(C, op); + return op->type->exec(C, op); +} - if (RNA_struct_property_is_set(op->ptr, "location")) { - RNA_float_get_array(op->ptr, "location", loc); - } - else { - ED_object_location_from_view(C, loc); - RNA_float_set_array(op->ptr, "location", loc); - } +int ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float loc[3], float rot[3], + int *enter_editmode, unsigned int *layer, int *is_view_aligned) +{ + View3D *v3d = CTX_wm_view3d(C); + int a, layer_values[20]; + int view_align; + + *enter_editmode = FALSE; + if (RNA_struct_find_property(op->ptr, "enter_editmode") && RNA_boolean_get(op->ptr, "enter_editmode")) { + *enter_editmode = TRUE; } - /* Rotation! */ - { - int _is_view_aligned; - float _rot[3]; - if (!is_view_aligned) - is_view_aligned = &_is_view_aligned; - if (!rot) - rot = _rot; - - if (RNA_struct_property_is_set(op->ptr, "rotation")) - *is_view_aligned = FALSE; - else if (RNA_struct_property_is_set(op->ptr, "view_align")) - *is_view_aligned = RNA_boolean_get(op->ptr, "view_align"); - else { - *is_view_aligned = U.flag & USER_ADD_VIEWALIGNED; - RNA_boolean_set(op->ptr, "view_align", *is_view_aligned); - } - - if (*is_view_aligned) { - ED_object_rotation_from_view(C, rot); - RNA_float_set_array(op->ptr, "rotation", rot); + if (RNA_struct_property_is_set(op->ptr, "layers")) { + RNA_boolean_get_array(op->ptr, "layers", layer_values); + *layer = 0; + for (a = 0; a < 20; a++) { + if (layer_values[a]) + *layer |= (1 << a); + else + *layer &= ~(1 << a); } - else - RNA_float_get_array(op->ptr, "rotation", rot); } + else { + /* not set, use the scenes layers */ + Scene *scene = CTX_data_scene(C); + *layer = scene->layact; + } + + /* in local view we additionally add local view layers, + * not part of operator properties */ + if (v3d && v3d->localvd) + *layer |= v3d->lay; - if (layer && *layer == 0) { + if (RNA_struct_property_is_set(op->ptr, "rotation")) + view_align = FALSE; + else if (RNA_struct_property_is_set(op->ptr, "view_align")) + view_align = RNA_boolean_get(op->ptr, "view_align"); + else { + view_align = U.flag & USER_ADD_VIEWALIGNED; + RNA_boolean_set(op->ptr, "view_align", view_align); + } + + if (view_align) { + ED_object_rotation_from_view(C, rot); + RNA_float_set_array(op->ptr, "rotation", rot); + } + else + RNA_float_get_array(op->ptr, "rotation", rot); + + if (is_view_aligned) + *is_view_aligned = view_align; + + RNA_float_get_array(op->ptr, "location", loc); + + if (*layer == 0) { BKE_report(op->reports, RPT_ERROR, "Property 'layer' has no values set"); return 0; } @@ -347,19 +329,19 @@ int ED_object_add_generic_get_opts(bContext *C, wmOperator *op, float loc[3], fl return 1; } -/* For object add primitive operators. - * Do not call undo push in this function (users of this function have to). */ +/* for object add primitive operators */ +/* do not call undo push in this function (users of this function have to) */ Object *ED_object_add_type(bContext *C, int type, const float loc[3], const float rot[3], int enter_editmode, unsigned int layer) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); Object *ob; - - /* For as long scene has editmode... */ + + /* for as long scene has editmode... */ if (CTX_data_edit_object(C)) ED_object_exit_editmode(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */ - + /* deselects all, sets scene->basact */ ob = BKE_object_add(scene, type); BASACT->lay = ob->lay = layer; @@ -389,12 +371,12 @@ static int object_add_exec(bContext *C, wmOperator *op) int enter_editmode; unsigned int layer; float loc[3], rot[3]; - + if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), loc, rot, enter_editmode, layer); - + return OPERATOR_FINISHED; } @@ -404,62 +386,89 @@ void OBJECT_OT_add(wmOperatorType *ot) ot->name = "Add Object"; ot->description = "Add an object to the scene"; ot->idname = "OBJECT_OT_add"; - + /* api callbacks */ + ot->invoke = ED_object_add_generic_invoke; ot->exec = object_add_exec; + ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + RNA_def_enum(ot->srna, "type", object_type_items, 0, "Type", ""); ED_object_add_generic_props(ot, TRUE); } /********************* Add Effector Operator ********************/ +/* copy from rna_object_force.c*/ +static EnumPropertyItem field_type_items[] = { + {PFIELD_FORCE, "FORCE", ICON_FORCE_FORCE, "Force", ""}, + {PFIELD_WIND, "WIND", ICON_FORCE_WIND, "Wind", ""}, + {PFIELD_VORTEX, "VORTEX", ICON_FORCE_VORTEX, "Vortex", ""}, + {PFIELD_MAGNET, "MAGNET", ICON_FORCE_MAGNETIC, "Magnetic", ""}, + {PFIELD_HARMONIC, "HARMONIC", ICON_FORCE_HARMONIC, "Harmonic", ""}, + {PFIELD_CHARGE, "CHARGE", ICON_FORCE_CHARGE, "Charge", ""}, + {PFIELD_LENNARDJ, "LENNARDJ", ICON_FORCE_LENNARDJONES, "Lennard-Jones", ""}, + {PFIELD_TEXTURE, "TEXTURE", ICON_FORCE_TEXTURE, "Texture", ""}, + {PFIELD_GUIDE, "GUIDE", ICON_FORCE_CURVE, "Curve Guide", ""}, + {PFIELD_BOID, "BOID", ICON_FORCE_BOID, "Boid", ""}, + {PFIELD_TURBULENCE, "TURBULENCE", ICON_FORCE_TURBULENCE, "Turbulence", ""}, + {PFIELD_DRAG, "DRAG", ICON_FORCE_DRAG, "Drag", ""}, + {0, NULL, 0, NULL, NULL}}; -/* for object add operator */ -static int effector_add_exec(bContext *C, wmOperator *op) +/* for effector add primitive operators */ +static Object *effector_add_type(bContext *C, wmOperator *op, int type) { Object *ob; - int type, enter_editmode; + int enter_editmode; unsigned int layer; float loc[3], rot[3]; float mat[4][4]; + + object_add_generic_invoke_options(C, op); if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) - return OPERATOR_CANCELLED; - - type = RNA_enum_get(op->ptr, "type"); + return NULL; if (type == PFIELD_GUIDE) { ob = ED_object_add_type(C, OB_CURVE, loc, rot, FALSE, layer); - if (!ob) - return OPERATOR_CANCELLED; - rename_id(&ob->id, "CurveGuide"); + ((Curve *)ob->data)->flag |= CU_PATH | CU_3D; ED_object_enter_editmode(C, 0); ED_object_new_primitive_matrix(C, ob, loc, rot, mat); BLI_addtail(object_editcurve_get(ob), add_nurbs_primitive(C, ob, mat, CU_NURBS | CU_PRIM_PATH, 1)); + if (!enter_editmode) ED_object_exit_editmode(C, EM_FREEDATA); } else { ob = ED_object_add_type(C, OB_EMPTY, loc, rot, FALSE, layer); - if (!ob) - return OPERATOR_CANCELLED; - rename_id(&ob->id, "Field"); - if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX)) - ob->empty_drawtype = OB_SINGLE_ARROW; + + switch (type) { + case PFIELD_WIND: + case PFIELD_VORTEX: + ob->empty_drawtype = OB_SINGLE_ARROW; + break; + } } ob->pd = object_add_collision_fields(type); DAG_scene_sort(CTX_data_main(C), CTX_data_scene(C)); + return ob; +} + +/* for object add operator */ +static int effector_add_exec(bContext *C, wmOperator *op) +{ + if (effector_add_type(C, op, RNA_enum_get(op->ptr, "type")) == NULL) + return OPERATOR_CANCELLED; + return OPERATOR_FINISHED; } @@ -469,20 +478,22 @@ void OBJECT_OT_effector_add(wmOperatorType *ot) ot->name = "Add Effector"; ot->description = "Add an empty object with a physics effector to the scene"; ot->idname = "OBJECT_OT_effector_add"; - + /* api callbacks */ + ot->invoke = WM_menu_invoke; ot->exec = effector_add_exec; + ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + ot->prop = RNA_def_enum(ot->srna, "type", field_type_items, 0, "Type", ""); ED_object_add_generic_props(ot, TRUE); } -/********************* Add Camera Operator ********************/ +/* ***************** Add Camera *************** */ static int object_camera_add_exec(bContext *C, wmOperator *op) { @@ -492,15 +503,17 @@ static int object_camera_add_exec(bContext *C, wmOperator *op) int enter_editmode; unsigned int layer; float loc[3], rot[3]; - + /* force view align for cameras */ RNA_boolean_set(op->ptr, "view_align", TRUE); + + object_add_generic_invoke_options(C, op); if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; ob = ED_object_add_type(C, OB_CAMERA, loc, rot, FALSE, layer); - + if (v3d) { if (v3d->camera == NULL) v3d->camera = ob; @@ -515,62 +528,83 @@ static int object_camera_add_exec(bContext *C, wmOperator *op) void OBJECT_OT_camera_add(wmOperatorType *ot) { PropertyRNA *prop; - + /* identifiers */ ot->name = "Add Camera"; ot->description = "Add a camera object to the scene"; ot->idname = "OBJECT_OT_camera_add"; - + /* api callbacks */ ot->exec = object_camera_add_exec; ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + ED_object_add_generic_props(ot, TRUE); - + /* hide this for cameras, default */ prop = RNA_struct_type_find_property(ot->srna, "view_align"); RNA_def_property_flag(prop, PROP_HIDDEN); -} +} -/********************* Add Metaball Operator ********************/ +/* ***************** add primitives *************** */ static int object_metaball_add_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); + /*MetaElem *elem;*/ /*UNUSED*/ int newob = 0; int enter_editmode; unsigned int layer; float loc[3], rot[3]; float mat[4][4]; + object_add_generic_invoke_options(C, op); /* XXX these props don't get set right when only exec() is called */ + if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; - + if (obedit == NULL || obedit->type != OB_MBALL) { obedit = ED_object_add_type(C, OB_MBALL, loc, rot, TRUE, layer); newob = 1; } - else - DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); - + else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + ED_object_new_primitive_matrix(C, obedit, loc, rot, mat); - - add_metaball_primitive(C, obedit, mat, RNA_enum_get(op->ptr, "type"), newob); + + /* elem= (MetaElem *) */ add_metaball_primitive(C, obedit, mat, RNA_enum_get(op->ptr, "type"), newob); /* userdef */ if (newob && !enter_editmode) { ED_object_exit_editmode(C, EM_FREEDATA); } - + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); - + return OPERATOR_FINISHED; } +static int object_metaball_add_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + Object *obedit = CTX_data_edit_object(C); + uiPopupMenu *pup; + uiLayout *layout; + + object_add_generic_invoke_options(C, op); + + pup = uiPupMenuBegin(C, op->type->name, ICON_NONE); + layout = uiPupMenuLayout(pup); + if (!obedit || obedit->type == OB_MBALL) + uiItemsEnumO(layout, op->type->idname, "type"); + else + uiItemsEnumO(layout, "OBJECT_OT_metaball_add", "type"); + uiPupMenuEnd(C, pup); + + return OPERATOR_CANCELLED; +} + void OBJECT_OT_metaball_add(wmOperatorType *ot) { /* identifiers */ @@ -579,37 +613,35 @@ void OBJECT_OT_metaball_add(wmOperatorType *ot) ot->idname = "OBJECT_OT_metaball_add"; /* api callbacks */ - ot->invoke = WM_menu_invoke;/* object_metaball_add_invoke; */ + ot->invoke = object_metaball_add_invoke; ot->exec = object_metaball_add_exec; ot->poll = ED_operator_scene_editable; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - ot->prop = RNA_def_enum(ot->srna, "type", metaelem_type_items, 0, "Primitive", ""); - + + RNA_def_enum(ot->srna, "type", metaelem_type_items, 0, "Primitive", ""); ED_object_add_generic_props(ot, TRUE); } -/********************* Add Text Operator ********************/ - static int object_add_text_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); int enter_editmode; unsigned int layer; float loc[3], rot[3]; - + + object_add_generic_invoke_options(C, op); /* XXX these props don't get set right when only exec() is called */ if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; - + if (obedit && obedit->type == OB_FONT) return OPERATOR_CANCELLED; obedit = ED_object_add_type(C, OB_FONT, loc, rot, enter_editmode, layer); - + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); - + return OPERATOR_FINISHED; } @@ -619,18 +651,17 @@ void OBJECT_OT_text_add(wmOperatorType *ot) ot->name = "Add Text"; ot->description = "Add a text object to the scene"; ot->idname = "OBJECT_OT_text_add"; - + /* api callbacks */ + ot->invoke = ED_object_add_generic_invoke; ot->exec = object_add_text_exec; ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; ED_object_add_generic_props(ot, TRUE); } -/********************* Add Armature Operator ********************/ - static int object_armature_add_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); @@ -641,6 +672,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) unsigned int layer; float loc[3], rot[3]; + object_add_generic_invoke_options(C, op); /* XXX these props don't get set right when only exec() is called */ if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; @@ -655,76 +687,36 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Cannot create editmode armature"); return OPERATOR_CANCELLED; } - + /* v3d and rv3d are allowed to be NULL */ add_primitive_bone(CTX_data_scene(C), v3d, rv3d); /* userdef */ if (newob && !enter_editmode) ED_object_exit_editmode(C, EM_FREEDATA); - + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); - + return OPERATOR_FINISHED; } void OBJECT_OT_armature_add(wmOperatorType *ot) -{ +{ /* identifiers */ ot->name = "Add Armature"; ot->description = "Add an armature object to the scene"; ot->idname = "OBJECT_OT_armature_add"; - + /* api callbacks */ + ot->invoke = ED_object_add_generic_invoke; ot->exec = object_armature_add_exec; ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; ED_object_add_generic_props(ot, TRUE); } -/********************* Add Empty Operator ********************/ - -static int object_empty_add_exec(bContext *C, wmOperator *op) -{ - Object *ob; - int type = RNA_enum_get(op->ptr, "type"); - unsigned int layer; - float loc[3], rot[3]; - - if (!ED_object_add_generic_get_opts(C, op, loc, rot, NULL, &layer, NULL)) - return OPERATOR_CANCELLED; - - ob = ED_object_add_type(C, OB_EMPTY, loc, rot, FALSE, layer); - ob->empty_drawtype = type; - - return OPERATOR_FINISHED; -} - -void OBJECT_OT_empty_add(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Add Empty"; - ot->description = "Add an empty object to the scene"; - ot->idname = "OBJECT_OT_empty_add"; - - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = object_empty_add_exec; - ot->poll = ED_operator_objectmode; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", object_empty_drawtype_items, 0, "Type", ""); - - ED_object_add_generic_props(ot, FALSE); -} - -/********************* Add Lamp Operator ********************/ - static const char *get_lamp_defname(int type) { switch (type) { @@ -744,10 +736,12 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op) Object *ob; Lamp *la; int type = RNA_enum_get(op->ptr, "type"); + int enter_editmode; unsigned int layer; float loc[3], rot[3]; - - if (!ED_object_add_generic_get_opts(C, op, loc, rot, NULL, &layer, NULL)) + + object_add_generic_invoke_options(C, op); + if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; ob = ED_object_add_type(C, OB_LAMP, loc, rot, FALSE, layer); @@ -761,7 +755,7 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op) ED_node_shader_default(scene, &la->id); la->use_nodes = TRUE; } - + return OPERATOR_FINISHED; } @@ -771,12 +765,12 @@ void OBJECT_OT_lamp_add(wmOperatorType *ot) ot->name = "Add Lamp"; ot->description = "Add a lamp object to the scene"; ot->idname = "OBJECT_OT_lamp_add"; - + /* api callbacks */ ot->invoke = WM_menu_invoke; ot->exec = object_lamp_add_exec; ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -786,16 +780,16 @@ void OBJECT_OT_lamp_add(wmOperatorType *ot) ED_object_add_generic_props(ot, FALSE); } -/********************* Add Group Instance Operator ********************/ - static int group_instance_add_exec(bContext *C, wmOperator *op) { Group *group = BLI_findlink(&CTX_data_main(C)->group, RNA_enum_get(op->ptr, "group")); + int enter_editmode; unsigned int layer; float loc[3], rot[3]; - - if (!ED_object_add_generic_get_opts(C, op, loc, rot, NULL, &layer, NULL)) + + object_add_generic_invoke_options(C, op); + if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; if (group) { @@ -818,45 +812,20 @@ static int group_instance_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -/* only used as menu */ -void OBJECT_OT_group_instance_add(wmOperatorType *ot) -{ - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Add Group Instance"; - ot->description = "Add a dupligroup instance"; - ot->idname = "OBJECT_OT_group_instance_add"; - - /* api callbacks */ - ot->invoke = WM_enum_search_invoke; - ot->exec = group_instance_add_exec; - ot->poll = ED_operator_objectmode; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", ""); - RNA_def_enum_funcs(prop, RNA_group_itemf); - ot->prop = prop; - ED_object_add_generic_props(ot, FALSE); -} - -/********************* Add Speaker Operator ********************/ - static int object_speaker_add_exec(bContext *C, wmOperator *op) { Object *ob; + int enter_editmode; unsigned int layer; float loc[3], rot[3]; Scene *scene = CTX_data_scene(C); - if (!ED_object_add_generic_get_opts(C, op, loc, rot, NULL, &layer, NULL)) + object_add_generic_invoke_options(C, op); + if (!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; ob = ED_object_add_type(C, OB_SPEAKER, loc, rot, FALSE, layer); - + /* to make it easier to start using this immediately in NLA, a default sound clip is created * ready to be moved around to retime the sound and/or make new sound clips */ @@ -867,14 +836,14 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) NlaStrip *strip = add_nla_soundstrip(CTX_data_scene(C), ob->data); strip->start = CFRA; strip->end += strip->start; - + /* hook them up */ BKE_nlatrack_add_strip(nlt, strip); - + /* auto-name the strip, and give the track an interesting name */ strcpy(nlt->name, "SoundTrack"); BKE_nlastrip_validate_name(adt, strip); - + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); } @@ -898,6 +867,32 @@ void OBJECT_OT_speaker_add(wmOperatorType *ot) ED_object_add_generic_props(ot, TRUE); } +/* only used as menu */ +void OBJECT_OT_group_instance_add(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Add Group Instance"; + ot->description = "Add a dupligroup instance"; + ot->idname = "OBJECT_OT_group_instance_add"; + + /* api callbacks */ + ot->invoke = WM_enum_search_invoke; + ot->exec = group_instance_add_exec; + + ot->poll = ED_operator_objectmode; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", ""); + RNA_def_enum_funcs(prop, RNA_group_itemf); + ot->prop = prop; + ED_object_add_generic_props(ot, FALSE); +} + /**************************** Delete Object *************************/ static void object_delete_check_glsl_update(Object *ob) @@ -906,7 +901,7 @@ static void object_delete_check_glsl_update(Object *ob) * are being tagged to be updated when object is removing from scene */ if (ob->type == OB_LAMP) { - if (ob->gpulamp.first) + if (ob->gpulamp.first) GPU_lamp_free(ob); } } @@ -928,12 +923,16 @@ static int object_delete_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); const short use_global = RNA_boolean_get(op->ptr, "use_global"); - + /* int is_lamp = FALSE; */ /* UNUSED */ + if (CTX_data_edit_object(C)) return OPERATOR_CANCELLED; - + CTX_DATA_BEGIN (C, Base *, base, selected_bases) { + + /* if (base->object->type==OB_LAMP) is_lamp = TRUE; */ + /* deselect object -- it could be used in other scenes */ base->object->flag &= ~SELECT; @@ -960,10 +959,10 @@ static int object_delete_exec(bContext *C, wmOperator *op) DAG_scene_sort(bmain, scene); DAG_ids_flush_update(bmain, 0); - + WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); - + return OPERATOR_FINISHED; } @@ -973,12 +972,12 @@ void OBJECT_OT_delete(wmOperatorType *ot) ot->name = "Delete"; ot->description = "Delete selected objects"; ot->idname = "OBJECT_OT_delete"; - + /* api callbacks */ ot->invoke = WM_operator_confirm; ot->exec = object_delete_exec; ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -994,29 +993,29 @@ static void copy_object_set_idnew(bContext *C, int dupflag) Material *ma, *mao; ID *id; int a; - + /* XXX check object pointers */ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { BKE_object_relink(ob); } CTX_DATA_END; - + /* materials */ if (dupflag & USER_DUP_MAT) { mao = bmain->mat.first; while (mao) { if (mao->id.newid) { + ma = (Material *)mao->id.newid; - + if (dupflag & USER_DUP_TEX) { for (a = 0; a < MAX_MTEX; a++) { if (ma->mtex[a]) { id = (ID *)ma->mtex[a]->tex; if (id) { ID_NEW_US(ma->mtex[a]->tex) - else - ma->mtex[a]->tex = BKE_texture_copy(ma->mtex[a]->tex); + else ma->mtex[a]->tex = BKE_texture_copy(ma->mtex[a]->tex); id->us--; } } @@ -1026,8 +1025,7 @@ static void copy_object_set_idnew(bContext *C, int dupflag) id = (ID *)ma->ipo; if (id) { ID_NEW_US(ma->ipo) - else - ma->ipo = copy_ipo(ma->ipo); + else ma->ipo = copy_ipo(ma->ipo); id->us--; } #endif // XXX old animation system @@ -1035,7 +1033,7 @@ static void copy_object_set_idnew(bContext *C, int dupflag) mao = mao->id.next; } } - + #if 0 // XXX old animation system /* lamps */ if (dupflag & USER_DUP_IPO) { @@ -1046,15 +1044,14 @@ static void copy_object_set_idnew(bContext *C, int dupflag) id = (ID *)lan->ipo; if (id) { ID_NEW_US(lan->ipo) - else - lan->ipo = copy_ipo(lan->ipo); + else lan->ipo = copy_ipo(lan->ipo); id->us--; } } la = la->id.next; } } - + /* ipos */ ipo = bmain->ipo.first; while (ipo) { @@ -1070,9 +1067,9 @@ static void copy_object_set_idnew(bContext *C, int dupflag) ipo = ipo->id.next; } #endif // XXX old animation system - + set_sca_new_poins(); - + clear_id_newpoins(); } @@ -1085,17 +1082,17 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, ListBase *lb; DupliObject *dob; GHash *dupli_gh = NULL, *parent_gh = NULL; - + if (!(base->object->transflag & OB_DUPLI)) return; - - lb = object_duplilist(scene, base->object, FALSE); + + lb = object_duplilist(scene, base->object); if (use_hierarchy || use_base_parent) { dupli_gh = BLI_ghash_ptr_new("make_object_duplilist_real dupli_gh"); parent_gh = BLI_ghash_pair_new("make_object_duplilist_real parent_gh"); } - + for (dob = lb->first; dob; dob = dob->next) { Base *basen; Object *ob = BKE_object_copy(dob->ob); @@ -1103,24 +1100,24 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, * should be implemented better... */ if (ob->mat == NULL) ob->totcol = 0; - + basen = MEM_dupallocN(base); basen->flag &= ~(OB_FROMDUPLI | OB_FROMGROUP); ob->flag = basen->flag; basen->lay = base->lay; BLI_addhead(&scene->base, basen); /* addhead: othwise eternal loop */ basen->object = ob; - + /* make sure apply works */ BKE_free_animdata(&ob->id); ob->adt = NULL; - + ob->parent = NULL; ob->constraints.first = ob->constraints.last = NULL; ob->disp.first = ob->disp.last = NULL; ob->transflag &= ~OB_DUPLI; ob->lay = base->lay; - + copy_m4_m4(ob->obmat, dob->mat); BKE_object_apply_mat4(ob, ob->obmat, FALSE, FALSE); @@ -1129,7 +1126,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, if (parent_gh) BLI_ghash_insert(parent_gh, BLI_ghashutil_pairalloc(dob->ob, SET_INT_IN_POINTER(dob->index)), ob); } - + if (use_hierarchy) { for (dob = lb->first; dob; dob = dob->next) { /* original parents */ @@ -1189,6 +1186,8 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, invert_m4_m4(ob_dst->parentinv, dob->mat); BKE_object_apply_mat4(ob_dst, dob->mat, FALSE, TRUE); DAG_id_tag_update(&ob_dst->id, OB_RECALC_OB); + + } } @@ -1198,9 +1197,9 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, BLI_ghash_free(parent_gh, BLI_ghashutil_pairfree, NULL); copy_object_set_idnew(C, 0); - + free_object_duplilist(lb); - + base->object->transflag &= ~OB_DUPLI; } @@ -1211,9 +1210,9 @@ static int object_duplicates_make_real_exec(bContext *C, wmOperator *op) const short use_base_parent = RNA_boolean_get(op->ptr, "use_base_parent"); const short use_hierarchy = RNA_boolean_get(op->ptr, "use_hierarchy"); - + clear_id_newpoins(); - + CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { make_object_duplilist_real(C, scene, base, use_base_parent, use_hierarchy); @@ -1227,22 +1226,23 @@ static int object_duplicates_make_real_exec(bContext *C, wmOperator *op) DAG_ids_flush_update(bmain, 0); WM_event_add_notifier(C, NC_SCENE, scene); WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL); - + return OPERATOR_FINISHED; } void OBJECT_OT_duplicates_make_real(wmOperatorType *ot) { + /* identifiers */ ot->name = "Make Duplicates Real"; ot->description = "Make dupli objects attached to this object real"; ot->idname = "OBJECT_OT_duplicates_make_real"; - + /* api callbacks */ ot->exec = object_duplicates_make_real_exec; - + ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1616,12 +1616,12 @@ void OBJECT_OT_convert(wmOperatorType *ot) ot->name = "Convert to"; ot->description = "Convert selected objects to another type"; ot->idname = "OBJECT_OT_convert"; - + /* api callbacks */ ot->invoke = WM_menu_invoke; ot->exec = convert_exec; ot->poll = convert_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1655,12 +1655,12 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base else { obn = BKE_object_copy(ob); obn->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; - + basen = MEM_mallocN(sizeof(Base), "duplibase"); *basen = *base; BLI_addhead(&scene->base, basen); /* addhead: prevent eternal loop */ basen->object = obn; - + if (basen->flag & OB_FROMGROUP) { Group *group; for (group = bmain->group.first; group; group = group->id.next) { @@ -1668,21 +1668,20 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base add_to_group(group, obn, scene, basen); } } - + /* duplicates using userflags */ if (dupflag & USER_DUP_ACT) { BKE_copy_animdata_id_action(&obn->id); } - + if (dupflag & USER_DUP_MAT) { for (a = 0; a < obn->totcol; a++) { id = (ID *)obn->mat[a]; if (id) { ID_NEW_US(obn->mat[a]) - else - obn->mat[a] = BKE_material_copy(obn->mat[a]); + else obn->mat[a] = BKE_material_copy(obn->mat[a]); id->us--; - + if (dupflag & USER_DUP_ACT) { BKE_copy_animdata_id_action(&obn->mat[a]->id); } @@ -1695,9 +1694,8 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base id = (ID *) psys->part; if (id) { ID_NEW_US(psys->part) - else - psys->part = BKE_particlesettings_copy(psys->part); - + else psys->part = BKE_particlesettings_copy(psys->part); + if (dupflag & USER_DUP_ACT) { BKE_copy_animdata_id_action(&psys->part->id); } @@ -1706,19 +1704,21 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base } } } - + id = obn->data; didit = 0; - + switch (obn->type) { case OB_MESH: if (dupflag & USER_DUP_MESH) { ID_NEW_US2(obn->data) else { obn->data = BKE_mesh_copy(obn->data); + if (obn->fluidsimSettings) { obn->fluidsimSettings->orgMesh = (Mesh *)obn->data; } + didit = 1; } id->us--; @@ -1774,10 +1774,11 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base id->us--; } break; + case OB_ARMATURE: obn->recalc |= OB_RECALC_DATA; - if (obn->pose) - obn->pose->flag |= POSE_RECALC; + if (obn->pose) obn->pose->flag |= POSE_RECALC; + if (dupflag & USER_DUP_ARM) { ID_NEW_US2(obn->data) else { @@ -1787,7 +1788,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base } id->us--; } + break; + case OB_LATTICE: if (dupflag != 0) { ID_NEW_US2(obn->data) @@ -1818,12 +1821,13 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base id->us--; } break; + } /* check if obdata is copied */ if (didit) { Key *key = BKE_key_from_object(obn); - + if (dupflag & USER_DUP_ACT) { bActuator *act; @@ -1842,7 +1846,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base } } } - + if (dupflag & USER_DUP_MAT) { matarar = give_matarar(obn); if (matarar) { @@ -1850,8 +1854,8 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base id = (ID *)(*matarar)[a]; if (id) { ID_NEW_US((*matarar)[a]) - else - (*matarar)[a] = BKE_material_copy((*matarar)[a]); + else (*matarar)[a] = BKE_material_copy((*matarar)[a]); + id->us--; } } @@ -1902,14 +1906,14 @@ static int duplicate_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); int linked = RNA_boolean_get(op->ptr, "linked"); int dupflag = (linked) ? 0 : U.dupflag; - + clear_id_newpoins(); clear_sca_new_poins(); /* sensor/contr/act */ - + CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { Base *basen = object_add_duplicate_internal(bmain, scene, base, dupflag); - + /* note that this is safe to do with this context iterator, * the list is made in advance */ ED_base_object_select(base, BA_DESELECT); @@ -1941,19 +1945,19 @@ static int duplicate_exec(bContext *C, wmOperator *op) void OBJECT_OT_duplicate(wmOperatorType *ot) { PropertyRNA *prop; - + /* identifiers */ ot->name = "Duplicate Objects"; ot->description = "Duplicate selected objects"; ot->idname = "OBJECT_OT_duplicate"; - + /* api callbacks */ ot->exec = duplicate_exec; ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* to give to transform */ RNA_def_boolean(ot->srna, "linked", 0, "Linked", "Duplicate object but not object data, linking to the original data"); prop = RNA_def_enum(ot->srna, "mode", transform_mode_types, TFM_TRANSLATION, "Mode", ""); @@ -1962,6 +1966,7 @@ void OBJECT_OT_duplicate(wmOperatorType *ot) /* **************** add named object, for dragdrop ************* */ + static int add_named_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -2016,32 +2021,34 @@ void OBJECT_OT_add_named(wmOperatorType *ot) ot->name = "Add Named Object"; ot->description = "Add named object"; ot->idname = "OBJECT_OT_add_named"; - + /* api callbacks */ ot->exec = add_named_exec; ot->poll = ED_operator_objectmode; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + RNA_def_boolean(ot->srna, "linked", 0, "Linked", "Duplicate object but not object data, linking to the original data"); RNA_def_string(ot->srna, "name", "Cube", MAX_ID_NAME - 2, "Name", "Object name to add"); } -/**************************** Join *************************/ + +/**************************** Join *************************/ static int join_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - + if (!ob || ob->id.lib) return 0; - + if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE)) return ED_operator_screenactive(C); else return 0; } + static int join_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); @@ -2062,7 +2069,7 @@ static int join_exec(bContext *C, wmOperator *op) return join_curve_exec(C, op); else if (ob->type == OB_ARMATURE) return join_armature_exec(C, op); - + return OPERATOR_CANCELLED; } @@ -2072,23 +2079,22 @@ void OBJECT_OT_join(wmOperatorType *ot) ot->name = "Join"; ot->description = "Join selected objects into active object"; ot->idname = "OBJECT_OT_join"; - + /* api callbacks */ ot->exec = join_exec; ot->poll = join_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /**************************** Join as Shape Key*************************/ - static int join_shapes_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - + if (!ob || ob->id.lib) return 0; - + /* only meshes supported at the moment */ if (ob->type == OB_MESH) return ED_operator_screenactive(C); @@ -2100,7 +2106,7 @@ static int join_shapes_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); - + if (scene->obedit) { BKE_report(op->reports, RPT_ERROR, "This data does not support joining in editmode"); return OPERATOR_CANCELLED; @@ -2109,10 +2115,10 @@ static int join_shapes_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata"); return OPERATOR_CANCELLED; } - + if (ob->type == OB_MESH) return join_mesh_shapes_exec(C, op); - + return OPERATOR_CANCELLED; } @@ -2122,11 +2128,11 @@ void OBJECT_OT_join_shapes(wmOperatorType *ot) ot->name = "Join as Shapes"; ot->description = "Merge selected objects to shapes of active object"; ot->idname = "OBJECT_OT_join_shapes"; - + /* api callbacks */ ot->exec = join_shapes_exec; ot->poll = join_shapes_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } |