merge with/from trunk at r35190
[blender.git] / source / blender / editors / object / object_modifier.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
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.
10  *
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.
15  *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, 2009
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <math.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_curve_types.h"
35 #include "DNA_key_types.h"
36 #include "DNA_mesh_types.h"
37 #include "DNA_meshdata_types.h"
38 #include "DNA_object_force.h"
39 #include "DNA_scene_types.h"
40
41 #include "BLI_math.h"
42 #include "BLI_listbase.h"
43 #include "BLI_string.h"
44 #include "BLI_path_util.h"
45 #include "BLI_editVert.h"
46 #include "BLI_utildefines.h"
47
48 #include "BKE_curve.h"
49 #include "BKE_context.h"
50 #include "BKE_depsgraph.h"
51 #include "BKE_displist.h"
52 #include "BKE_DerivedMesh.h"
53 #include "BKE_effect.h"
54 #include "BKE_global.h"
55 #include "BKE_key.h"
56 #include "BKE_lattice.h"
57 #include "BKE_main.h"
58 #include "BKE_mesh.h"
59 #include "BKE_modifier.h"
60 #include "BKE_multires.h"
61 #include "BKE_report.h"
62 #include "BKE_object.h"
63 #include "BKE_particle.h"
64 #include "BKE_softbody.h"
65 #include "BKE_tessmesh.h"
66
67 #include "RNA_access.h"
68 #include "RNA_define.h"
69 #include "RNA_enum_types.h"
70
71 #include "ED_armature.h"
72 #include "ED_object.h"
73 #include "ED_screen.h"
74 #include "ED_mesh.h"
75
76 #include "WM_api.h"
77 #include "WM_types.h"
78
79 #include "object_intern.h"
80
81 /******************************** API ****************************/
82
83 ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
84 {
85         ModifierData *md=NULL, *new_md=NULL;
86         ModifierTypeInfo *mti = modifierType_getInfo(type);
87         
88         /* only geometry objects should be able to get modifiers [#25291] */
89         if(!ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
90                 BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to Object '%s'", ob->id.name+2);
91                 return NULL;
92         }
93         
94         if(mti->flags&eModifierTypeFlag_Single) {
95                 if(modifiers_findByType(ob, type)) {
96                         BKE_report(reports, RPT_WARNING, "Only one modifier of this type allowed.");
97                         return NULL;
98                 }
99         }
100         
101         if(type == eModifierType_ParticleSystem) {
102                 /* don't need to worry about the new modifier's name, since that is set to the number
103                  * of particle systems which shouldn't have too many duplicates 
104                  */
105                 new_md = object_add_particle_system(scene, ob, name);
106         }
107         else {
108                 /* get new modifier data to add */
109                 new_md= modifier_new(type);
110                 
111                 if(mti->flags&eModifierTypeFlag_RequiresOriginalData) {
112                         md = ob->modifiers.first;
113                         
114                         while(md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform)
115                                 md = md->next;
116                         
117                         BLI_insertlinkbefore(&ob->modifiers, md, new_md);
118                 }
119                 else
120                         BLI_addtail(&ob->modifiers, new_md);
121
122                 if(name)
123                         BLI_strncpy(new_md->name, name, sizeof(new_md->name));
124
125                 /* make sure modifier data has unique name */
126
127                 modifier_unique_name(&ob->modifiers, new_md);
128                 
129                 /* special cases */
130                 if(type == eModifierType_Softbody) {
131                         if(!ob->soft) {
132                                 ob->soft= sbNew(scene);
133                                 ob->softflag |= OB_SB_GOAL|OB_SB_EDGES;
134                         }
135                 }
136                 else if(type == eModifierType_Collision) {
137                         if(!ob->pd)
138                                 ob->pd= object_add_collision_fields(0);
139                         
140                         ob->pd->deflect= 1;
141                         DAG_scene_sort(bmain, scene);
142                 }
143                 else if(type == eModifierType_Surface)
144                         DAG_scene_sort(bmain, scene);
145                 else if(type == eModifierType_Multires)
146                         /* set totlvl from existing MDISPS layer if object already had it */
147                         multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob);
148         }
149
150         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
151
152         return new_md;
153 }
154
155 int ED_object_modifier_remove(ReportList *reports, Main *bmain, Scene *scene, Object *ob, ModifierData *md)
156 {
157         ModifierData *obmd;
158         int sort_depsgraph = 0;
159
160         /* It seems on rapid delete it is possible to
161          * get called twice on same modifier, so make
162          * sure it is in list. */
163         for(obmd=ob->modifiers.first; obmd; obmd=obmd->next)
164                 if(obmd==md)
165                         break;
166         
167         if(!obmd) {
168                 BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'.", ob->id.name, md->name);
169                 return 0;
170         }
171
172         /* special cases */
173         if(md->type == eModifierType_ParticleSystem) {
174                 ParticleSystemModifierData *psmd=(ParticleSystemModifierData*)md;
175
176                 BLI_remlink(&ob->particlesystem, psmd->psys);
177                 psys_free(ob, psmd->psys);
178                 psmd->psys= NULL;
179         }
180         else if(md->type == eModifierType_Softbody) {
181                 if(ob->soft) {
182                         sbFree(ob->soft);
183                         ob->soft= NULL;
184                         ob->softflag= 0;
185                 }
186         }
187         else if(md->type == eModifierType_Collision) {
188                 if(ob->pd)
189                         ob->pd->deflect= 0;
190
191                 sort_depsgraph = 1;
192         }
193         else if(md->type == eModifierType_Surface) {
194                 if(ob->pd && ob->pd->shape == PFIELD_SHAPE_SURFACE)
195                         ob->pd->shape = PFIELD_SHAPE_PLANE;
196
197                 sort_depsgraph = 1;
198         }
199         else if(md->type == eModifierType_Smoke) {
200                 ob->dt = OB_TEXTURE;
201         }
202         else if(md->type == eModifierType_Multires) {
203                 Mesh *me= ob->data;
204
205                 if(me->edit_btmesh) {
206                         BMEditMesh *em= me->edit_btmesh;
207                         /* CustomData_external_remove is used here only to mark layer as non-external
208                            for further free-ing, so zero element count looks safer than em->totface */
209                         CustomData_external_remove(&em->bm->ldata, &me->id, CD_MDISPS, 0);
210                         BM_free_data_layer(em, &em->bm->ldata, CD_MDISPS);
211                 } else {
212                         CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
213                         CustomData_free_layer_active(&me->ldata, CD_MDISPS, me->totloop);
214                 }
215         }
216
217         if(ELEM(md->type, eModifierType_Softbody, eModifierType_Cloth) &&
218                 ob->particlesystem.first == NULL) {
219                 ob->mode &= ~OB_MODE_PARTICLE_EDIT;
220         }
221
222         BLI_remlink(&ob->modifiers, md);
223         modifier_free(md);
224
225         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
226
227         /* sorting has to be done after the update so that dynamic systems can react properly */
228         if(sort_depsgraph)
229                 DAG_scene_sort(bmain, scene);
230
231         return 1;
232 }
233
234 int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md)
235 {
236         if(md->prev) {
237                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
238
239                 if(mti->type!=eModifierTypeType_OnlyDeform) {
240                         ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
241
242                         if(nmti->flags&eModifierTypeFlag_RequiresOriginalData) {
243                                 BKE_report(reports, RPT_WARNING, "Cannot move above a modifier requiring original data.");
244                                 return 0;
245                         }
246                 }
247
248                 BLI_remlink(&ob->modifiers, md);
249                 BLI_insertlink(&ob->modifiers, md->prev->prev, md);
250         }
251
252         return 1;
253 }
254
255 int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *md)
256 {
257         if(md->next) {
258                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
259
260                 if(mti->flags&eModifierTypeFlag_RequiresOriginalData) {
261                         ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
262
263                         if(nmti->type!=eModifierTypeType_OnlyDeform) {
264                                 BKE_report(reports, RPT_WARNING, "Cannot move beyond a non-deforming modifier.");
265                                 return 0;
266                         }
267                 }
268
269                 BLI_remlink(&ob->modifiers, md);
270                 BLI_insertlink(&ob->modifiers, md->next, md);
271         }
272
273         return 1;
274 }
275
276 int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, Object *ob, ModifierData *md)
277 {
278         Object *obn;
279         ParticleSystem *psys;
280         ParticleCacheKey *key, **cache;
281         ParticleSettings *part;
282         Mesh *me;
283         MVert *mvert;
284         MEdge *medge;
285         int a, k, kmax;
286         int totvert=0, totedge=0, cvert=0;
287         int totpart=0, totchild=0;
288
289         if(md->type != eModifierType_ParticleSystem) return 0;
290         if(ob && ob->mode & OB_MODE_PARTICLE_EDIT) return 0;
291
292         psys=((ParticleSystemModifierData *)md)->psys;
293         part= psys->part;
294
295         if(part->ren_as != PART_DRAW_PATH || psys->pathcache == 0)
296                 return 0;
297
298         totpart= psys->totcached;
299         totchild= psys->totchildcache;
300
301         if(totchild && (part->draw&PART_DRAW_PARENT)==0)
302                 totpart= 0;
303
304         /* count */
305         cache= psys->pathcache;
306         for(a=0; a<totpart; a++) {
307                 key= cache[a];
308                 totvert+= key->steps+1;
309                 totedge+= key->steps;
310         }
311
312         cache= psys->childcache;
313         for(a=0; a<totchild; a++) {
314                 key= cache[a];
315                 totvert+= key->steps+1;
316                 totedge+= key->steps;
317         }
318
319         if(totvert==0) return 0;
320
321         /* add new mesh */
322         obn= add_object(scene, OB_MESH);
323         me= obn->data;
324         
325         me->totvert= totvert;
326         me->totedge= totedge;
327         
328         me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
329         me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
330         me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
331         
332         mvert= me->mvert;
333         medge= me->medge;
334
335         /* copy coordinates */
336         cache= psys->pathcache;
337         for(a=0; a<totpart; a++) {
338                 key= cache[a];
339                 kmax= key->steps;
340                 for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
341                         VECCOPY(mvert->co,key->co);
342                         if(k) {
343                                 medge->v1= cvert-1;
344                                 medge->v2= cvert;
345                                 medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
346                                 medge++;
347                         }
348                         else {
349                                 /* cheap trick to select the roots */
350                                 mvert->flag |= SELECT;
351                         }
352                 }
353         }
354
355         cache=psys->childcache;
356         for(a=0; a<totchild; a++) {
357                 key=cache[a];
358                 kmax=key->steps;
359                 for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
360                         VECCOPY(mvert->co,key->co);
361                         if(k) {
362                                 medge->v1=cvert-1;
363                                 medge->v2=cvert;
364                                 medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
365                                 medge++;
366                         }
367                         else {
368                                 /* cheap trick to select the roots */
369                                 mvert->flag |= SELECT;
370                         }
371                 }
372         }
373
374         DAG_scene_sort(bmain, scene);
375
376         return 1;
377 }
378
379 static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
380 {
381         /*
382           It should be ridiculously easy to extract the original verts that we want
383           and form the shape data.  We can probably use the CD KEYINDEX layer (or
384           whatever I ended up calling it, too tired to check now), though this would
385           by necassity have to make some potentially ugly assumptions about the order
386           of the mesh data :-/  you can probably assume in 99% of cases that the first
387           element of a given index is the original, and any subsequent duplicates are
388           copies/interpolates, but that's an assumption that would need to be tested
389           and then predominantly stated in comments in a half dozen headers.
390         */
391
392         if (ob->type==OB_MESH) {
393                 DerivedMesh *dm;
394                 Mesh *me= ob->data;
395                 Key *key=me->key;
396                 KeyBlock *kb;
397                 
398                 if(!modifier_sameTopology(md)) {
399                         BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to Shapes");
400                         return 0;
401                 }
402                 mesh_pmv_off(me);
403                 
404                 dm = mesh_create_derived_for_modifier(scene, ob, md);
405                 if (!dm) {
406                         BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
407                         return 0;
408                 }
409                 
410                 if(key == NULL) {
411                         key= me->key= add_key((ID *)me);
412                         key->type= KEY_RELATIVE;
413                         /* if that was the first key block added, then it was the basis.
414                          * Initialise it with the mesh, and add another for the modifier */
415                         kb= add_keyblock(key, NULL);
416                         mesh_to_key(me, kb);
417                 }
418
419                 kb= add_keyblock(key, md->name);
420                 DM_to_meshkey(dm, me, kb);
421                 
422                 dm->release(dm);
423         }
424         else {
425                 BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
426                 return 0;
427         }
428         return 1;
429 }
430
431 static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
432 {
433         ModifierTypeInfo *mti= modifierType_getInfo(md->type);
434
435         if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md, 0))) {
436                 BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
437                 return 0;
438         }
439
440         if (ob->type==OB_MESH) {
441                 DerivedMesh *dm;
442                 Mesh *me = ob->data;
443                 MultiresModifierData *mmd= find_multires_modifier_before(scene, md);
444
445                 if( me->key) {
446                         BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to Mesh with Shape Keys");
447                         return 0;
448                 }
449
450                 mesh_pmv_off(me);
451
452                 /* Multires: ensure that recent sculpting is applied */
453                 if(md->type == eModifierType_Multires)
454                         multires_force_update(ob);
455
456                 if (mmd && mmd->totlvl && mti->type==eModifierTypeType_OnlyDeform) {
457                         if(!multiresModifier_reshapeFromDeformMod (scene, mmd, ob, md)) {
458                                 BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
459                                 return 0;
460                         }
461                 } else {
462                         dm = mesh_create_derived_for_modifier(scene, ob, md);
463                         if (!dm) {
464                                 BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
465                                 return 0;
466                         }
467
468                         DM_to_mesh(dm, me);
469
470                         dm->release(dm);
471
472                         if(md->type == eModifierType_Multires) {
473                                 CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
474                                 CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
475                         }
476                 }
477         } 
478         else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
479                 Curve *cu;
480                 int numVerts;
481                 float (*vertexCos)[3];
482
483                 if (mti->type==eModifierTypeType_Constructive) {
484                         BKE_report(reports, RPT_ERROR, "Cannot apply constructive modifiers on curve");
485                         return 0;
486                 }
487
488                 cu = ob->data;
489                 BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tesselated/bevel vertices");
490
491                 vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts);
492                 mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0, 0);
493                 curve_applyVertexCos(cu, &cu->nurb, vertexCos);
494
495                 MEM_freeN(vertexCos);
496
497                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
498         }
499         else {
500                 BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
501                 return 0;
502         }
503
504         /* lattice modifier can be applied to particle system too */
505         if(ob->particlesystem.first) {
506
507                 ParticleSystem *psys = ob->particlesystem.first;
508
509                 for(; psys; psys=psys->next) {
510                         
511                         if(psys->part->type != PART_HAIR)
512                                 continue;
513
514                         psys_apply_hair_lattice(scene, ob, psys);
515                 }
516         }
517
518         return 1;
519 }
520
521 int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, ModifierData *md, int mode)
522 {
523         if (scene->obedit) {
524                 BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in editmode");
525                 return 0;
526         } else if (((ID*) ob->data)->us>1) {
527                 BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
528                 return 0;
529         }
530
531         if (md!=ob->modifiers.first)
532                 BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected.");
533
534         if (mode == MODIFIER_APPLY_SHAPE) {
535                 if (!modifier_apply_shape(reports, scene, ob, md))
536                         return 0;
537         } else {
538                 if (!modifier_apply_obdata(reports, scene, ob, md))
539                         return 0;
540         }
541
542         BLI_remlink(&ob->modifiers, md);
543         modifier_free(md);
544
545         return 1;
546 }
547
548 int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierData *md)
549 {
550         ModifierData *nmd;
551         
552         nmd = modifier_new(md->type);
553         modifier_copyData(md, nmd);
554         BLI_insertlink(&ob->modifiers, md, nmd);
555         modifier_unique_name(&ob->modifiers, nmd);
556
557         return 1;
558 }
559
560 /************************ add modifier operator *********************/
561
562 static int modifier_add_exec(bContext *C, wmOperator *op)
563 {
564         Main *bmain= CTX_data_main(C);
565         Scene *scene= CTX_data_scene(C);
566         Object *ob = ED_object_active_context(C);
567         int type= RNA_enum_get(op->ptr, "type");
568
569         if(!ED_object_modifier_add(op->reports, bmain, scene, ob, NULL, type))
570                 return OPERATOR_CANCELLED;
571
572         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
573         
574         return OPERATOR_FINISHED;
575 }
576
577 static EnumPropertyItem *modifier_add_itemf(bContext *C, PointerRNA *UNUSED(ptr), int *free)
578 {       
579         Object *ob= ED_object_active_context(C);
580         EnumPropertyItem *item= NULL, *md_item;
581         ModifierTypeInfo *mti;
582         int totitem= 0, a;
583         
584         if(!ob)
585                 return modifier_type_items;
586
587         for(a=0; modifier_type_items[a].identifier; a++) {
588                 md_item= &modifier_type_items[a];
589
590                 if(md_item->identifier[0]) {
591                         mti= modifierType_getInfo(md_item->value);
592
593                         if(mti->flags & eModifierTypeFlag_NoUserAdd)
594                                 continue;
595
596                         if(!((mti->flags & eModifierTypeFlag_AcceptsCVs) ||
597                            (ob->type==OB_MESH && (mti->flags & eModifierTypeFlag_AcceptsMesh))))
598                                 continue;
599                 }
600
601                 RNA_enum_item_add(&item, &totitem, md_item);
602         }
603
604         RNA_enum_item_end(&item, &totitem);
605         *free= 1;
606
607         return item;
608 }
609
610 void OBJECT_OT_modifier_add(wmOperatorType *ot)
611 {
612         PropertyRNA *prop;
613
614         /* identifiers */
615         ot->name= "Add Modifier";
616         ot->description = "Add a modifier to the active object";
617         ot->idname= "OBJECT_OT_modifier_add";
618         
619         /* api callbacks */
620         ot->invoke= WM_menu_invoke;
621         ot->exec= modifier_add_exec;
622         ot->poll= ED_operator_object_active_editable;
623         
624         /* flags */
625         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
626         
627         /* properties */
628         prop= RNA_def_enum(ot->srna, "type", modifier_type_items, eModifierType_Subsurf, "Type", "");
629         RNA_def_enum_funcs(prop, modifier_add_itemf);
630         ot->prop= prop;
631 }
632
633 /************************ generic functions for operators using mod names and data context *********************/
634
635 static int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
636 {
637         PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", rna_type);
638         Object *ob= (ptr.id.data)?ptr.id.data:ED_object_active_context(C);
639         
640         if (!ob || ob->id.lib) return 0;
641         if (obtype_flag && ((1<<ob->type) & obtype_flag)==0) return 0;
642         if (ptr.id.data && ((ID*)ptr.id.data)->lib) return 0;
643         
644         return 1;
645 }
646
647 static int edit_modifier_poll(bContext *C)
648 {
649         return edit_modifier_poll_generic(C, &RNA_Modifier, 0);
650 }
651
652 static void edit_modifier_properties(wmOperatorType *ot)
653 {
654         RNA_def_string(ot->srna, "modifier", "", 32, "Modifier", "Name of the modifier to edit");
655 }
656
657 static int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
658 {
659         PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
660         ModifierData *md;
661         
662         if (RNA_property_is_set(op->ptr, "modifier"))
663                 return 1;
664         
665         if (ptr.data) {
666                 md = ptr.data;
667                 RNA_string_set(op->ptr, "modifier", md->name);
668                 return 1;
669         }
670         
671         return 0;
672 }
673
674 static ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
675 {
676         char modifier_name[32];
677         ModifierData *md;
678         RNA_string_get(op->ptr, "modifier", modifier_name);
679         
680         md = modifiers_findByName(ob, modifier_name);
681         
682         if (md && type != 0 && md->type != type)
683                 md = NULL;
684
685         return md;
686 }
687
688 /************************ remove modifier operator *********************/
689
690 static int modifier_remove_exec(bContext *C, wmOperator *op)
691 {
692         Main *bmain= CTX_data_main(C);
693         Scene *scene= CTX_data_scene(C);
694         Object *ob = ED_object_active_context(C);
695         ModifierData *md = edit_modifier_property_get(op, ob, 0);
696         int mode_orig = ob->mode;
697         
698         if(!ob || !md || !ED_object_modifier_remove(op->reports, bmain, scene, ob, md))
699                 return OPERATOR_CANCELLED;
700
701         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
702
703         /* if cloth/softbody was removed, particle mode could be cleared */
704         if(mode_orig & OB_MODE_PARTICLE_EDIT)
705                 if((ob->mode & OB_MODE_PARTICLE_EDIT)==0)
706                         if(scene->basact && scene->basact->object==ob)
707                                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
708         
709         return OPERATOR_FINISHED;
710 }
711
712 static int modifier_remove_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
713 {
714         if (edit_modifier_invoke_properties(C, op))
715                 return modifier_remove_exec(C, op);
716         else
717                 return OPERATOR_CANCELLED;
718 }
719
720 void OBJECT_OT_modifier_remove(wmOperatorType *ot)
721 {
722         ot->name= "Remove Modifier";
723         ot->description= "Remove a modifier from the active object";
724         ot->idname= "OBJECT_OT_modifier_remove";
725
726         ot->invoke= modifier_remove_invoke;
727         ot->exec= modifier_remove_exec;
728         ot->poll= edit_modifier_poll;
729         
730         /* flags */
731         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
732         edit_modifier_properties(ot);
733 }
734
735 /************************ move up modifier operator *********************/
736
737 static int modifier_move_up_exec(bContext *C, wmOperator *op)
738 {
739         Object *ob = ED_object_active_context(C);
740         ModifierData *md = edit_modifier_property_get(op, ob, 0);
741
742         if(!ob || !md || !ED_object_modifier_move_up(op->reports, ob, md))
743                 return OPERATOR_CANCELLED;
744
745         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
746         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
747         
748         return OPERATOR_FINISHED;
749 }
750
751 static int modifier_move_up_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
752 {
753         if (edit_modifier_invoke_properties(C, op))
754                 return modifier_move_up_exec(C, op);
755         else
756                 return OPERATOR_CANCELLED;
757 }
758
759 void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
760 {
761         ot->name= "Move Up Modifier";
762         ot->description= "Move modifier up in the stack";
763         ot->idname= "OBJECT_OT_modifier_move_up";
764
765         ot->invoke= modifier_move_up_invoke;
766         ot->exec= modifier_move_up_exec;
767         ot->poll= edit_modifier_poll;
768         
769         /* flags */
770         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
771         edit_modifier_properties(ot);
772 }
773
774 /************************ move down modifier operator *********************/
775
776 static int modifier_move_down_exec(bContext *C, wmOperator *op)
777 {
778         Object *ob = ED_object_active_context(C);
779         ModifierData *md = edit_modifier_property_get(op, ob, 0);
780
781         if(!ob || !md || !ED_object_modifier_move_down(op->reports, ob, md))
782                 return OPERATOR_CANCELLED;
783
784         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
785         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
786         
787         return OPERATOR_FINISHED;
788 }
789
790 static int modifier_move_down_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
791 {
792         if (edit_modifier_invoke_properties(C, op))
793                 return modifier_move_down_exec(C, op);
794         else
795                 return OPERATOR_CANCELLED;
796 }
797
798 void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
799 {
800         ot->name= "Move Down Modifier";
801         ot->description= "Move modifier down in the stack";
802         ot->idname= "OBJECT_OT_modifier_move_down";
803
804         ot->invoke= modifier_move_down_invoke;
805         ot->exec= modifier_move_down_exec;
806         ot->poll= edit_modifier_poll;
807         
808         /* flags */
809         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
810         edit_modifier_properties(ot);
811 }
812
813 /************************ apply modifier operator *********************/
814
815 static int modifier_apply_exec(bContext *C, wmOperator *op)
816 {
817         Scene *scene= CTX_data_scene(C);
818         Object *ob = ED_object_active_context(C);
819         ModifierData *md = edit_modifier_property_get(op, ob, 0);
820         int apply_as= RNA_enum_get(op->ptr, "apply_as");
821         
822         if(!ob || !md || !ED_object_modifier_apply(op->reports, scene, ob, md, apply_as)) {
823                 return OPERATOR_CANCELLED;
824         }
825
826         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
827         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
828         
829         return OPERATOR_FINISHED;
830 }
831
832 static int modifier_apply_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
833 {
834         if (edit_modifier_invoke_properties(C, op))
835                 return modifier_apply_exec(C, op);
836         else
837                 return OPERATOR_CANCELLED;
838 }
839
840 static EnumPropertyItem modifier_apply_as_items[] = {
841         {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
842         {MODIFIER_APPLY_SHAPE, "SHAPE", 0, "New Shape", "Apply deform-only modifier to a new shape on this object"},
843         {0, NULL, 0, NULL, NULL}};
844
845 void OBJECT_OT_modifier_apply(wmOperatorType *ot)
846 {
847         ot->name= "Apply Modifier";
848         ot->description= "Apply modifier and remove from the stack";
849         ot->idname= "OBJECT_OT_modifier_apply";
850
851         ot->invoke= modifier_apply_invoke;
852         ot->exec= modifier_apply_exec;
853         ot->poll= edit_modifier_poll;
854         
855         /* flags */
856         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
857         
858         RNA_def_enum(ot->srna, "apply_as", modifier_apply_as_items, MODIFIER_APPLY_DATA, "Apply as", "How to apply the modifier to the geometry");
859         edit_modifier_properties(ot);
860 }
861
862 /************************ convert modifier operator *********************/
863
864 static int modifier_convert_exec(bContext *C, wmOperator *op)
865 {
866         Main *bmain= CTX_data_main(C);
867         Scene *scene= CTX_data_scene(C);
868         Object *ob = ED_object_active_context(C);
869         ModifierData *md = edit_modifier_property_get(op, ob, 0);
870         
871         if(!ob || !md || !ED_object_modifier_convert(op->reports, bmain, scene, ob, md))
872                 return OPERATOR_CANCELLED;
873
874         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
875         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
876         
877         return OPERATOR_FINISHED;
878 }
879
880 static int modifier_convert_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
881 {
882         if (edit_modifier_invoke_properties(C, op))
883                 return modifier_convert_exec(C, op);
884         else
885                 return OPERATOR_CANCELLED;
886 }
887
888 void OBJECT_OT_modifier_convert(wmOperatorType *ot)
889 {
890         ot->name= "Convert Modifier";
891         ot->description= "Convert particles to a mesh object";
892         ot->idname= "OBJECT_OT_modifier_convert";
893
894         ot->invoke= modifier_convert_invoke;
895         ot->exec= modifier_convert_exec;
896         ot->poll= edit_modifier_poll;
897         
898         /* flags */
899         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
900         edit_modifier_properties(ot);
901 }
902
903 /************************ copy modifier operator *********************/
904
905 static int modifier_copy_exec(bContext *C, wmOperator *op)
906 {
907         Object *ob = ED_object_active_context(C);
908         ModifierData *md = edit_modifier_property_get(op, ob, 0);
909
910         if(!ob || !md || !ED_object_modifier_copy(op->reports, ob, md))
911                 return OPERATOR_CANCELLED;
912
913         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
914         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
915         
916         return OPERATOR_FINISHED;
917 }
918
919 static int modifier_copy_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
920 {
921         if (edit_modifier_invoke_properties(C, op))
922                 return modifier_copy_exec(C, op);
923         else
924                 return OPERATOR_CANCELLED;
925 }
926
927 void OBJECT_OT_modifier_copy(wmOperatorType *ot)
928 {
929         ot->name= "Copy Modifier";
930         ot->description= "Duplicate modifier at the same position in the stack";
931         ot->idname= "OBJECT_OT_modifier_copy";
932
933         ot->invoke= modifier_copy_invoke;
934         ot->exec= modifier_copy_exec;
935         ot->poll= edit_modifier_poll;
936         
937         /* flags */
938         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
939         edit_modifier_properties(ot);
940 }
941
942 /************* multires delete higher levels operator ****************/
943
944 static int multires_poll(bContext *C)
945 {
946         return edit_modifier_poll_generic(C, &RNA_MultiresModifier, (1<<OB_MESH));
947 }
948
949 static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op)
950 {
951         Object *ob = ED_object_active_context(C);
952         MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
953         
954         if (!mmd)
955                 return OPERATOR_CANCELLED;
956         
957         multiresModifier_del_levels(mmd, ob, 1);
958         
959         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
960         
961         return OPERATOR_FINISHED;
962 }
963
964 static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
965 {
966         if (edit_modifier_invoke_properties(C, op))
967                 return multires_higher_levels_delete_exec(C, op);
968         else
969                 return OPERATOR_CANCELLED;
970 }
971
972 void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
973 {
974         ot->name= "Delete Higher Levels";
975         ot->idname= "OBJECT_OT_multires_higher_levels_delete";
976
977         ot->poll= multires_poll;
978         ot->invoke= multires_higher_levels_delete_invoke;
979         ot->exec= multires_higher_levels_delete_exec;
980         
981         /* flags */
982         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
983         edit_modifier_properties(ot);
984 }
985
986 /****************** multires subdivide operator *********************/
987
988 static int multires_subdivide_exec(bContext *C, wmOperator *op)
989 {
990         Object *ob = ED_object_active_context(C);
991         MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
992         
993         if (!mmd)
994                 return OPERATOR_CANCELLED;
995         
996         multiresModifier_subdivide(mmd, ob, 0, mmd->simple);
997
998         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
999         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1000         
1001         return OPERATOR_FINISHED;
1002 }
1003
1004 static int multires_subdivide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1005 {
1006         if (edit_modifier_invoke_properties(C, op))
1007                 return multires_subdivide_exec(C, op);
1008         else
1009                 return OPERATOR_CANCELLED;
1010 }
1011
1012 void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
1013 {
1014         ot->name= "Multires Subdivide";
1015         ot->description= "Add a new level of subdivision";
1016         ot->idname= "OBJECT_OT_multires_subdivide";
1017
1018         ot->poll= multires_poll;
1019         ot->invoke= multires_subdivide_invoke;
1020         ot->exec= multires_subdivide_exec;
1021         
1022         /* flags */
1023         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1024         edit_modifier_properties(ot);
1025 }
1026
1027 /****************** multires reshape operator *********************/
1028
1029 static int multires_reshape_exec(bContext *C, wmOperator *op)
1030 {
1031         Object *ob= ED_object_active_context(C), *secondob= NULL;
1032         Scene *scene= CTX_data_scene(C);
1033         MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1034
1035         if (!mmd)
1036                 return OPERATOR_CANCELLED;
1037         
1038         CTX_DATA_BEGIN(C, Object*, selob, selected_editable_objects) {
1039                 if(selob->type == OB_MESH && selob != ob) {
1040                         secondob= selob;
1041                         break;
1042                 }
1043         }
1044         CTX_DATA_END;
1045
1046         if(!secondob) {
1047                 BKE_report(op->reports, RPT_ERROR, "Second selected mesh object require to copy shape from.");
1048                 return OPERATOR_CANCELLED;
1049         }
1050
1051         if(!multiresModifier_reshape(scene, mmd, ob, secondob)) {
1052                 BKE_report(op->reports, RPT_ERROR, "Objects do not have the same number of vertices.");
1053                 return OPERATOR_CANCELLED;
1054         }
1055
1056         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1057         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1058
1059         return OPERATOR_FINISHED;
1060 }
1061
1062 static int multires_reshape_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1063 {
1064         if (edit_modifier_invoke_properties(C, op))
1065                 return multires_reshape_exec(C, op);
1066         else
1067                 return OPERATOR_CANCELLED;
1068 }
1069
1070 void OBJECT_OT_multires_reshape(wmOperatorType *ot)
1071 {
1072         ot->name= "Multires Reshape";
1073         ot->description= "Copy vertex coordinates from other object";
1074         ot->idname= "OBJECT_OT_multires_reshape";
1075
1076         ot->poll= multires_poll;
1077         ot->invoke= multires_reshape_invoke;
1078         ot->exec= multires_reshape_exec;
1079         
1080         /* flags */
1081         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1082         edit_modifier_properties(ot);
1083 }
1084
1085 /****************** multires save external operator *********************/
1086
1087 static int multires_external_save_exec(bContext *C, wmOperator *op)
1088 {
1089         Object *ob = ED_object_active_context(C);
1090         Mesh *me= (ob)? ob->data: op->customdata;
1091         char path[FILE_MAX];
1092         int relative= RNA_boolean_get(op->ptr, "relative_path");
1093
1094         if(!me)
1095                 return OPERATOR_CANCELLED;
1096
1097         if(CustomData_external_test(&me->fdata, CD_MDISPS))
1098                 return OPERATOR_CANCELLED;
1099         
1100         RNA_string_get(op->ptr, "filepath", path);
1101
1102         if(relative)
1103                 BLI_path_rel(path, G.main->name);
1104
1105         CustomData_external_add(&me->fdata, &me->id, CD_MDISPS, me->totface, path);
1106         CustomData_external_write(&me->fdata, &me->id, CD_MASK_MESH, me->totface, 0);
1107         
1108         return OPERATOR_FINISHED;
1109 }
1110
1111 static int multires_external_save_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1112 {
1113         Object *ob = ED_object_active_context(C);
1114         MultiresModifierData *mmd;
1115         Mesh *me= ob->data;
1116         char path[FILE_MAX];
1117
1118         if (!edit_modifier_invoke_properties(C, op))
1119                 return OPERATOR_CANCELLED;
1120         
1121         mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1122         
1123         if (!mmd)
1124                 return OPERATOR_CANCELLED;
1125         
1126         if(CustomData_external_test(&me->fdata, CD_MDISPS))
1127                 return OPERATOR_CANCELLED;
1128
1129         if(!RNA_property_is_set(op->ptr, "relative_path"))
1130                 RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS);
1131
1132         if(RNA_property_is_set(op->ptr, "filepath"))
1133                 return multires_external_save_exec(C, op);
1134         
1135         op->customdata= me;
1136
1137         BLI_snprintf(path, sizeof(path), "//%s.btx", me->id.name+2);
1138         RNA_string_set(op->ptr, "filepath", path);
1139         
1140         WM_event_add_fileselect(C, op);
1141
1142         return OPERATOR_RUNNING_MODAL;
1143 }
1144
1145 void OBJECT_OT_multires_external_save(wmOperatorType *ot)
1146 {
1147         ot->name= "Multires Save External";
1148         ot->description= "Save displacements to an external file";
1149         ot->idname= "OBJECT_OT_multires_external_save";
1150
1151         // XXX modifier no longer in context after file browser .. ot->poll= multires_poll;
1152         ot->exec= multires_external_save_exec;
1153         ot->invoke= multires_external_save_invoke;
1154         ot->poll= multires_poll;
1155         
1156         /* flags */
1157         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1158
1159         WM_operator_properties_filesel(ot, FOLDERFILE|BTXFILE, FILE_SPECIAL, FILE_SAVE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH);
1160         edit_modifier_properties(ot);
1161 }
1162
1163 /****************** multires pack operator *********************/
1164
1165 static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op))
1166 {
1167         Object *ob = ED_object_active_context(C);
1168         Mesh *me= ob->data;
1169
1170         if(!CustomData_external_test(&me->fdata, CD_MDISPS))
1171                 return OPERATOR_CANCELLED;
1172
1173         // XXX don't remove..
1174         CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
1175         
1176         return OPERATOR_FINISHED;
1177 }
1178
1179 void OBJECT_OT_multires_external_pack(wmOperatorType *ot)
1180 {
1181         ot->name= "Multires Pack External";
1182         ot->description= "Pack displacements from an external file";
1183         ot->idname= "OBJECT_OT_multires_external_pack";
1184
1185         ot->poll= multires_poll;
1186         ot->exec= multires_external_pack_exec;
1187         
1188         /* flags */
1189         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1190 }
1191
1192 /********************* multires apply base ***********************/
1193 static int multires_base_apply_exec(bContext *C, wmOperator *op)
1194 {
1195         Object *ob = ED_object_active_context(C);
1196         MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1197         
1198         if (!mmd)
1199                 return OPERATOR_CANCELLED;
1200         
1201         multiresModifier_base_apply(mmd, ob);
1202
1203         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1204         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1205         
1206         return OPERATOR_FINISHED;
1207 }
1208
1209 static int multires_base_apply_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1210 {
1211         if (edit_modifier_invoke_properties(C, op))
1212                 return multires_base_apply_exec(C, op);
1213         else
1214                 return OPERATOR_CANCELLED;
1215 }
1216
1217
1218 void OBJECT_OT_multires_base_apply(wmOperatorType *ot)
1219 {
1220         ot->name= "Multires Apply Base";
1221         ot->description= "Modify the base mesh to conform to the displaced mesh";
1222         ot->idname= "OBJECT_OT_multires_base_apply";
1223
1224         ot->poll= multires_poll;
1225         ot->invoke= multires_base_apply_invoke;
1226         ot->exec= multires_base_apply_exec;
1227         
1228         /* flags */
1229         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1230         edit_modifier_properties(ot);
1231 }
1232
1233
1234 /************************ mdef bind operator *********************/
1235
1236 static int meshdeform_poll(bContext *C)
1237 {
1238         return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, (1<<OB_MESH));
1239 }
1240
1241 static int meshdeform_bind_exec(bContext *C, wmOperator *op)
1242 {
1243         Scene *scene= CTX_data_scene(C);
1244         Object *ob = ED_object_active_context(C);
1245         MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_MeshDeform);
1246         
1247         if (!mmd)
1248                 return OPERATOR_CANCELLED;
1249
1250         if(mmd->bindcagecos) {
1251                 if(mmd->bindweights) MEM_freeN(mmd->bindweights);
1252                 if(mmd->bindcagecos) MEM_freeN(mmd->bindcagecos);
1253                 if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
1254                 if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
1255                 if(mmd->dynverts) MEM_freeN(mmd->dynverts);
1256                 mmd->bindweights= NULL;
1257                 mmd->bindcagecos= NULL;
1258                 mmd->dyngrid= NULL;
1259                 mmd->dyninfluences= NULL;
1260                 mmd->dynverts= NULL;
1261                 mmd->totvert= 0;
1262                 mmd->totcagevert= 0;
1263                 mmd->totinfluence= 0;
1264                 
1265                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1266                 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1267         }
1268         else {
1269                 DerivedMesh *dm;
1270                 int mode= mmd->modifier.mode;
1271
1272                 /* force modifier to run, it will call binding routine */
1273                 mmd->bindfunc= mesh_deform_bind;
1274                 mmd->modifier.mode |= eModifierMode_Realtime;
1275
1276                 if(ob->type == OB_MESH) {
1277                         dm= mesh_create_derived_view(scene, ob, 0);
1278                         dm->release(dm);
1279                 }
1280                 else if(ob->type == OB_LATTICE) {
1281                         lattice_calc_modifiers(scene, ob);
1282                 }
1283                 else if(ob->type==OB_MBALL) {
1284                         makeDispListMBall(scene, ob);
1285                 }
1286                 else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1287                         makeDispListCurveTypes(scene, ob, 0);
1288                 }
1289
1290                 mmd->bindfunc= NULL;
1291                 mmd->modifier.mode= mode;
1292         }
1293         
1294         return OPERATOR_FINISHED;
1295 }
1296
1297 static int meshdeform_bind_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1298 {
1299         if (edit_modifier_invoke_properties(C, op))
1300                 return meshdeform_bind_exec(C, op);
1301         else 
1302                 return OPERATOR_CANCELLED;
1303 }
1304
1305 void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
1306 {
1307         /* identifiers */
1308         ot->name= "Mesh Deform Bind";
1309         ot->description = "Bind mesh to cage in mesh deform modifier";
1310         ot->idname= "OBJECT_OT_meshdeform_bind";
1311         
1312         /* api callbacks */
1313         ot->poll= meshdeform_poll;
1314         ot->invoke= meshdeform_bind_invoke;
1315         ot->exec= meshdeform_bind_exec;
1316         
1317         /* flags */
1318         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1319         edit_modifier_properties(ot);
1320 }
1321
1322 /****************** explode refresh operator *********************/
1323
1324 static int explode_poll(bContext *C)
1325 {
1326         return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0);
1327 }
1328
1329 static int explode_refresh_exec(bContext *C, wmOperator *op)
1330 {
1331         Object *ob = ED_object_active_context(C);
1332         ExplodeModifierData *emd = (ExplodeModifierData *)edit_modifier_property_get(op, ob, eModifierType_Explode);
1333         
1334         if (!emd)
1335                 return OPERATOR_CANCELLED;
1336
1337         emd->flag |= eExplodeFlag_CalcFaces;
1338
1339         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1340         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1341         
1342         return OPERATOR_FINISHED;
1343 }
1344
1345 static int explode_refresh_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1346 {
1347         if (edit_modifier_invoke_properties(C, op))
1348                 return explode_refresh_exec(C, op);
1349         else
1350                 return OPERATOR_CANCELLED;
1351 }
1352
1353
1354 void OBJECT_OT_explode_refresh(wmOperatorType *ot)
1355 {
1356         ot->name= "Explode Refresh";
1357         ot->description= "Refresh data in the Explode modifier";
1358         ot->idname= "OBJECT_OT_explode_refresh";
1359
1360         ot->poll= explode_poll;
1361         ot->invoke= explode_refresh_invoke;
1362         ot->exec= explode_refresh_exec;
1363         
1364         /* flags */
1365         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1366         edit_modifier_properties(ot);
1367 }
1368