svn merge -r36900:37028 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         /*
404           It should be ridiculously easy to extract the original verts that we want
405           and form the shape data.  We can probably use the CD KEYINDEX layer (or
406           whatever I ended up calling it, too tired to check now), though this would
407           by necassity have to make some potentially ugly assumptions about the order
408           of the mesh data :-/  you can probably assume in 99% of cases that the first
409           element of a given index is the original, and any subsequent duplicates are
410           copies/interpolates, but that's an assumption that would need to be tested
411           and then predominantly stated in comments in a half dozen headers.
412         */
413
414         if (ob->type==OB_MESH) {
415                 DerivedMesh *dm;
416                 Mesh *me= ob->data;
417                 Key *key=me->key;
418                 KeyBlock *kb;
419                 
420                 if(!modifier_sameTopology(md)) {
421                         BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to Shapes");
422                         return 0;
423                 }
424                 mesh_pmv_off(me);
425                 
426                 dm = mesh_create_derived_for_modifier(scene, ob, md, 0);
427                 if (!dm) {
428                         BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
429                         return 0;
430                 }
431                 
432                 if(key == NULL) {
433                         key= me->key= add_key((ID *)me);
434                         key->type= KEY_RELATIVE;
435                         /* if that was the first key block added, then it was the basis.
436                          * Initialise it with the mesh, and add another for the modifier */
437                         kb= add_keyblock(key, NULL);
438                         mesh_to_key(me, kb);
439                 }
440
441                 kb= add_keyblock(key, md->name);
442                 DM_to_meshkey(dm, me, kb);
443                 
444                 dm->release(dm);
445         }
446         else {
447                 BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
448                 return 0;
449         }
450         return 1;
451 }
452
453 static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
454 {
455         ModifierTypeInfo *mti= modifierType_getInfo(md->type);
456
457         if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md, 0))) {
458                 BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
459                 return 0;
460         }
461
462         if (ob->type==OB_MESH) {
463                 DerivedMesh *dm;
464                 Mesh *me = ob->data;
465                 MultiresModifierData *mmd= find_multires_modifier_before(scene, md);
466                 
467                 mesh_pmv_off(me);
468
469                 /* Multires: ensure that recent sculpting is applied */
470                 if(md->type == eModifierType_Multires)
471                         multires_force_update(ob);
472
473                 if (mmd && mmd->totlvl && mti->type==eModifierTypeType_OnlyDeform) {
474                         if(!multiresModifier_reshapeFromDeformMod (scene, mmd, ob, md)) {
475                                 BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
476                                 return 0;
477                         }
478                 } else {
479                         dm = mesh_create_derived_for_modifier(scene, ob, md, 1);
480                         if (!dm) {
481                                 BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
482                                 return 0;
483                         }
484
485                         DM_to_mesh(dm, me, ob);
486
487                         dm->release(dm);
488
489                         if(md->type == eModifierType_Multires) {
490                                 CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
491                                 CustomData_free_layer_active(&me->ldata, CD_MDISPS, me->totloop);
492                         }
493                 }
494         } 
495         else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
496                 Curve *cu;
497                 int numVerts;
498                 float (*vertexCos)[3];
499
500                 if (mti->type==eModifierTypeType_Constructive) {
501                         BKE_report(reports, RPT_ERROR, "Cannot apply constructive modifiers on curve");
502                         return 0;
503                 }
504
505                 cu = ob->data;
506                 BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tesselated/bevel vertices");
507
508                 vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts);
509                 mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0, 0);
510                 curve_applyVertexCos(cu, &cu->nurb, vertexCos);
511
512                 MEM_freeN(vertexCos);
513
514                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
515         }
516         else {
517                 BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
518                 return 0;
519         }
520
521         /* lattice modifier can be applied to particle system too */
522         if(ob->particlesystem.first) {
523
524                 ParticleSystem *psys = ob->particlesystem.first;
525
526                 for(; psys; psys=psys->next) {
527                         
528                         if(psys->part->type != PART_HAIR)
529                                 continue;
530
531                         psys_apply_hair_lattice(scene, ob, psys);
532                 }
533         }
534
535         return 1;
536 }
537
538 int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, ModifierData *md, int mode)
539 {
540         if (scene->obedit) {
541                 BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in editmode");
542                 return 0;
543         } else if (((ID*) ob->data)->us>1) {
544                 BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
545                 return 0;
546         }
547
548         if (md!=ob->modifiers.first)
549                 BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected.");
550
551         if (mode == MODIFIER_APPLY_SHAPE) {
552                 if (!modifier_apply_shape(reports, scene, ob, md))
553                         return 0;
554         } else {
555                 if (!modifier_apply_obdata(reports, scene, ob, md))
556                         return 0;
557         }
558
559         BLI_remlink(&ob->modifiers, md);
560         modifier_free(md);
561
562         return 1;
563 }
564
565 int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierData *md)
566 {
567         ModifierData *nmd;
568         
569         nmd = modifier_new(md->type);
570         modifier_copyData(md, nmd);
571         BLI_insertlink(&ob->modifiers, md, nmd);
572         modifier_unique_name(&ob->modifiers, nmd);
573
574         return 1;
575 }
576
577 /************************ add modifier operator *********************/
578
579 static int modifier_add_exec(bContext *C, wmOperator *op)
580 {
581         Main *bmain= CTX_data_main(C);
582         Scene *scene= CTX_data_scene(C);
583         Object *ob = ED_object_active_context(C);
584         int type= RNA_enum_get(op->ptr, "type");
585
586         if(!ED_object_modifier_add(op->reports, bmain, scene, ob, NULL, type))
587                 return OPERATOR_CANCELLED;
588
589         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
590         
591         return OPERATOR_FINISHED;
592 }
593
594 static EnumPropertyItem *modifier_add_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
595 {       
596         Object *ob= ED_object_active_context(C);
597         EnumPropertyItem *item= NULL, *md_item;
598         ModifierTypeInfo *mti;
599         int totitem= 0, a;
600         
601         if(!ob)
602                 return modifier_type_items;
603
604         for(a=0; modifier_type_items[a].identifier; a++) {
605                 md_item= &modifier_type_items[a];
606
607                 if(md_item->identifier[0]) {
608                         mti= modifierType_getInfo(md_item->value);
609
610                         if(mti->flags & eModifierTypeFlag_NoUserAdd)
611                                 continue;
612
613                         if(!((mti->flags & eModifierTypeFlag_AcceptsCVs) ||
614                            (ob->type==OB_MESH && (mti->flags & eModifierTypeFlag_AcceptsMesh))))
615                                 continue;
616                 }
617
618                 RNA_enum_item_add(&item, &totitem, md_item);
619         }
620
621         RNA_enum_item_end(&item, &totitem);
622         *free= 1;
623
624         return item;
625 }
626
627 void OBJECT_OT_modifier_add(wmOperatorType *ot)
628 {
629         PropertyRNA *prop;
630
631         /* identifiers */
632         ot->name= "Add Modifier";
633         ot->description = "Add a modifier to the active object";
634         ot->idname= "OBJECT_OT_modifier_add";
635         
636         /* api callbacks */
637         ot->invoke= WM_menu_invoke;
638         ot->exec= modifier_add_exec;
639         ot->poll= ED_operator_object_active_editable;
640         
641         /* flags */
642         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
643         
644         /* properties */
645         prop= RNA_def_enum(ot->srna, "type", modifier_type_items, eModifierType_Subsurf, "Type", "");
646         RNA_def_enum_funcs(prop, modifier_add_itemf);
647         ot->prop= prop;
648 }
649
650 /************************ generic functions for operators using mod names and data context *********************/
651
652 static int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
653 {
654         PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", rna_type);
655         Object *ob= (ptr.id.data)?ptr.id.data:ED_object_active_context(C);
656         
657         if (!ob || ob->id.lib) return 0;
658         if (obtype_flag && ((1<<ob->type) & obtype_flag)==0) return 0;
659         if (ptr.id.data && ((ID*)ptr.id.data)->lib) return 0;
660         
661         return 1;
662 }
663
664 static int edit_modifier_poll(bContext *C)
665 {
666         return edit_modifier_poll_generic(C, &RNA_Modifier, 0);
667 }
668
669 static void edit_modifier_properties(wmOperatorType *ot)
670 {
671         RNA_def_string(ot->srna, "modifier", "", 32, "Modifier", "Name of the modifier to edit");
672 }
673
674 static int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
675 {
676         PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
677         ModifierData *md;
678         
679         if (RNA_property_is_set(op->ptr, "modifier"))
680                 return 1;
681         
682         if (ptr.data) {
683                 md = ptr.data;
684                 RNA_string_set(op->ptr, "modifier", md->name);
685                 return 1;
686         }
687         
688         return 0;
689 }
690
691 static ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
692 {
693         char modifier_name[32];
694         ModifierData *md;
695         RNA_string_get(op->ptr, "modifier", modifier_name);
696         
697         md = modifiers_findByName(ob, modifier_name);
698         
699         if (md && type != 0 && md->type != type)
700                 md = NULL;
701
702         return md;
703 }
704
705 /************************ remove modifier operator *********************/
706
707 static int modifier_remove_exec(bContext *C, wmOperator *op)
708 {
709         Main *bmain= CTX_data_main(C);
710         Scene *scene= CTX_data_scene(C);
711         Object *ob = ED_object_active_context(C);
712         ModifierData *md = edit_modifier_property_get(op, ob, 0);
713         int mode_orig = ob->mode;
714         
715         if(!ob || !md || !ED_object_modifier_remove(op->reports, bmain, scene, ob, md))
716                 return OPERATOR_CANCELLED;
717
718         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
719
720         /* if cloth/softbody was removed, particle mode could be cleared */
721         if(mode_orig & OB_MODE_PARTICLE_EDIT)
722                 if((ob->mode & OB_MODE_PARTICLE_EDIT)==0)
723                         if(scene->basact && scene->basact->object==ob)
724                                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
725         
726         return OPERATOR_FINISHED;
727 }
728
729 static int modifier_remove_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
730 {
731         if (edit_modifier_invoke_properties(C, op))
732                 return modifier_remove_exec(C, op);
733         else
734                 return OPERATOR_CANCELLED;
735 }
736
737 void OBJECT_OT_modifier_remove(wmOperatorType *ot)
738 {
739         ot->name= "Remove Modifier";
740         ot->description= "Remove a modifier from the active object";
741         ot->idname= "OBJECT_OT_modifier_remove";
742
743         ot->invoke= modifier_remove_invoke;
744         ot->exec= modifier_remove_exec;
745         ot->poll= edit_modifier_poll;
746         
747         /* flags */
748         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
749         edit_modifier_properties(ot);
750 }
751
752 /************************ move up modifier operator *********************/
753
754 static int modifier_move_up_exec(bContext *C, wmOperator *op)
755 {
756         Object *ob = ED_object_active_context(C);
757         ModifierData *md = edit_modifier_property_get(op, ob, 0);
758
759         if(!ob || !md || !ED_object_modifier_move_up(op->reports, ob, md))
760                 return OPERATOR_CANCELLED;
761
762         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
763         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
764         
765         return OPERATOR_FINISHED;
766 }
767
768 static int modifier_move_up_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
769 {
770         if (edit_modifier_invoke_properties(C, op))
771                 return modifier_move_up_exec(C, op);
772         else
773                 return OPERATOR_CANCELLED;
774 }
775
776 void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
777 {
778         ot->name= "Move Up Modifier";
779         ot->description= "Move modifier up in the stack";
780         ot->idname= "OBJECT_OT_modifier_move_up";
781
782         ot->invoke= modifier_move_up_invoke;
783         ot->exec= modifier_move_up_exec;
784         ot->poll= edit_modifier_poll;
785         
786         /* flags */
787         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
788         edit_modifier_properties(ot);
789 }
790
791 /************************ move down modifier operator *********************/
792
793 static int modifier_move_down_exec(bContext *C, wmOperator *op)
794 {
795         Object *ob = ED_object_active_context(C);
796         ModifierData *md = edit_modifier_property_get(op, ob, 0);
797
798         if(!ob || !md || !ED_object_modifier_move_down(op->reports, ob, md))
799                 return OPERATOR_CANCELLED;
800
801         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
802         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
803         
804         return OPERATOR_FINISHED;
805 }
806
807 static int modifier_move_down_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
808 {
809         if (edit_modifier_invoke_properties(C, op))
810                 return modifier_move_down_exec(C, op);
811         else
812                 return OPERATOR_CANCELLED;
813 }
814
815 void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
816 {
817         ot->name= "Move Down Modifier";
818         ot->description= "Move modifier down in the stack";
819         ot->idname= "OBJECT_OT_modifier_move_down";
820
821         ot->invoke= modifier_move_down_invoke;
822         ot->exec= modifier_move_down_exec;
823         ot->poll= edit_modifier_poll;
824         
825         /* flags */
826         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
827         edit_modifier_properties(ot);
828 }
829
830 /************************ apply modifier operator *********************/
831
832 static int modifier_apply_exec(bContext *C, wmOperator *op)
833 {
834         Scene *scene= CTX_data_scene(C);
835         Object *ob = ED_object_active_context(C);
836         ModifierData *md = edit_modifier_property_get(op, ob, 0);
837         int apply_as= RNA_enum_get(op->ptr, "apply_as");
838         
839         if(!ob || !md || !ED_object_modifier_apply(op->reports, scene, ob, md, apply_as)) {
840                 return OPERATOR_CANCELLED;
841         }
842
843         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
844         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
845         
846         return OPERATOR_FINISHED;
847 }
848
849 static int modifier_apply_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
850 {
851         if (edit_modifier_invoke_properties(C, op))
852                 return modifier_apply_exec(C, op);
853         else
854                 return OPERATOR_CANCELLED;
855 }
856
857 static EnumPropertyItem modifier_apply_as_items[] = {
858         {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
859         {MODIFIER_APPLY_SHAPE, "SHAPE", 0, "New Shape", "Apply deform-only modifier to a new shape on this object"},
860         {0, NULL, 0, NULL, NULL}};
861
862 void OBJECT_OT_modifier_apply(wmOperatorType *ot)
863 {
864         ot->name= "Apply Modifier";
865         ot->description= "Apply modifier and remove from the stack";
866         ot->idname= "OBJECT_OT_modifier_apply";
867
868         ot->invoke= modifier_apply_invoke;
869         ot->exec= modifier_apply_exec;
870         ot->poll= edit_modifier_poll;
871         
872         /* flags */
873         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
874         
875         RNA_def_enum(ot->srna, "apply_as", modifier_apply_as_items, MODIFIER_APPLY_DATA, "Apply as", "How to apply the modifier to the geometry");
876         edit_modifier_properties(ot);
877 }
878
879 /************************ convert modifier operator *********************/
880
881 static int modifier_convert_exec(bContext *C, wmOperator *op)
882 {
883         Main *bmain= CTX_data_main(C);
884         Scene *scene= CTX_data_scene(C);
885         Object *ob = ED_object_active_context(C);
886         ModifierData *md = edit_modifier_property_get(op, ob, 0);
887         
888         if(!ob || !md || !ED_object_modifier_convert(op->reports, bmain, scene, ob, md))
889                 return OPERATOR_CANCELLED;
890
891         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
892         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
893         
894         return OPERATOR_FINISHED;
895 }
896
897 static int modifier_convert_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
898 {
899         if (edit_modifier_invoke_properties(C, op))
900                 return modifier_convert_exec(C, op);
901         else
902                 return OPERATOR_CANCELLED;
903 }
904
905 void OBJECT_OT_modifier_convert(wmOperatorType *ot)
906 {
907         ot->name= "Convert Modifier";
908         ot->description= "Convert particles to a mesh object";
909         ot->idname= "OBJECT_OT_modifier_convert";
910
911         ot->invoke= modifier_convert_invoke;
912         ot->exec= modifier_convert_exec;
913         ot->poll= edit_modifier_poll;
914         
915         /* flags */
916         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
917         edit_modifier_properties(ot);
918 }
919
920 /************************ copy modifier operator *********************/
921
922 static int modifier_copy_exec(bContext *C, wmOperator *op)
923 {
924         Object *ob = ED_object_active_context(C);
925         ModifierData *md = edit_modifier_property_get(op, ob, 0);
926
927         if(!ob || !md || !ED_object_modifier_copy(op->reports, ob, md))
928                 return OPERATOR_CANCELLED;
929
930         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
931         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
932         
933         return OPERATOR_FINISHED;
934 }
935
936 static int modifier_copy_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
937 {
938         if (edit_modifier_invoke_properties(C, op))
939                 return modifier_copy_exec(C, op);
940         else
941                 return OPERATOR_CANCELLED;
942 }
943
944 void OBJECT_OT_modifier_copy(wmOperatorType *ot)
945 {
946         ot->name= "Copy Modifier";
947         ot->description= "Duplicate modifier at the same position in the stack";
948         ot->idname= "OBJECT_OT_modifier_copy";
949
950         ot->invoke= modifier_copy_invoke;
951         ot->exec= modifier_copy_exec;
952         ot->poll= edit_modifier_poll;
953         
954         /* flags */
955         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
956         edit_modifier_properties(ot);
957 }
958
959 /************* multires delete higher levels operator ****************/
960
961 static int multires_poll(bContext *C)
962 {
963         return edit_modifier_poll_generic(C, &RNA_MultiresModifier, (1<<OB_MESH));
964 }
965
966 static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op)
967 {
968         Object *ob = ED_object_active_context(C);
969         MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
970         
971         if (!mmd)
972                 return OPERATOR_CANCELLED;
973         
974         multiresModifier_del_levels(mmd, ob, 1);
975         
976         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
977         
978         return OPERATOR_FINISHED;
979 }
980
981 static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
982 {
983         if (edit_modifier_invoke_properties(C, op))
984                 return multires_higher_levels_delete_exec(C, op);
985         else
986                 return OPERATOR_CANCELLED;
987 }
988
989 void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
990 {
991         ot->name= "Delete Higher Levels";
992         ot->description= "Deletes the higher resolution mesh, potential loss of detail";
993         ot->idname= "OBJECT_OT_multires_higher_levels_delete";
994
995         ot->poll= multires_poll;
996         ot->invoke= multires_higher_levels_delete_invoke;
997         ot->exec= multires_higher_levels_delete_exec;
998         
999         /* flags */
1000         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1001         edit_modifier_properties(ot);
1002 }
1003
1004 /****************** multires subdivide operator *********************/
1005
1006 static int multires_subdivide_exec(bContext *C, wmOperator *op)
1007 {
1008         Object *ob = ED_object_active_context(C);
1009         MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1010         
1011         if (!mmd)
1012                 return OPERATOR_CANCELLED;
1013         
1014         multiresModifier_subdivide(mmd, ob, 0, mmd->simple);
1015
1016         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1017         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1018         
1019         return OPERATOR_FINISHED;
1020 }
1021
1022 static int multires_subdivide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1023 {
1024         if (edit_modifier_invoke_properties(C, op))
1025                 return multires_subdivide_exec(C, op);
1026         else
1027                 return OPERATOR_CANCELLED;
1028 }
1029
1030 void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
1031 {
1032         ot->name= "Multires Subdivide";
1033         ot->description= "Add a new level of subdivision";
1034         ot->idname= "OBJECT_OT_multires_subdivide";
1035
1036         ot->poll= multires_poll;
1037         ot->invoke= multires_subdivide_invoke;
1038         ot->exec= multires_subdivide_exec;
1039         
1040         /* flags */
1041         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1042         edit_modifier_properties(ot);
1043 }
1044
1045 /****************** multires reshape operator *********************/
1046
1047 static int multires_reshape_exec(bContext *C, wmOperator *op)
1048 {
1049         Object *ob= ED_object_active_context(C), *secondob= NULL;
1050         Scene *scene= CTX_data_scene(C);
1051         MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1052
1053         if (!mmd)
1054                 return OPERATOR_CANCELLED;
1055         
1056         CTX_DATA_BEGIN(C, Object*, selob, selected_editable_objects) {
1057                 if(selob->type == OB_MESH && selob != ob) {
1058                         secondob= selob;
1059                         break;
1060                 }
1061         }
1062         CTX_DATA_END;
1063
1064         if(!secondob) {
1065                 BKE_report(op->reports, RPT_ERROR, "Second selected mesh object require to copy shape from.");
1066                 return OPERATOR_CANCELLED;
1067         }
1068
1069         if(!multiresModifier_reshape(scene, mmd, ob, secondob)) {
1070                 BKE_report(op->reports, RPT_ERROR, "Objects do not have the same number of vertices.");
1071                 return OPERATOR_CANCELLED;
1072         }
1073
1074         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1075         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1076
1077         return OPERATOR_FINISHED;
1078 }
1079
1080 static int multires_reshape_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1081 {
1082         if (edit_modifier_invoke_properties(C, op))
1083                 return multires_reshape_exec(C, op);
1084         else
1085                 return OPERATOR_CANCELLED;
1086 }
1087
1088 void OBJECT_OT_multires_reshape(wmOperatorType *ot)
1089 {
1090         ot->name= "Multires Reshape";
1091         ot->description= "Copy vertex coordinates from other object";
1092         ot->idname= "OBJECT_OT_multires_reshape";
1093
1094         ot->poll= multires_poll;
1095         ot->invoke= multires_reshape_invoke;
1096         ot->exec= multires_reshape_exec;
1097         
1098         /* flags */
1099         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1100         edit_modifier_properties(ot);
1101 }
1102
1103 static int multires_test_exec(bContext *C, wmOperator *op)
1104 {
1105         Object *ob= ED_object_active_context(C);
1106         Mesh *me = ob->data;
1107         MPoly *mp;
1108         MDisps *mdisps;
1109         int i, x = RNA_int_get(op->ptr, "x"), y = RNA_int_get(op->ptr, "y");
1110         
1111         if (ob->type != OB_MESH || !me)
1112                 return OPERATOR_CANCELLED;
1113         
1114         mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
1115         if (!mdisps)
1116                 return OPERATOR_CANCELLED;
1117         
1118         mp = me->mpoly;
1119         for (i=0; i<me->totpoly; i++, mp++) {
1120                 MLoop *ml;
1121                 int j;
1122                 
1123                 ml = me->mloop + mp->loopstart;
1124                 for (j=0; j<mp->totloop; j++, ml++) {
1125                         MLoop *ml2 = me->mloop + mp->loopstart + (j+mp->totloop-1)%mp->totloop;
1126                         MLoop *ml3 = me->mloop + mp->loopstart + (j+1)%mp->totloop;
1127                         
1128                         if ((me->mvert[ml->v].flag&SELECT) && (me->mvert[ml2->v].flag&SELECT) && (me->mvert[ml3->v].flag&SELECT)) {
1129                                 MDisps *md = mdisps + mp->loopstart + j;
1130                                 int res = sqrt(md->totdisp);
1131                                 
1132                                 if (x >= res) x = res-1;
1133                                 if (y >= res) y = res-1;
1134                                 
1135                                 md->disps[y*res + x][2] += 1.0;
1136                         }
1137                 }
1138         }
1139                 
1140         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1141         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1142
1143         return OPERATOR_FINISHED;
1144 }
1145
1146 void OBJECT_OT_test_multires(wmOperatorType *ot)
1147 {
1148         ot->name= "Multires Object Mode Test";
1149         ot->description= "";
1150         ot->idname= "OBJECT_OT_test_multires";
1151
1152         ot->poll= multires_poll;
1153         ot->exec= multires_test_exec;
1154         
1155         /* flags */
1156         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1157         RNA_def_int(ot->srna, "x", 0, 0, 100, "x", "x", 0, 100);
1158         RNA_def_int(ot->srna, "y", 0, 0, 100, "y", "y", 0, 100);
1159 }
1160
1161
1162                 
1163 /****************** multires save external operator *********************/
1164
1165 static int multires_external_save_exec(bContext *C, wmOperator *op)
1166 {
1167         Object *ob = ED_object_active_context(C);
1168         Mesh *me= (ob)? ob->data: op->customdata;
1169         char path[FILE_MAX];
1170         int relative= RNA_boolean_get(op->ptr, "relative_path");
1171
1172         if(!me)
1173                 return OPERATOR_CANCELLED;
1174
1175         if(CustomData_external_test(&me->ldata, CD_MDISPS))
1176                 return OPERATOR_CANCELLED;
1177         
1178         RNA_string_get(op->ptr, "filepath", path);
1179
1180         if(relative)
1181                 BLI_path_rel(path, G.main->name);
1182
1183         CustomData_external_add(&me->ldata, &me->id, CD_MDISPS, me->totloop, path);
1184         CustomData_external_write(&me->ldata, &me->id, CD_MASK_MESH, me->totloop, 0);
1185         
1186         return OPERATOR_FINISHED;
1187 }
1188
1189 static int multires_external_save_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1190 {
1191         Object *ob = ED_object_active_context(C);
1192         MultiresModifierData *mmd;
1193         Mesh *me= ob->data;
1194         char path[FILE_MAX];
1195
1196         if (!edit_modifier_invoke_properties(C, op))
1197                 return OPERATOR_CANCELLED;
1198         
1199         mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1200         
1201         if (!mmd)
1202                 return OPERATOR_CANCELLED;
1203         
1204         if(CustomData_external_test(&me->ldata, CD_MDISPS))
1205                 return OPERATOR_CANCELLED;
1206
1207         if(!RNA_property_is_set(op->ptr, "relative_path"))
1208                 RNA_boolean_set(op->ptr, "relative_path", U.flag & USER_RELPATHS);
1209
1210         if(RNA_property_is_set(op->ptr, "filepath"))
1211                 return multires_external_save_exec(C, op);
1212         
1213         op->customdata= me;
1214
1215         BLI_snprintf(path, sizeof(path), "//%s.btx", me->id.name+2);
1216         RNA_string_set(op->ptr, "filepath", path);
1217         
1218         WM_event_add_fileselect(C, op);
1219
1220         return OPERATOR_RUNNING_MODAL;
1221 }
1222
1223 void OBJECT_OT_multires_external_save(wmOperatorType *ot)
1224 {
1225         ot->name= "Multires Save External";
1226         ot->description= "Save displacements to an external file";
1227         ot->idname= "OBJECT_OT_multires_external_save";
1228
1229         // XXX modifier no longer in context after file browser .. ot->poll= multires_poll;
1230         ot->exec= multires_external_save_exec;
1231         ot->invoke= multires_external_save_invoke;
1232         ot->poll= multires_poll;
1233         
1234         /* flags */
1235         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1236
1237         WM_operator_properties_filesel(ot, FOLDERFILE|BTXFILE, FILE_SPECIAL, FILE_SAVE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH);
1238         edit_modifier_properties(ot);
1239 }
1240
1241 /****************** multires pack operator *********************/
1242
1243 static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op))
1244 {
1245         Object *ob = ED_object_active_context(C);
1246         Mesh *me= ob->data;
1247
1248         if(!CustomData_external_test(&me->ldata, CD_MDISPS))
1249                 return OPERATOR_CANCELLED;
1250
1251         // XXX don't remove..
1252         CustomData_external_remove(&me->ldata, &me->id, CD_MDISPS, me->totloop);
1253         
1254         return OPERATOR_FINISHED;
1255 }
1256
1257 void OBJECT_OT_multires_external_pack(wmOperatorType *ot)
1258 {
1259         ot->name= "Multires Pack External";
1260         ot->description= "Pack displacements from an external file";
1261         ot->idname= "OBJECT_OT_multires_external_pack";
1262
1263         ot->poll= multires_poll;
1264         ot->exec= multires_external_pack_exec;
1265         
1266         /* flags */
1267         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1268 }
1269
1270 /********************* multires apply base ***********************/
1271 static int multires_base_apply_exec(bContext *C, wmOperator *op)
1272 {
1273         Object *ob = ED_object_active_context(C);
1274         MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1275         
1276         if (!mmd)
1277                 return OPERATOR_CANCELLED;
1278         
1279         multiresModifier_base_apply(mmd, ob);
1280
1281         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1282         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1283         
1284         return OPERATOR_FINISHED;
1285 }
1286
1287 static int multires_base_apply_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1288 {
1289         if (edit_modifier_invoke_properties(C, op))
1290                 return multires_base_apply_exec(C, op);
1291         else
1292                 return OPERATOR_CANCELLED;
1293 }
1294
1295
1296 void OBJECT_OT_multires_base_apply(wmOperatorType *ot)
1297 {
1298         ot->name= "Multires Apply Base";
1299         ot->description= "Modify the base mesh to conform to the displaced mesh";
1300         ot->idname= "OBJECT_OT_multires_base_apply";
1301
1302         ot->poll= multires_poll;
1303         ot->invoke= multires_base_apply_invoke;
1304         ot->exec= multires_base_apply_exec;
1305         
1306         /* flags */
1307         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1308         edit_modifier_properties(ot);
1309 }
1310
1311
1312 /************************ mdef bind operator *********************/
1313
1314 static int meshdeform_poll(bContext *C)
1315 {
1316         return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, (1<<OB_MESH));
1317 }
1318
1319 static int meshdeform_bind_exec(bContext *C, wmOperator *op)
1320 {
1321         Scene *scene= CTX_data_scene(C);
1322         Object *ob = ED_object_active_context(C);
1323         MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_MeshDeform);
1324         
1325         if (!mmd)
1326                 return OPERATOR_CANCELLED;
1327
1328         if(mmd->bindcagecos) {
1329                 if(mmd->bindweights) MEM_freeN(mmd->bindweights);
1330                 if(mmd->bindcagecos) MEM_freeN(mmd->bindcagecos);
1331                 if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
1332                 if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
1333                 if(mmd->dynverts) MEM_freeN(mmd->dynverts);
1334                 mmd->bindweights= NULL;
1335                 mmd->bindcagecos= NULL;
1336                 mmd->dyngrid= NULL;
1337                 mmd->dyninfluences= NULL;
1338                 mmd->dynverts= NULL;
1339                 mmd->totvert= 0;
1340                 mmd->totcagevert= 0;
1341                 mmd->totinfluence= 0;
1342                 
1343                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1344                 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1345         }
1346         else {
1347                 DerivedMesh *dm;
1348                 int mode= mmd->modifier.mode;
1349
1350                 /* force modifier to run, it will call binding routine */
1351                 mmd->bindfunc= mesh_deform_bind;
1352                 mmd->modifier.mode |= eModifierMode_Realtime;
1353
1354                 if(ob->type == OB_MESH) {
1355                         dm= mesh_create_derived_view(scene, ob, 0);
1356                         dm->release(dm);
1357                 }
1358                 else if(ob->type == OB_LATTICE) {
1359                         lattice_calc_modifiers(scene, ob);
1360                 }
1361                 else if(ob->type==OB_MBALL) {
1362                         makeDispListMBall(scene, ob);
1363                 }
1364                 else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1365                         makeDispListCurveTypes(scene, ob, 0);
1366                 }
1367
1368                 mmd->bindfunc= NULL;
1369                 mmd->modifier.mode= mode;
1370         }
1371         
1372         return OPERATOR_FINISHED;
1373 }
1374
1375 static int meshdeform_bind_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1376 {
1377         if (edit_modifier_invoke_properties(C, op))
1378                 return meshdeform_bind_exec(C, op);
1379         else 
1380                 return OPERATOR_CANCELLED;
1381 }
1382
1383 void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
1384 {
1385         /* identifiers */
1386         ot->name= "Mesh Deform Bind";
1387         ot->description = "Bind mesh to cage in mesh deform modifier";
1388         ot->idname= "OBJECT_OT_meshdeform_bind";
1389         
1390         /* api callbacks */
1391         ot->poll= meshdeform_poll;
1392         ot->invoke= meshdeform_bind_invoke;
1393         ot->exec= meshdeform_bind_exec;
1394         
1395         /* flags */
1396         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1397         edit_modifier_properties(ot);
1398 }
1399
1400 /****************** explode refresh operator *********************/
1401
1402 static int explode_poll(bContext *C)
1403 {
1404         return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0);
1405 }
1406
1407 static int explode_refresh_exec(bContext *C, wmOperator *op)
1408 {
1409         Object *ob = ED_object_active_context(C);
1410         ExplodeModifierData *emd = (ExplodeModifierData *)edit_modifier_property_get(op, ob, eModifierType_Explode);
1411         
1412         if (!emd)
1413                 return OPERATOR_CANCELLED;
1414
1415         emd->flag |= eExplodeFlag_CalcFaces;
1416
1417         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1418         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1419         
1420         return OPERATOR_FINISHED;
1421 }
1422
1423 static int explode_refresh_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1424 {
1425         if (edit_modifier_invoke_properties(C, op))
1426                 return explode_refresh_exec(C, op);
1427         else
1428                 return OPERATOR_CANCELLED;
1429 }
1430
1431
1432 void OBJECT_OT_explode_refresh(wmOperatorType *ot)
1433 {
1434         ot->name= "Explode Refresh";
1435         ot->description= "Refresh data in the Explode modifier";
1436         ot->idname= "OBJECT_OT_explode_refresh";
1437
1438         ot->poll= explode_poll;
1439         ot->invoke= explode_refresh_invoke;
1440         ot->exec= explode_refresh_exec;
1441         
1442         /* flags */
1443         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1444         edit_modifier_properties(ot);
1445 }
1446