Fix [#22078] Cannot apply modifier in python (context error)

Previously all modifier operators relied on the buttons layout data context pointer to 
decide which modifier to work on. This meant that these operators would only work 
from from the properties panel, and not from scripting/macros or for operator redo.

This commit makes all modifier operators take the modifier name as an operator 
property, so the operators can be re-done or executed outside of the modifier panel. 
When invoking the operators from the modifier panel, they automatically fill in the 
operator property from context.

This isn't a perfect API design, but it does bring these operators in line with the design 
of being able to access all UI functionality via other means like scripts.
This commit is contained in:
Matt Ebb 2010-04-22 01:55:10 +00:00
parent 27fa482714
commit 5c94896490
4 changed files with 255 additions and 69 deletions

View File

@ -292,6 +292,7 @@ void modifiers_foreachIDLink(struct Object *ob,
IDWalkFunc walk,
void *userData);
struct ModifierData *modifiers_findByType(struct Object *ob, ModifierType type);
struct ModifierData *modifiers_findByName(struct Object *ob, const char *name);
void modifiers_clearErrors(struct Object *ob);
int modifiers_getCageIndex(struct Scene *scene, struct Object *ob,
int *lastPossibleCageIndex_r, int virtual_);

View File

@ -176,6 +176,17 @@ ModifierData *modifiers_findByType(Object *ob, ModifierType type)
return md;
}
ModifierData *modifiers_findByName(Object *ob, const char *name)
{
ModifierData *md = ob->modifiers.first;
for (; md; md=md->next)
if (strcmp(md->name, name)==0)
break;
return md;
}
void modifiers_clearErrors(Object *ob)
{
ModifierData *md = ob->modifiers.first;

View File

@ -815,6 +815,7 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, Modif
}
}
else {
uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
uiItemEnumO(row, "OBJECT_OT_modifier_apply", "Apply", 0, "apply_as", MODIFIER_APPLY_DATA);
if (modifier_sameTopology(md))

View File

@ -573,16 +573,69 @@ void OBJECT_OT_modifier_add(wmOperatorType *ot)
ot->prop= prop;
}
/************************ poll function for operators using mod names and data context *********************/
static int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", rna_type);
Object *ob= (ptr.id.data)?ptr.id.data:ED_object_active_context(C);
if (!ob || ob->id.lib) return 0;
if (ptr.data && ((ID*)ptr.id.data)->lib) return 0;
return 1;
}
static int edit_modifier_poll(bContext *C)
{
return edit_modifier_poll_generic(C, &RNA_Modifier);
}
static void edit_modifier_properties(wmOperatorType *ot)
{
RNA_def_string(ot->srna, "modifier", "", 32, "Modifier", "Name of the modifier to apply");
}
static int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
ModifierData *md;
if (RNA_property_is_set(op->ptr, "modifier"))
return 1;
if (ptr.data) {
md = ptr.data;
RNA_string_set(op->ptr, "modifier", md->name);
return 1;
}
return 0;
}
static ModifierData *edit_modifier_property_get(bContext *C, wmOperator *op, Object *ob, int type)
{
char modifier_name[32];
ModifierData *md;
RNA_string_get(op->ptr, "modifier", modifier_name);
md = modifiers_findByName(ob, modifier_name);
if (md && type != 0 && md->type != type)
md = NULL;
return md;
}
/************************ remove modifier operator *********************/
static int modifier_remove_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
Object *ob= ptr.id.data;
ModifierData *md= ptr.data;
if(!ED_object_modifier_remove(op->reports, scene, ob, md))
Object *ob = ED_object_active_context(C);
ModifierData *md = edit_modifier_property_get(C, op, ob, 0);
if(!ob || !md || !ED_object_modifier_remove(op->reports, scene, ob, md))
return OPERATOR_CANCELLED;
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
@ -590,28 +643,37 @@ static int modifier_remove_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static int modifier_remove_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
if (edit_modifier_invoke_properties(C, op))
return modifier_remove_exec(C, op);
else
return OPERATOR_CANCELLED;
}
void OBJECT_OT_modifier_remove(wmOperatorType *ot)
{
ot->name= "Remove Modifier";
ot->description= "Remove a modifier from the active object";
ot->idname= "OBJECT_OT_modifier_remove";
ot->invoke= modifier_remove_invoke;
ot->exec= modifier_remove_exec;
ot->poll= modifier_poll;
ot->poll= edit_modifier_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
edit_modifier_properties(ot);
}
/************************ move up modifier operator *********************/
static int modifier_move_up_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
Object *ob= ptr.id.data;
ModifierData *md= ptr.data;
Object *ob = ED_object_active_context(C);
ModifierData *md = edit_modifier_property_get(C, op, ob, 0);
if(!ED_object_modifier_move_up(op->reports, ob, md))
if(!ob || !md || !ED_object_modifier_move_up(op->reports, ob, md))
return OPERATOR_CANCELLED;
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
@ -620,26 +682,35 @@ static int modifier_move_up_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static int modifier_move_up_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
if (edit_modifier_invoke_properties(C, op))
return modifier_move_up_exec(C, op);
else
return OPERATOR_CANCELLED;
}
void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
{
ot->name= "Move Up Modifier";
ot->description= "Move modifier up in the stack";
ot->idname= "OBJECT_OT_modifier_move_up";
ot->invoke= modifier_move_up_invoke;
ot->exec= modifier_move_up_exec;
ot->poll= modifier_poll;
ot->poll= edit_modifier_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
edit_modifier_properties(ot);
}
/************************ move down modifier operator *********************/
static int modifier_move_down_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
Object *ob= ptr.id.data;
ModifierData *md= ptr.data;
Object *ob = ED_object_active_context(C);
ModifierData *md = edit_modifier_property_get(C, op, ob, 0);
if(!ob || !md || !ED_object_modifier_move_down(op->reports, ob, md))
return OPERATOR_CANCELLED;
@ -650,17 +721,27 @@ static int modifier_move_down_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static int modifier_move_down_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
if (edit_modifier_invoke_properties(C, op))
return modifier_move_down_exec(C, op);
else
return OPERATOR_CANCELLED;
}
void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
{
ot->name= "Move Down Modifier";
ot->description= "Move modifier down in the stack";
ot->idname= "OBJECT_OT_modifier_move_down";
ot->invoke= modifier_move_down_invoke;
ot->exec= modifier_move_down_exec;
ot->poll= modifier_poll;
ot->poll= edit_modifier_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
edit_modifier_properties(ot);
}
/************************ apply modifier operator *********************/
@ -668,13 +749,13 @@ void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
static int modifier_apply_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
Object *ob= ptr.id.data;
ModifierData *md= ptr.data;
Object *ob = ED_object_active_context(C);
ModifierData *md = edit_modifier_property_get(C, op, ob, 0);
int apply_as= RNA_enum_get(op->ptr, "apply_as");
if(!ob || !md || !ED_object_modifier_apply(op->reports, scene, ob, md, apply_as))
if(!ob || !md || !ED_object_modifier_apply(op->reports, scene, ob, md, apply_as)) {
return OPERATOR_CANCELLED;
}
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
@ -682,6 +763,14 @@ static int modifier_apply_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static int modifier_apply_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
if (edit_modifier_invoke_properties(C, op))
return modifier_apply_exec(C, op);
else
return OPERATOR_CANCELLED;
}
static EnumPropertyItem modifier_apply_as_items[] = {
{MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
{MODIFIER_APPLY_SHAPE, "SHAPE", 0, "New Shape", "Apply deform-only modifier to a new shape on this object"},
@ -693,14 +782,15 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot)
ot->description= "Apply modifier and remove from the stack";
ot->idname= "OBJECT_OT_modifier_apply";
//ot->invoke= WM_menu_invoke;
ot->invoke= modifier_apply_invoke;
ot->exec= modifier_apply_exec;
ot->poll= modifier_poll;
ot->poll= edit_modifier_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_enum(ot->srna, "apply_as", modifier_apply_as_items, MODIFIER_APPLY_DATA, "Apply as", "How to apply the modifier to the geometry");
edit_modifier_properties(ot);
}
/************************ convert modifier operator *********************/
@ -708,10 +798,9 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot)
static int modifier_convert_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
Object *ob= ptr.id.data;
ModifierData *md= ptr.data;
Object *ob = ED_object_active_context(C);
ModifierData *md = edit_modifier_property_get(C, op, ob, 0);
if(!ob || !md || !ED_object_modifier_convert(op->reports, scene, ob, md))
return OPERATOR_CANCELLED;
@ -721,26 +810,35 @@ static int modifier_convert_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static int modifier_convert_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
if (edit_modifier_invoke_properties(C, op))
return modifier_convert_exec(C, op);
else
return OPERATOR_CANCELLED;
}
void OBJECT_OT_modifier_convert(wmOperatorType *ot)
{
ot->name= "Convert Modifier";
ot->description= "Convert particles to a mesh object";
ot->idname= "OBJECT_OT_modifier_convert";
ot->invoke= modifier_convert_invoke;
ot->exec= modifier_convert_exec;
ot->poll= modifier_poll;
ot->poll= edit_modifier_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
edit_modifier_properties(ot);
}
/************************ copy modifier operator *********************/
static int modifier_copy_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
Object *ob= ptr.id.data;
ModifierData *md= ptr.data;
Object *ob = ED_object_active_context(C);
ModifierData *md = edit_modifier_property_get(C, op, ob, 0);
if(!ob || !md || !ED_object_modifier_copy(op->reports, ob, md))
return OPERATOR_CANCELLED;
@ -751,62 +849,83 @@ static int modifier_copy_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static int modifier_copy_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
if (edit_modifier_invoke_properties(C, op))
return modifier_copy_exec(C, op);
else
return OPERATOR_CANCELLED;
}
void OBJECT_OT_modifier_copy(wmOperatorType *ot)
{
ot->name= "Copy Modifier";
ot->description= "Duplicate modifier at the same position in the stack";
ot->idname= "OBJECT_OT_modifier_copy";
ot->invoke= modifier_copy_invoke;
ot->exec= modifier_copy_exec;
ot->poll= modifier_poll;
ot->poll= edit_modifier_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
edit_modifier_properties(ot);
}
/************* multires delete higher levels operator ****************/
static int multires_poll(bContext *C)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_MultiresModifier);
ID *id= ptr.id.data;
return (ptr.data && id && !id->lib);
return edit_modifier_poll_generic(C, &RNA_MultiresModifier);
}
static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_MultiresModifier);
Object *ob= ptr.id.data;
MultiresModifierData *mmd= ptr.data;
if(mmd) {
multiresModifier_del_levels(mmd, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
}
Object *ob = ED_object_active_context(C);
MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(C, op, ob, eModifierType_Multires);
if (!mmd)
return OPERATOR_CANCELLED;
multiresModifier_del_levels(mmd, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
return OPERATOR_FINISHED;
}
static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
if (edit_modifier_invoke_properties(C, op))
return multires_higher_levels_delete_exec(C, op);
else
return OPERATOR_CANCELLED;
}
void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
{
ot->name= "Delete Higher Levels";
ot->idname= "OBJECT_OT_multires_higher_levels_delete";
ot->poll= multires_poll;
ot->invoke= multires_higher_levels_delete_invoke;
ot->exec= multires_higher_levels_delete_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
edit_modifier_properties(ot);
}
/****************** multires subdivide operator *********************/
static int multires_subdivide_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_MultiresModifier);
Object *ob= ptr.id.data;
MultiresModifierData *mmd= ptr.data;
Object *ob = ED_object_active_context(C);
MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(C, op, ob, eModifierType_Multires);
if (!mmd)
return OPERATOR_CANCELLED;
multiresModifier_subdivide(mmd, ob, 0, mmd->simple);
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
@ -815,6 +934,14 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static int multires_subdivide_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
if (edit_modifier_invoke_properties(C, op))
return multires_subdivide_exec(C, op);
else
return OPERATOR_CANCELLED;
}
void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
{
ot->name= "Multires Subdivide";
@ -822,20 +949,24 @@ void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
ot->idname= "OBJECT_OT_multires_subdivide";
ot->poll= multires_poll;
ot->invoke= multires_subdivide_invoke;
ot->exec= multires_subdivide_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
edit_modifier_properties(ot);
}
/****************** multires reshape operator *********************/
static int multires_reshape_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_MultiresModifier);
Object *ob= ptr.id.data, *secondob= NULL;
MultiresModifierData *mmd= ptr.data;
Object *ob= ED_object_active_context(C), *secondob= NULL;
MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(C, op, ob, eModifierType_Multires);
if (!mmd)
return OPERATOR_CANCELLED;
CTX_DATA_BEGIN(C, Object*, selob, selected_editable_objects) {
if(selob->type == OB_MESH && selob != ob) {
secondob= selob;
@ -860,6 +991,14 @@ static int multires_reshape_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static int multires_reshape_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
if (edit_modifier_invoke_properties(C, op))
return multires_reshape_exec(C, op);
else
return OPERATOR_CANCELLED;
}
void OBJECT_OT_multires_reshape(wmOperatorType *ot)
{
ot->name= "Multires Reshape";
@ -867,18 +1006,19 @@ void OBJECT_OT_multires_reshape(wmOperatorType *ot)
ot->idname= "OBJECT_OT_multires_reshape";
ot->poll= multires_poll;
ot->invoke= multires_reshape_invoke;
ot->exec= multires_reshape_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
edit_modifier_properties(ot);
}
/****************** multires save external operator *********************/
static int multires_save_external_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_MultiresModifier);
Object *ob= ptr.id.data;
Object *ob = ED_object_active_context(C);
Mesh *me= (ob)? ob->data: op->customdata;
char path[FILE_MAX];
@ -900,11 +1040,19 @@ static int multires_save_external_exec(bContext *C, wmOperator *op)
static int multires_save_external_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_MultiresModifier);
Object *ob= ptr.id.data;
Object *ob = ED_object_active_context(C);
MultiresModifierData *mmd;
Mesh *me= ob->data;
char path[FILE_MAX];
if (!edit_modifier_invoke_properties(C, op))
return OPERATOR_CANCELLED;
mmd = (MultiresModifierData *)edit_modifier_property_get(C, op, ob, eModifierType_Multires);
if (!mmd)
return OPERATOR_CANCELLED;
if(CustomData_external_test(&me->fdata, CD_MDISPS))
return OPERATOR_CANCELLED;
@ -930,19 +1078,20 @@ void OBJECT_OT_multires_save_external(wmOperatorType *ot)
// XXX modifier no longer in context after file browser .. ot->poll= multires_poll;
ot->exec= multires_save_external_exec;
ot->invoke= multires_save_external_invoke;
ot->poll= multires_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
WM_operator_properties_filesel(ot, FOLDERFILE|BTXFILE, FILE_SPECIAL, FILE_SAVE);
edit_modifier_properties(ot);
}
/****************** multires pack operator *********************/
static int multires_pack_external_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_MultiresModifier);
Object *ob= ptr.id.data;
Object *ob = ED_object_active_context(C);
Mesh *me= ob->data;
if(!CustomData_external_test(&me->fdata, CD_MDISPS))
@ -971,17 +1120,17 @@ void OBJECT_OT_multires_pack_external(wmOperatorType *ot)
static int meshdeform_poll(bContext *C)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_MeshDeformModifier);
ID *id= ptr.id.data;
return (ptr.data && id && !id->lib);
return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier);
}
static int meshdeform_bind_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
PointerRNA ptr= CTX_data_pointer_get(C, "modifier");
Object *ob= ptr.id.data;
MeshDeformModifierData *mmd= ptr.data;
Object *ob = ED_object_active_context(C);
MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(C, op, ob, eModifierType_MeshDeform);
if (!mmd)
return OPERATOR_CANCELLED;
if(mmd->bindcos) {
if(mmd->bindweights) MEM_freeN(mmd->bindweights);
@ -997,6 +1146,9 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op)
mmd->totvert= 0;
mmd->totcagevert= 0;
mmd->totinfluence= 0;
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
}
else {
DerivedMesh *dm;
@ -1027,6 +1179,14 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static int meshdeform_bind_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
if (edit_modifier_invoke_properties(C, op))
return meshdeform_bind_exec(C, op);
else
return OPERATOR_CANCELLED;
}
void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
{
/* identifiers */
@ -1036,26 +1196,28 @@ void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
/* api callbacks */
ot->poll= meshdeform_poll;
ot->invoke= meshdeform_bind_invoke;
ot->exec= meshdeform_bind_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
edit_modifier_properties(ot);
}
/****************** explode refresh operator *********************/
static int explode_refresh_poll(bContext *C)
static int explode_poll(bContext *C)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_ExplodeModifier);
ID *id= ptr.id.data;
return (ptr.data && id && !id->lib);
return edit_modifier_poll_generic(C, &RNA_ExplodeModifier);
}
static int explode_refresh_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_ExplodeModifier);
Object *ob= ptr.id.data;
ExplodeModifierData *emd= ptr.data;
Object *ob = ED_object_active_context(C);
ExplodeModifierData *emd = (ExplodeModifierData *)edit_modifier_property_get(C, op, ob, eModifierType_Explode);
if (!emd)
return OPERATOR_CANCELLED;
emd->flag |= eExplodeFlag_CalcFaces;
@ -1065,16 +1227,27 @@ static int explode_refresh_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static int explode_refresh_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
if (edit_modifier_invoke_properties(C, op))
return explode_refresh_exec(C, op);
else
return OPERATOR_CANCELLED;
}
void OBJECT_OT_explode_refresh(wmOperatorType *ot)
{
ot->name= "Explode Refresh";
ot->description= "Refresh data in the Explode modifier";
ot->idname= "OBJECT_OT_explode_refresh";
ot->poll= explode_poll;
ot->invoke= explode_refresh_invoke;
ot->exec= explode_refresh_exec;
ot->poll= explode_refresh_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
edit_modifier_properties(ot);
}