Ocean Sim modifier patch
[blender.git] / source / blender / editors / object / object_modifier.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, 2009
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/object/object_modifier.c
27  *  \ingroup edobj
28  */
29
30
31 #include <math.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34
35 #include "MEM_guardedalloc.h"
36
37 #include "DNA_anim_types.h"
38 #include "DNA_curve_types.h"
39 #include "DNA_key_types.h"
40 #include "DNA_mesh_types.h"
41 #include "DNA_meshdata_types.h"
42 #include "DNA_object_force.h"
43 #include "DNA_scene_types.h"
44
45 #include "BLI_math.h"
46 #include "BLI_listbase.h"
47 #include "BLI_string.h"
48 #include "BLI_path_util.h"
49 #include "BLI_editVert.h"
50 #include "BLI_utildefines.h"
51
52 #include "BKE_animsys.h"
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_ocean.h"
69 #include "BKE_particle.h"
70 #include "BKE_softbody.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_mesh) {
221                                 EditMesh *em= me->edit_mesh;
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->fdata, &me->id, CD_MDISPS, 0);
225                                 EM_free_data_layer(em, &em->fdata, CD_MDISPS);
226                         } else {
227                                 CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
228                                 CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
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                         copy_v3_v3(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                         copy_v3_v3(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         if (ob->type==OB_MESH) {
413                 DerivedMesh *dm;
414                 Mesh *me= ob->data;
415                 Key *key=me->key;
416                 KeyBlock *kb;
417                 
418                 if(!modifier_sameTopology(md)) {
419                         BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to Shapes");
420                         return 0;
421                 }
422                 mesh_pmv_off(me);
423                 
424                 dm = mesh_create_derived_for_modifier(scene, ob, md);
425                 if (!dm) {
426                         BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
427                         return 0;
428                 }
429                 
430                 if(key == NULL) {
431                         key= me->key= add_key((ID *)me);
432                         key->type= KEY_RELATIVE;
433                         /* if that was the first key block added, then it was the basis.
434                          * Initialise it with the mesh, and add another for the modifier */
435                         kb= add_keyblock(key, NULL);
436                         mesh_to_key(me, kb);
437                 }
438
439                 kb= add_keyblock(key, md->name);
440                 DM_to_meshkey(dm, me, kb);
441                 
442                 dm->release(dm);
443         }
444         else {
445                 BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
446                 return 0;
447         }
448         return 1;
449 }
450
451 static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
452 {
453         ModifierTypeInfo *mti= modifierType_getInfo(md->type);
454
455         md->scene= scene;
456
457         if (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                 if( me->key) {
468                         BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to Mesh with Shape Keys");
469                         return 0;
470                 }
471
472                 mesh_pmv_off(me);
473
474                 /* Multires: ensure that recent sculpting is applied */
475                 if(md->type == eModifierType_Multires)
476                         multires_force_update(ob);
477
478                 if (mmd && mmd->totlvl && mti->type==eModifierTypeType_OnlyDeform) {
479                         if(!multiresModifier_reshapeFromDeformMod (scene, mmd, ob, md)) {
480                                 BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
481                                 return 0;
482                         }
483                 } else {
484                         dm = mesh_create_derived_for_modifier(scene, ob, md);
485                         if (!dm) {
486                                 BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
487                                 return 0;
488                         }
489
490                         DM_to_mesh(dm, me);
491
492                         dm->release(dm);
493
494                         if(md->type == eModifierType_Multires) {
495                                 CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
496                                 CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
497                         }
498                 }
499         }
500         else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
501                 Curve *cu;
502                 int numVerts;
503                 float (*vertexCos)[3];
504
505                 if (mti->type==eModifierTypeType_Constructive) {
506                         BKE_report(reports, RPT_ERROR, "Cannot apply constructive modifiers on curve");
507                         return 0;
508                 }
509
510                 cu = ob->data;
511                 BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tesselated/bevel vertices");
512
513                 vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts);
514                 mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0, 0);
515                 curve_applyVertexCos(cu, &cu->nurb, vertexCos);
516
517                 MEM_freeN(vertexCos);
518
519                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
520         }
521         else {
522                 BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
523                 return 0;
524         }
525
526         /* lattice modifier can be applied to particle system too */
527         if(ob->particlesystem.first) {
528
529                 ParticleSystem *psys = ob->particlesystem.first;
530
531                 for(; psys; psys=psys->next) {
532                         
533                         if(psys->part->type != PART_HAIR)
534                                 continue;
535
536                         psys_apply_hair_lattice(scene, ob, psys);
537                 }
538         }
539
540         return 1;
541 }
542
543 int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, ModifierData *md, int mode)
544 {
545         int prev_mode;
546
547         if (scene->obedit) {
548                 BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in editmode");
549                 return 0;
550         } else if (((ID*) ob->data)->us>1) {
551                 BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
552                 return 0;
553         }
554
555         if (md!=ob->modifiers.first)
556                 BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
557
558         /* allow apply of a not-realtime modifier, by first re-enabling realtime. */
559         prev_mode= md->mode;
560         md->mode |= eModifierMode_Realtime;
561
562         if (mode == MODIFIER_APPLY_SHAPE) {
563                 if (!modifier_apply_shape(reports, scene, ob, md)) {
564                         md->mode= prev_mode;
565                         return 0;
566                 }
567         } else {
568                 if (!modifier_apply_obdata(reports, scene, ob, md)) {
569                         md->mode= prev_mode;
570                         return 0;
571                 }
572         }
573
574         BLI_remlink(&ob->modifiers, md);
575         modifier_free(md);
576
577         return 1;
578 }
579
580 int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierData *md)
581 {
582         ModifierData *nmd;
583         
584         nmd = modifier_new(md->type);
585         modifier_copyData(md, nmd);
586         BLI_insertlink(&ob->modifiers, md, nmd);
587         modifier_unique_name(&ob->modifiers, nmd);
588
589         return 1;
590 }
591
592 /************************ add modifier operator *********************/
593
594 static int modifier_add_exec(bContext *C, wmOperator *op)
595 {
596         Main *bmain= CTX_data_main(C);
597         Scene *scene= CTX_data_scene(C);
598         Object *ob = ED_object_active_context(C);
599         int type= RNA_enum_get(op->ptr, "type");
600
601         if(!ED_object_modifier_add(op->reports, bmain, scene, ob, NULL, type))
602                 return OPERATOR_CANCELLED;
603
604         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
605         
606         return OPERATOR_FINISHED;
607 }
608
609 static EnumPropertyItem *modifier_add_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
610 {       
611         Object *ob= ED_object_active_context(C);
612         EnumPropertyItem *item= NULL, *md_item;
613         ModifierTypeInfo *mti;
614         int totitem= 0, a;
615         
616         if(!ob)
617                 return modifier_type_items;
618
619         for(a=0; modifier_type_items[a].identifier; a++) {
620                 md_item= &modifier_type_items[a];
621
622                 if(md_item->identifier[0]) {
623                         mti= modifierType_getInfo(md_item->value);
624
625                         if(mti->flags & eModifierTypeFlag_NoUserAdd)
626                                 continue;
627
628                         if(!((mti->flags & eModifierTypeFlag_AcceptsCVs) ||
629                            (ob->type==OB_MESH && (mti->flags & eModifierTypeFlag_AcceptsMesh))))
630                                 continue;
631                 }
632
633                 RNA_enum_item_add(&item, &totitem, md_item);
634         }
635
636         RNA_enum_item_end(&item, &totitem);
637         *free= 1;
638
639         return item;
640 }
641
642 void OBJECT_OT_modifier_add(wmOperatorType *ot)
643 {
644         PropertyRNA *prop;
645
646         /* identifiers */
647         ot->name= "Add Modifier";
648         ot->description = "Add a modifier to the active object";
649         ot->idname= "OBJECT_OT_modifier_add";
650         
651         /* api callbacks */
652         ot->invoke= WM_menu_invoke;
653         ot->exec= modifier_add_exec;
654         ot->poll= ED_operator_object_active_editable;
655         
656         /* flags */
657         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
658         
659         /* properties */
660         prop= RNA_def_enum(ot->srna, "type", modifier_type_items, eModifierType_Subsurf, "Type", "");
661         RNA_def_enum_funcs(prop, modifier_add_itemf);
662         ot->prop= prop;
663 }
664
665 /************************ generic functions for operators using mod names and data context *********************/
666
667 static int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
668 {
669         PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", rna_type);
670         Object *ob= (ptr.id.data)?ptr.id.data:ED_object_active_context(C);
671         
672         if (!ob || ob->id.lib) return 0;
673         if (obtype_flag && ((1<<ob->type) & obtype_flag)==0) return 0;
674         if (ptr.id.data && ((ID*)ptr.id.data)->lib) return 0;
675         
676         return 1;
677 }
678
679 static int edit_modifier_poll(bContext *C)
680 {
681         return edit_modifier_poll_generic(C, &RNA_Modifier, 0);
682 }
683
684 static void edit_modifier_properties(wmOperatorType *ot)
685 {
686         RNA_def_string(ot->srna, "modifier", "", 32, "Modifier", "Name of the modifier to edit");
687 }
688
689 static int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
690 {
691         PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
692         ModifierData *md;
693         
694         if (RNA_property_is_set(op->ptr, "modifier"))
695                 return 1;
696         
697         if (ptr.data) {
698                 md = ptr.data;
699                 RNA_string_set(op->ptr, "modifier", md->name);
700                 return 1;
701         }
702         
703         return 0;
704 }
705
706 static ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
707 {
708         char modifier_name[32];
709         ModifierData *md;
710         RNA_string_get(op->ptr, "modifier", modifier_name);
711         
712         md = modifiers_findByName(ob, modifier_name);
713         
714         if (md && type != 0 && md->type != type)
715                 md = NULL;
716
717         return md;
718 }
719
720 /************************ remove modifier operator *********************/
721
722 static int modifier_remove_exec(bContext *C, wmOperator *op)
723 {
724         Main *bmain= CTX_data_main(C);
725         Scene *scene= CTX_data_scene(C);
726         Object *ob = ED_object_active_context(C);
727         ModifierData *md = edit_modifier_property_get(op, ob, 0);
728         int mode_orig = ob ? ob->mode : 0;
729         
730         if(!ob || !md || !ED_object_modifier_remove(op->reports, bmain, scene, ob, md))
731                 return OPERATOR_CANCELLED;
732
733         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
734
735         /* if cloth/softbody was removed, particle mode could be cleared */
736         if(mode_orig & OB_MODE_PARTICLE_EDIT)
737                 if((ob->mode & OB_MODE_PARTICLE_EDIT)==0)
738                         if(scene->basact && scene->basact->object==ob)
739                                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
740         
741         return OPERATOR_FINISHED;
742 }
743
744 static int modifier_remove_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
745 {
746         if (edit_modifier_invoke_properties(C, op))
747                 return modifier_remove_exec(C, op);
748         else
749                 return OPERATOR_CANCELLED;
750 }
751
752 void OBJECT_OT_modifier_remove(wmOperatorType *ot)
753 {
754         ot->name= "Remove Modifier";
755         ot->description= "Remove a modifier from the active object";
756         ot->idname= "OBJECT_OT_modifier_remove";
757
758         ot->invoke= modifier_remove_invoke;
759         ot->exec= modifier_remove_exec;
760         ot->poll= edit_modifier_poll;
761         
762         /* flags */
763         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
764         edit_modifier_properties(ot);
765 }
766
767 /************************ move up modifier operator *********************/
768
769 static int modifier_move_up_exec(bContext *C, wmOperator *op)
770 {
771         Object *ob = ED_object_active_context(C);
772         ModifierData *md = edit_modifier_property_get(op, ob, 0);
773
774         if(!ob || !md || !ED_object_modifier_move_up(op->reports, ob, md))
775                 return OPERATOR_CANCELLED;
776
777         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
778         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
779         
780         return OPERATOR_FINISHED;
781 }
782
783 static int modifier_move_up_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
784 {
785         if (edit_modifier_invoke_properties(C, op))
786                 return modifier_move_up_exec(C, op);
787         else
788                 return OPERATOR_CANCELLED;
789 }
790
791 void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
792 {
793         ot->name= "Move Up Modifier";
794         ot->description= "Move modifier up in the stack";
795         ot->idname= "OBJECT_OT_modifier_move_up";
796
797         ot->invoke= modifier_move_up_invoke;
798         ot->exec= modifier_move_up_exec;
799         ot->poll= edit_modifier_poll;
800         
801         /* flags */
802         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
803         edit_modifier_properties(ot);
804 }
805
806 /************************ move down modifier operator *********************/
807
808 static int modifier_move_down_exec(bContext *C, wmOperator *op)
809 {
810         Object *ob = ED_object_active_context(C);
811         ModifierData *md = edit_modifier_property_get(op, ob, 0);
812
813         if(!ob || !md || !ED_object_modifier_move_down(op->reports, ob, md))
814                 return OPERATOR_CANCELLED;
815
816         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
817         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
818         
819         return OPERATOR_FINISHED;
820 }
821
822 static int modifier_move_down_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
823 {
824         if (edit_modifier_invoke_properties(C, op))
825                 return modifier_move_down_exec(C, op);
826         else
827                 return OPERATOR_CANCELLED;
828 }
829
830 void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
831 {
832         ot->name= "Move Down Modifier";
833         ot->description= "Move modifier down in the stack";
834         ot->idname= "OBJECT_OT_modifier_move_down";
835
836         ot->invoke= modifier_move_down_invoke;
837         ot->exec= modifier_move_down_exec;
838         ot->poll= edit_modifier_poll;
839         
840         /* flags */
841         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
842         edit_modifier_properties(ot);
843 }
844
845 /************************ apply modifier operator *********************/
846
847 static int modifier_apply_exec(bContext *C, wmOperator *op)
848 {
849         Scene *scene= CTX_data_scene(C);
850         Object *ob = ED_object_active_context(C);
851         ModifierData *md = edit_modifier_property_get(op, ob, 0);
852         int apply_as= RNA_enum_get(op->ptr, "apply_as");
853         
854         if(!ob || !md || !ED_object_modifier_apply(op->reports, scene, ob, md, apply_as)) {
855                 return OPERATOR_CANCELLED;
856         }
857
858         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
859         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
860         
861         return OPERATOR_FINISHED;
862 }
863
864 static int modifier_apply_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
865 {
866         if (edit_modifier_invoke_properties(C, op))
867                 return modifier_apply_exec(C, op);
868         else
869                 return OPERATOR_CANCELLED;
870 }
871
872 static EnumPropertyItem modifier_apply_as_items[] = {
873         {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
874         {MODIFIER_APPLY_SHAPE, "SHAPE", 0, "New Shape", "Apply deform-only modifier to a new shape on this object"},
875         {0, NULL, 0, NULL, NULL}};
876
877 void OBJECT_OT_modifier_apply(wmOperatorType *ot)
878 {
879         ot->name= "Apply Modifier";
880         ot->description= "Apply modifier and remove from the stack";
881         ot->idname= "OBJECT_OT_modifier_apply";
882
883         ot->invoke= modifier_apply_invoke;
884         ot->exec= modifier_apply_exec;
885         ot->poll= edit_modifier_poll;
886         
887         /* flags */
888         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
889         
890         RNA_def_enum(ot->srna, "apply_as", modifier_apply_as_items, MODIFIER_APPLY_DATA, "Apply as", "How to apply the modifier to the geometry");
891         edit_modifier_properties(ot);
892 }
893
894 /************************ convert modifier operator *********************/
895
896 static int modifier_convert_exec(bContext *C, wmOperator *op)
897 {
898         Main *bmain= CTX_data_main(C);
899         Scene *scene= CTX_data_scene(C);
900         Object *ob = ED_object_active_context(C);
901         ModifierData *md = edit_modifier_property_get(op, ob, 0);
902         
903         if(!ob || !md || !ED_object_modifier_convert(op->reports, bmain, scene, ob, md))
904                 return OPERATOR_CANCELLED;
905
906         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
907         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
908         
909         return OPERATOR_FINISHED;
910 }
911
912 static int modifier_convert_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
913 {
914         if (edit_modifier_invoke_properties(C, op))
915                 return modifier_convert_exec(C, op);
916         else
917                 return OPERATOR_CANCELLED;
918 }
919
920 void OBJECT_OT_modifier_convert(wmOperatorType *ot)
921 {
922         ot->name= "Convert Modifier";
923         ot->description= "Convert particles to a mesh object";
924         ot->idname= "OBJECT_OT_modifier_convert";
925
926         ot->invoke= modifier_convert_invoke;
927         ot->exec= modifier_convert_exec;
928         ot->poll= edit_modifier_poll;
929         
930         /* flags */
931         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
932         edit_modifier_properties(ot);
933 }
934
935 /************************ copy modifier operator *********************/
936
937 static int modifier_copy_exec(bContext *C, wmOperator *op)
938 {
939         Object *ob = ED_object_active_context(C);
940         ModifierData *md = edit_modifier_property_get(op, ob, 0);
941
942         if(!ob || !md || !ED_object_modifier_copy(op->reports, ob, md))
943                 return OPERATOR_CANCELLED;
944
945         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
946         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
947         
948         return OPERATOR_FINISHED;
949 }
950
951 static int modifier_copy_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
952 {
953         if (edit_modifier_invoke_properties(C, op))
954                 return modifier_copy_exec(C, op);
955         else
956                 return OPERATOR_CANCELLED;
957 }
958
959 void OBJECT_OT_modifier_copy(wmOperatorType *ot)
960 {
961         ot->name= "Copy Modifier";
962         ot->description= "Duplicate modifier at the same position in the stack";
963         ot->idname= "OBJECT_OT_modifier_copy";
964
965         ot->invoke= modifier_copy_invoke;
966         ot->exec= modifier_copy_exec;
967         ot->poll= edit_modifier_poll;
968         
969         /* flags */
970         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
971         edit_modifier_properties(ot);
972 }
973
974 /************* multires delete higher levels operator ****************/
975
976 static int multires_poll(bContext *C)
977 {
978         return edit_modifier_poll_generic(C, &RNA_MultiresModifier, (1<<OB_MESH));
979 }
980
981 static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op)
982 {
983         Object *ob = ED_object_active_context(C);
984         MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
985         
986         if (!mmd)
987                 return OPERATOR_CANCELLED;
988         
989         multiresModifier_del_levels(mmd, ob, 1);
990         
991         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
992         
993         return OPERATOR_FINISHED;
994 }
995
996 static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
997 {
998         if (edit_modifier_invoke_properties(C, op))
999                 return multires_higher_levels_delete_exec(C, op);
1000         else
1001                 return OPERATOR_CANCELLED;
1002 }
1003
1004 void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
1005 {
1006         ot->name= "Delete Higher Levels";
1007         ot->description= "Deletes the higher resolution mesh, potential loss of detail";
1008         ot->idname= "OBJECT_OT_multires_higher_levels_delete";
1009
1010         ot->poll= multires_poll;
1011         ot->invoke= multires_higher_levels_delete_invoke;
1012         ot->exec= multires_higher_levels_delete_exec;
1013         
1014         /* flags */
1015         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1016         edit_modifier_properties(ot);
1017 }
1018
1019 /****************** multires subdivide operator *********************/
1020
1021 static int multires_subdivide_exec(bContext *C, wmOperator *op)
1022 {
1023         Object *ob = ED_object_active_context(C);
1024         MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1025         
1026         if (!mmd)
1027                 return OPERATOR_CANCELLED;
1028         
1029         multiresModifier_subdivide(mmd, ob, 0, mmd->simple);
1030
1031         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1032         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1033         
1034         return OPERATOR_FINISHED;
1035 }
1036
1037 static int multires_subdivide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1038 {
1039         if (edit_modifier_invoke_properties(C, op))
1040                 return multires_subdivide_exec(C, op);
1041         else
1042                 return OPERATOR_CANCELLED;
1043 }
1044
1045 void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
1046 {
1047         ot->name= "Multires Subdivide";
1048         ot->description= "Add a new level of subdivision";
1049         ot->idname= "OBJECT_OT_multires_subdivide";
1050
1051         ot->poll= multires_poll;
1052         ot->invoke= multires_subdivide_invoke;
1053         ot->exec= multires_subdivide_exec;
1054         
1055         /* flags */
1056         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1057         edit_modifier_properties(ot);
1058 }
1059
1060 /****************** multires reshape operator *********************/
1061
1062 static int multires_reshape_exec(bContext *C, wmOperator *op)
1063 {
1064         Object *ob= ED_object_active_context(C), *secondob= NULL;
1065         Scene *scene= CTX_data_scene(C);
1066         MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1067
1068         if (!mmd)
1069                 return OPERATOR_CANCELLED;
1070
1071         if(mmd->lvl==0) {
1072                 BKE_report(op->reports, RPT_ERROR, "Reshape can work only with higher levels of subdivisions");
1073                 return OPERATOR_CANCELLED;
1074         }
1075
1076         CTX_DATA_BEGIN(C, Object*, selob, selected_editable_objects) {
1077                 if(selob->type == OB_MESH && selob != ob) {
1078                         secondob= selob;
1079                         break;
1080                 }
1081         }
1082         CTX_DATA_END;
1083
1084         if(!secondob) {
1085                 BKE_report(op->reports, RPT_ERROR, "Second selected mesh object require to copy shape from");
1086                 return OPERATOR_CANCELLED;
1087         }
1088
1089         if(!multiresModifier_reshape(scene, mmd, ob, secondob)) {
1090                 BKE_report(op->reports, RPT_ERROR, "Objects do not have the same number of vertices");
1091                 return OPERATOR_CANCELLED;
1092         }
1093
1094         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1095         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1096
1097         return OPERATOR_FINISHED;
1098 }
1099
1100 static int multires_reshape_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1101 {
1102         if (edit_modifier_invoke_properties(C, op))
1103                 return multires_reshape_exec(C, op);
1104         else
1105                 return OPERATOR_CANCELLED;
1106 }
1107
1108 void OBJECT_OT_multires_reshape(wmOperatorType *ot)
1109 {
1110         ot->name= "Multires Reshape";
1111         ot->description= "Copy vertex coordinates from other object";
1112         ot->idname= "OBJECT_OT_multires_reshape";
1113
1114         ot->poll= multires_poll;
1115         ot->invoke= multires_reshape_invoke;
1116         ot->exec= multires_reshape_exec;
1117         
1118         /* flags */
1119         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1120         edit_modifier_properties(ot);
1121 }
1122
1123 /****************** multires save external operator *********************/
1124
1125 static int multires_external_save_exec(bContext *C, wmOperator *op)
1126 {
1127         Object *ob = ED_object_active_context(C);
1128         Mesh *me= (ob)? ob->data: op->customdata;
1129         char path[FILE_MAX];
1130         int relative= RNA_boolean_get(op->ptr, "relative_path");
1131
1132         if(!me)
1133                 return OPERATOR_CANCELLED;
1134
1135         if(CustomData_external_test(&me->fdata, CD_MDISPS))
1136                 return OPERATOR_CANCELLED;
1137         
1138         RNA_string_get(op->ptr, "filepath", path);
1139
1140         if(relative)
1141                 BLI_path_rel(path, G.main->name);
1142
1143         CustomData_external_add(&me->fdata, &me->id, CD_MDISPS, me->totface, path);
1144         CustomData_external_write(&me->fdata, &me->id, CD_MASK_MESH, me->totface, 0);
1145         
1146         return OPERATOR_FINISHED;
1147 }
1148
1149 static int multires_external_save_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1150 {
1151         Object *ob = ED_object_active_context(C);
1152         MultiresModifierData *mmd;
1153         Mesh *me= ob->data;
1154         char path[FILE_MAX];
1155
1156         if (!edit_modifier_invoke_properties(C, op))
1157                 return OPERATOR_CANCELLED;
1158         
1159         mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1160         
1161         if (!mmd)
1162                 return OPERATOR_CANCELLED;
1163         
1164         if(CustomData_external_test(&me->fdata, CD_MDISPS))
1165                 return OPERATOR_CANCELLED;
1166
1167         if(RNA_property_is_set(op->ptr, "filepath"))
1168                 return multires_external_save_exec(C, op);
1169         
1170         op->customdata= me;
1171
1172         BLI_snprintf(path, sizeof(path), "//%s.btx", me->id.name+2);
1173         RNA_string_set(op->ptr, "filepath", path);
1174         
1175         WM_event_add_fileselect(C, op);
1176
1177         return OPERATOR_RUNNING_MODAL;
1178 }
1179
1180 void OBJECT_OT_multires_external_save(wmOperatorType *ot)
1181 {
1182         ot->name= "Multires Save External";
1183         ot->description= "Save displacements to an external file";
1184         ot->idname= "OBJECT_OT_multires_external_save";
1185
1186         // XXX modifier no longer in context after file browser .. ot->poll= multires_poll;
1187         ot->exec= multires_external_save_exec;
1188         ot->invoke= multires_external_save_invoke;
1189         ot->poll= multires_poll;
1190         
1191         /* flags */
1192         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1193
1194         WM_operator_properties_filesel(ot, FOLDERFILE|BTXFILE, FILE_SPECIAL, FILE_SAVE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH);
1195         edit_modifier_properties(ot);
1196 }
1197
1198 /****************** multires pack operator *********************/
1199
1200 static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op))
1201 {
1202         Object *ob = ED_object_active_context(C);
1203         Mesh *me= ob->data;
1204
1205         if(!CustomData_external_test(&me->fdata, CD_MDISPS))
1206                 return OPERATOR_CANCELLED;
1207
1208         // XXX don't remove..
1209         CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
1210         
1211         return OPERATOR_FINISHED;
1212 }
1213
1214 void OBJECT_OT_multires_external_pack(wmOperatorType *ot)
1215 {
1216         ot->name= "Multires Pack External";
1217         ot->description= "Pack displacements from an external file";
1218         ot->idname= "OBJECT_OT_multires_external_pack";
1219
1220         ot->poll= multires_poll;
1221         ot->exec= multires_external_pack_exec;
1222         
1223         /* flags */
1224         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1225 }
1226
1227 /********************* multires apply base ***********************/
1228 static int multires_base_apply_exec(bContext *C, wmOperator *op)
1229 {
1230         Object *ob = ED_object_active_context(C);
1231         MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
1232         
1233         if (!mmd)
1234                 return OPERATOR_CANCELLED;
1235         
1236         multiresModifier_base_apply(mmd, ob);
1237
1238         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1239         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1240         
1241         return OPERATOR_FINISHED;
1242 }
1243
1244 static int multires_base_apply_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1245 {
1246         if (edit_modifier_invoke_properties(C, op))
1247                 return multires_base_apply_exec(C, op);
1248         else
1249                 return OPERATOR_CANCELLED;
1250 }
1251
1252
1253 void OBJECT_OT_multires_base_apply(wmOperatorType *ot)
1254 {
1255         ot->name= "Multires Apply Base";
1256         ot->description= "Modify the base mesh to conform to the displaced mesh";
1257         ot->idname= "OBJECT_OT_multires_base_apply";
1258
1259         ot->poll= multires_poll;
1260         ot->invoke= multires_base_apply_invoke;
1261         ot->exec= multires_base_apply_exec;
1262         
1263         /* flags */
1264         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1265         edit_modifier_properties(ot);
1266 }
1267
1268
1269 /************************ mdef bind operator *********************/
1270
1271 static int meshdeform_poll(bContext *C)
1272 {
1273         return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, (1<<OB_MESH));
1274 }
1275
1276 static int meshdeform_bind_exec(bContext *C, wmOperator *op)
1277 {
1278         Scene *scene= CTX_data_scene(C);
1279         Object *ob = ED_object_active_context(C);
1280         MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_MeshDeform);
1281         
1282         if (!mmd)
1283                 return OPERATOR_CANCELLED;
1284
1285         if(mmd->bindcagecos) {
1286                 MEM_freeN(mmd->bindcagecos);
1287                 if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
1288                 if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
1289                 if(mmd->bindinfluences) MEM_freeN(mmd->bindinfluences);
1290                 if(mmd->bindoffsets) MEM_freeN(mmd->bindoffsets);
1291                 if(mmd->dynverts) MEM_freeN(mmd->dynverts);
1292                 if(mmd->bindweights) MEM_freeN(mmd->bindweights); /* deprecated */
1293                 if(mmd->bindcos) MEM_freeN(mmd->bindcos); /* deprecated */
1294
1295                 mmd->bindcagecos= NULL;
1296                 mmd->dyngrid= NULL;
1297                 mmd->dyninfluences= NULL;
1298                 mmd->bindoffsets= NULL;
1299                 mmd->dynverts= NULL;
1300                 mmd->bindweights= NULL; /* deprecated */
1301                 mmd->bindcos= NULL; /* deprecated */
1302                 mmd->totvert= 0;
1303                 mmd->totcagevert= 0;
1304                 mmd->totinfluence= 0;
1305                 
1306                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1307                 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1308         }
1309         else {
1310                 DerivedMesh *dm;
1311                 int mode= mmd->modifier.mode;
1312
1313                 /* force modifier to run, it will call binding routine */
1314                 mmd->bindfunc= mesh_deform_bind;
1315                 mmd->modifier.mode |= eModifierMode_Realtime;
1316
1317                 if(ob->type == OB_MESH) {
1318                         dm= mesh_create_derived_view(scene, ob, 0);
1319                         dm->release(dm);
1320                 }
1321                 else if(ob->type == OB_LATTICE) {
1322                         lattice_calc_modifiers(scene, ob);
1323                 }
1324                 else if(ob->type==OB_MBALL) {
1325                         makeDispListMBall(scene, ob);
1326                 }
1327                 else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1328                         makeDispListCurveTypes(scene, ob, 0);
1329                 }
1330
1331                 mmd->bindfunc= NULL;
1332                 mmd->modifier.mode= mode;
1333         }
1334         
1335         return OPERATOR_FINISHED;
1336 }
1337
1338 static int meshdeform_bind_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1339 {
1340         if (edit_modifier_invoke_properties(C, op))
1341                 return meshdeform_bind_exec(C, op);
1342         else 
1343                 return OPERATOR_CANCELLED;
1344 }
1345
1346 void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
1347 {
1348         /* identifiers */
1349         ot->name= "Mesh Deform Bind";
1350         ot->description = "Bind mesh to cage in mesh deform modifier";
1351         ot->idname= "OBJECT_OT_meshdeform_bind";
1352         
1353         /* api callbacks */
1354         ot->poll= meshdeform_poll;
1355         ot->invoke= meshdeform_bind_invoke;
1356         ot->exec= meshdeform_bind_exec;
1357         
1358         /* flags */
1359         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1360         edit_modifier_properties(ot);
1361 }
1362
1363 /****************** explode refresh operator *********************/
1364
1365 static int explode_poll(bContext *C)
1366 {
1367         return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0);
1368 }
1369
1370 static int explode_refresh_exec(bContext *C, wmOperator *op)
1371 {
1372         Object *ob = ED_object_active_context(C);
1373         ExplodeModifierData *emd = (ExplodeModifierData *)edit_modifier_property_get(op, ob, eModifierType_Explode);
1374         
1375         if (!emd)
1376                 return OPERATOR_CANCELLED;
1377
1378         emd->flag |= eExplodeFlag_CalcFaces;
1379
1380         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1381         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1382         
1383         return OPERATOR_FINISHED;
1384 }
1385
1386 static int explode_refresh_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1387 {
1388         if (edit_modifier_invoke_properties(C, op))
1389                 return explode_refresh_exec(C, op);
1390         else
1391                 return OPERATOR_CANCELLED;
1392 }
1393
1394
1395 void OBJECT_OT_explode_refresh(wmOperatorType *ot)
1396 {
1397         ot->name= "Explode Refresh";
1398         ot->description= "Refresh data in the Explode modifier";
1399         ot->idname= "OBJECT_OT_explode_refresh";
1400
1401         ot->poll= explode_poll;
1402         ot->invoke= explode_refresh_invoke;
1403         ot->exec= explode_refresh_exec;
1404         
1405         /* flags */
1406         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1407         edit_modifier_properties(ot);
1408 }
1409
1410
1411 /****************** ocean bake operator *********************/
1412
1413 static int ocean_bake_poll(bContext *C)
1414 {
1415         return edit_modifier_poll_generic(C, &RNA_OceanModifier, 0);
1416 }
1417
1418 /* copied from init_ocean_modifier, MOD_ocean.c */
1419 static void init_ocean_modifier_bake(struct Ocean *oc, struct OceanModifierData *omd)
1420 {
1421         int do_heightfield, do_chop, do_normals, do_jacobian;
1422         
1423         if (!omd || !oc) return; 
1424         
1425         do_heightfield = TRUE;
1426         do_chop = (omd->chop_amount > 0);
1427         do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
1428         do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
1429         
1430         BKE_init_ocean(oc, omd->resolution*omd->resolution, omd->resolution*omd->resolution, omd->spatial_size, omd->spatial_size, 
1431                                    omd->wind_velocity, omd->smallest_wave, 1.0, omd->wave_direction, omd->damp, omd->wave_alignment, 
1432                                    omd->depth, omd->time,
1433                                    do_heightfield, do_chop, do_normals, do_jacobian,
1434                                    omd->seed);
1435 }
1436
1437 typedef struct OceanBakeJob {
1438         /* from wmJob */
1439         void *owner;
1440         short *stop, *do_update;
1441         float *progress;
1442         int current_frame;
1443         struct OceanCache *och;
1444         struct Ocean *ocean;
1445         struct OceanModifierData *omd;
1446 } OceanBakeJob;
1447
1448 static void oceanbake_free(void *customdata)
1449 {
1450         OceanBakeJob *oj= customdata;
1451         MEM_freeN(oj);
1452 }
1453
1454 /* called by oceanbake, only to check job 'stop' value */
1455 static int oceanbake_breakjob(void *UNUSED(customdata))
1456 {
1457         //OceanBakeJob *ob= (OceanBakeJob *)customdata;
1458         //return *(ob->stop);
1459         
1460         /* this is not nice yet, need to make the jobs list template better 
1461          * for identifying/acting upon various different jobs */
1462         /* but for now we'll reuse the render break... */
1463         return (G.afbreek);
1464 }
1465
1466 /* called by oceanbake, wmJob sends notifier */
1467 static void oceanbake_update(void *customdata, float progress, int *cancel)
1468 {
1469         OceanBakeJob *oj= customdata;
1470         
1471         if (oceanbake_breakjob(oj))
1472                 *cancel = 1;
1473         
1474         *(oj->do_update)= 1;
1475         *(oj->progress)= progress;
1476 }
1477
1478 static void oceanbake_startjob(void *customdata, short *stop, short *do_update, float *progress)
1479 {
1480         OceanBakeJob *oj= customdata;
1481         
1482         oj->stop= stop;
1483         oj->do_update = do_update;
1484         oj->progress = progress;
1485         
1486         G.afbreek= 0;   /* XXX shared with render - replace with job 'stop' switch */
1487         
1488         BKE_bake_ocean(oj->ocean, oj->och, oceanbake_update, (void *)oj);
1489         
1490         *do_update= 1;
1491         *stop = 0;
1492 }
1493
1494 static void oceanbake_endjob(void *customdata)
1495 {
1496         OceanBakeJob *oj= customdata;
1497         
1498         if (oj->ocean) {
1499                 BKE_free_ocean(oj->ocean);
1500                 oj->ocean = NULL;
1501         }
1502         
1503         oj->omd->oceancache = oj->och;
1504         oj->omd->cached = TRUE;
1505 }
1506
1507 static int ocean_bake_exec(bContext *C, wmOperator *op)
1508 {
1509         Object *ob = ED_object_active_context(C);
1510         OceanModifierData *omd = (OceanModifierData *)edit_modifier_property_get(op, ob, eModifierType_Ocean);
1511         Scene *scene = CTX_data_scene(C);
1512         OceanCache *och;
1513         struct Ocean *ocean;
1514         int f, cfra, i=0;
1515         int free= RNA_boolean_get(op->ptr, "free");
1516         
1517         wmJob *steve;
1518         OceanBakeJob *oj;
1519         
1520         if (!omd)
1521                 return OPERATOR_CANCELLED;
1522         
1523         if (free) {
1524                 omd->refresh |= MOD_OCEAN_REFRESH_CLEAR_CACHE;
1525                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1526                 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1527                 return OPERATOR_FINISHED;
1528         }
1529         
1530         och = BKE_init_ocean_cache(omd->cachepath, omd->bakestart, omd->bakeend, omd->wave_scale, 
1531                                                            omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
1532         
1533         och->time = MEM_mallocN(och->duration*sizeof(float), "foam bake time");
1534         
1535         cfra = scene->r.cfra;
1536         
1537         /* precalculate time variable before baking */
1538         for (f=omd->bakestart; f<=omd->bakeend; f++) {
1539                 /* from physics_fluid.c:
1540                  
1541                  * XXX: This can't be used due to an anim sys optimisation that ignores recalc object animation,
1542                  * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ )
1543                  * --> BKE_animsys_evaluate_all_animation(G.main, eval_time);
1544                  * This doesn't work with drivers:
1545                  * --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL);
1546                  */
1547                 
1548                 /* Modifying the global scene isn't nice, but we can do it in 
1549                  * this part of the process before a threaded job is created */
1550                 
1551                 //scene->r.cfra = f;
1552                 //ED_update_for_newframe(CTX_data_main(C), scene, CTX_wm_screen(C), 1);
1553                 
1554                 /* ok, this doesn't work with drivers, but is way faster. 
1555                  * let's use this for now and hope nobody wants to drive the time value... */
1556                 BKE_animsys_evaluate_animdata(scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM);
1557                 
1558                 och->time[i] = omd->time;
1559                 i++;
1560         }
1561         
1562         /* make a copy of ocean to use for baking - threadsafety */
1563         ocean = BKE_add_ocean();
1564         init_ocean_modifier_bake(ocean, omd);
1565         
1566         /*
1567          BKE_bake_ocean(ocean, och);
1568         
1569         omd->oceancache = och;
1570         omd->cached = TRUE;
1571         
1572         scene->r.cfra = cfra;
1573         
1574         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1575         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
1576         */
1577         
1578         /* job stuff */
1579         
1580         scene->r.cfra = cfra;
1581         
1582         /* setup job */
1583         steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Ocean Simulation", WM_JOB_PROGRESS);
1584         oj= MEM_callocN(sizeof(OceanBakeJob), "ocean bake job");
1585         oj->ocean = ocean;
1586         oj->och = och;
1587         oj->omd = omd;
1588         
1589         WM_jobs_customdata(steve, oj, oceanbake_free);
1590         WM_jobs_timer(steve, 0.1, NC_OBJECT|ND_MODIFIER, NC_OBJECT|ND_MODIFIER);
1591         WM_jobs_callbacks(steve, oceanbake_startjob, NULL, NULL, oceanbake_endjob);
1592         
1593         WM_jobs_start(CTX_wm_manager(C), steve);
1594         
1595         
1596         
1597         return OPERATOR_FINISHED;
1598 }
1599
1600 static int ocean_bake_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
1601 {
1602         if (edit_modifier_invoke_properties(C, op))
1603                 return ocean_bake_exec(C, op);
1604         else
1605                 return OPERATOR_CANCELLED;
1606 }
1607
1608
1609 void OBJECT_OT_ocean_bake(wmOperatorType *ot)
1610 {
1611         ot->name= "Bake Ocean";
1612         ot->description= "Bake an image sequence of ocean data";
1613         ot->idname= "OBJECT_OT_ocean_bake";
1614         
1615         ot->poll= ocean_bake_poll;
1616         ot->invoke= ocean_bake_invoke;
1617         ot->exec= ocean_bake_exec;
1618         
1619         /* flags */
1620         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1621         edit_modifier_properties(ot);
1622         
1623         RNA_def_boolean(ot->srna, "free", FALSE, "Free", "Free the bake, rather than generating it");
1624 }
1625