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