Blender V2.61 - r43446

object_modifier.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): Blender Foundation, 2009
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  */
00025 
00031 #include <math.h>
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 
00035 #include "MEM_guardedalloc.h"
00036 
00037 #include "DNA_anim_types.h"
00038 #include "DNA_curve_types.h"
00039 #include "DNA_key_types.h"
00040 #include "DNA_mesh_types.h"
00041 #include "DNA_meshdata_types.h"
00042 #include "DNA_object_force.h"
00043 #include "DNA_scene_types.h"
00044 
00045 #include "BLI_math.h"
00046 #include "BLI_listbase.h"
00047 #include "BLI_string.h"
00048 #include "BLI_path_util.h"
00049 #include "BLI_editVert.h"
00050 #include "BLI_utildefines.h"
00051 
00052 #include "BKE_animsys.h"
00053 #include "BKE_curve.h"
00054 #include "BKE_context.h"
00055 #include "BKE_depsgraph.h"
00056 #include "BKE_displist.h"
00057 #include "BKE_DerivedMesh.h"
00058 #include "BKE_effect.h"
00059 #include "BKE_global.h"
00060 #include "BKE_key.h"
00061 #include "BKE_lattice.h"
00062 #include "BKE_main.h"
00063 #include "BKE_mesh.h"
00064 #include "BKE_modifier.h"
00065 #include "BKE_multires.h"
00066 #include "BKE_report.h"
00067 #include "BKE_object.h"
00068 #include "BKE_ocean.h"
00069 #include "BKE_particle.h"
00070 #include "BKE_softbody.h"
00071 
00072 #include "RNA_access.h"
00073 #include "RNA_define.h"
00074 #include "RNA_enum_types.h"
00075 
00076 #include "ED_armature.h"
00077 #include "ED_object.h"
00078 #include "ED_screen.h"
00079 #include "ED_mesh.h"
00080 
00081 #include "WM_api.h"
00082 #include "WM_types.h"
00083 
00084 #include "object_intern.h"
00085 
00086 /******************************** API ****************************/
00087 
00088 ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type)
00089 {
00090     ModifierData *md=NULL, *new_md=NULL;
00091     ModifierTypeInfo *mti = modifierType_getInfo(type);
00092     
00093     /* only geometry objects should be able to get modifiers [#25291] */
00094     if(!ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
00095         BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to Object '%s'", ob->id.name+2);
00096         return NULL;
00097     }
00098     
00099     if(mti->flags&eModifierTypeFlag_Single) {
00100         if(modifiers_findByType(ob, type)) {
00101             BKE_report(reports, RPT_WARNING, "Only one modifier of this type allowed");
00102             return NULL;
00103         }
00104     }
00105     
00106     if(type == eModifierType_ParticleSystem) {
00107         /* don't need to worry about the new modifier's name, since that is set to the number
00108          * of particle systems which shouldn't have too many duplicates 
00109          */
00110         new_md = object_add_particle_system(scene, ob, name);
00111     }
00112     else {
00113         /* get new modifier data to add */
00114         new_md= modifier_new(type);
00115         
00116         if(mti->flags&eModifierTypeFlag_RequiresOriginalData) {
00117             md = ob->modifiers.first;
00118             
00119             while(md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform)
00120                 md = md->next;
00121             
00122             BLI_insertlinkbefore(&ob->modifiers, md, new_md);
00123         }
00124         else
00125             BLI_addtail(&ob->modifiers, new_md);
00126 
00127         if(name)
00128             BLI_strncpy(new_md->name, name, sizeof(new_md->name));
00129 
00130         /* make sure modifier data has unique name */
00131 
00132         modifier_unique_name(&ob->modifiers, new_md);
00133         
00134         /* special cases */
00135         if(type == eModifierType_Softbody) {
00136             if(!ob->soft) {
00137                 ob->soft= sbNew(scene);
00138                 ob->softflag |= OB_SB_GOAL|OB_SB_EDGES;
00139             }
00140         }
00141         else if(type == eModifierType_Collision) {
00142             if(!ob->pd)
00143                 ob->pd= object_add_collision_fields(0);
00144             
00145             ob->pd->deflect= 1;
00146             DAG_scene_sort(bmain, scene);
00147         }
00148         else if(type == eModifierType_Surface)
00149             DAG_scene_sort(bmain, scene);
00150         else if(type == eModifierType_Multires)
00151             /* set totlvl from existing MDISPS layer if object already had it */
00152             multiresModifier_set_levels_from_disps((MultiresModifierData *)new_md, ob);
00153     }
00154 
00155     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00156 
00157     return new_md;
00158 }
00159 
00160 static int object_modifier_remove(Object *ob, ModifierData *md, int *sort_depsgraph)
00161 {
00162     ModifierData *obmd;
00163 
00164     /* It seems on rapid delete it is possible to
00165      * get called twice on same modifier, so make
00166      * sure it is in list. */
00167     for(obmd=ob->modifiers.first; obmd; obmd=obmd->next)
00168         if(obmd==md)
00169             break;
00170 
00171     if(!obmd)
00172         return 0;
00173 
00174     /* special cases */
00175     if(md->type == eModifierType_ParticleSystem) {
00176         ParticleSystemModifierData *psmd=(ParticleSystemModifierData*)md;
00177 
00178         BLI_remlink(&ob->particlesystem, psmd->psys);
00179         psys_free(ob, psmd->psys);
00180         psmd->psys= NULL;
00181     }
00182     else if(md->type == eModifierType_Softbody) {
00183         if(ob->soft) {
00184             sbFree(ob->soft);
00185             ob->soft= NULL;
00186             ob->softflag= 0;
00187         }
00188     }
00189     else if(md->type == eModifierType_Collision) {
00190         if(ob->pd)
00191             ob->pd->deflect= 0;
00192 
00193         *sort_depsgraph = 1;
00194     }
00195     else if(md->type == eModifierType_Surface) {
00196         if(ob->pd && ob->pd->shape == PFIELD_SHAPE_SURFACE)
00197             ob->pd->shape = PFIELD_SHAPE_PLANE;
00198 
00199         *sort_depsgraph = 1;
00200     }
00201     else if(md->type == eModifierType_Smoke) {
00202         ob->dt = OB_TEXTURE;
00203     }
00204     else if(md->type == eModifierType_Multires) {
00205         int ok= 1;
00206         Mesh *me= ob->data;
00207         ModifierData *tmpmd;
00208 
00209         /* ensure MDISPS CustomData layer is't used by another multires modifiers */
00210         for(tmpmd= ob->modifiers.first; tmpmd; tmpmd= tmpmd->next)
00211             if(tmpmd!=md && tmpmd->type == eModifierType_Multires) {
00212                 ok= 0;
00213                 break;
00214             }
00215 
00216         if(ok) {
00217             if(me->edit_mesh) {
00218                 EditMesh *em= me->edit_mesh;
00219                 /* CustomData_external_remove is used here only to mark layer as non-external
00220                    for further free-ing, so zero element count looks safer than em->totface */
00221                 CustomData_external_remove(&em->fdata, &me->id, CD_MDISPS, 0);
00222                 EM_free_data_layer(em, &em->fdata, CD_MDISPS);
00223             } else {
00224                 CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
00225                 CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
00226             }
00227         }
00228     }
00229 
00230     if(ELEM(md->type, eModifierType_Softbody, eModifierType_Cloth) &&
00231         ob->particlesystem.first == NULL) {
00232         ob->mode &= ~OB_MODE_PARTICLE_EDIT;
00233     }
00234 
00235     BLI_remlink(&ob->modifiers, md);
00236     modifier_free(md);
00237 
00238     return 1;
00239 }
00240 
00241 int ED_object_modifier_remove(ReportList *reports, Main *bmain, Scene *scene, Object *ob, ModifierData *md)
00242 {
00243     int sort_depsgraph = 0;
00244     int ok;
00245 
00246     ok= object_modifier_remove(ob, md, &sort_depsgraph);
00247 
00248     if(!ok) {
00249         BKE_reportf(reports, RPT_ERROR, "Modifier '%s' not in object '%s'", ob->id.name, md->name);
00250         return 0;
00251     }
00252 
00253     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00254 
00255     /* sorting has to be done after the update so that dynamic systems can react properly */
00256     if(sort_depsgraph)
00257         DAG_scene_sort(bmain, scene);
00258 
00259     return 1;
00260 }
00261 
00262 void ED_object_modifier_clear(Main *bmain, Scene *scene, Object *ob)
00263 {
00264     ModifierData *md =ob->modifiers.first;
00265     int sort_depsgraph = 0;
00266 
00267     if(!md)
00268         return;
00269 
00270     while(md) {
00271         ModifierData *next_md;
00272 
00273         next_md= md->next;
00274 
00275         object_modifier_remove(ob, md, &sort_depsgraph);
00276 
00277         md= next_md;
00278     }
00279 
00280     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00281 
00282     /* sorting has to be done after the update so that dynamic systems can react properly */
00283     if(sort_depsgraph)
00284         DAG_scene_sort(bmain, scene);
00285 }
00286 
00287 int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md)
00288 {
00289     if(md->prev) {
00290         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
00291 
00292         if(mti->type!=eModifierTypeType_OnlyDeform) {
00293             ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
00294 
00295             if(nmti->flags&eModifierTypeFlag_RequiresOriginalData) {
00296                 BKE_report(reports, RPT_WARNING, "Cannot move above a modifier requiring original data");
00297                 return 0;
00298             }
00299         }
00300 
00301         BLI_remlink(&ob->modifiers, md);
00302         BLI_insertlink(&ob->modifiers, md->prev->prev, md);
00303     }
00304 
00305     return 1;
00306 }
00307 
00308 int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *md)
00309 {
00310     if(md->next) {
00311         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
00312 
00313         if(mti->flags&eModifierTypeFlag_RequiresOriginalData) {
00314             ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
00315 
00316             if(nmti->type!=eModifierTypeType_OnlyDeform) {
00317                 BKE_report(reports, RPT_WARNING, "Cannot move beyond a non-deforming modifier");
00318                 return 0;
00319             }
00320         }
00321 
00322         BLI_remlink(&ob->modifiers, md);
00323         BLI_insertlink(&ob->modifiers, md->next, md);
00324     }
00325 
00326     return 1;
00327 }
00328 
00329 int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *scene, Object *ob, ModifierData *md)
00330 {
00331     Object *obn;
00332     ParticleSystem *psys;
00333     ParticleCacheKey *key, **cache;
00334     ParticleSettings *part;
00335     Mesh *me;
00336     MVert *mvert;
00337     MEdge *medge;
00338     int a, k, kmax;
00339     int totvert=0, totedge=0, cvert=0;
00340     int totpart=0, totchild=0;
00341 
00342     if(md->type != eModifierType_ParticleSystem) return 0;
00343     if(ob && ob->mode & OB_MODE_PARTICLE_EDIT) return 0;
00344 
00345     psys=((ParticleSystemModifierData *)md)->psys;
00346     part= psys->part;
00347 
00348     if(part->ren_as != PART_DRAW_PATH || psys->pathcache == NULL)
00349         return 0;
00350 
00351     totpart= psys->totcached;
00352     totchild= psys->totchildcache;
00353 
00354     if(totchild && (part->draw&PART_DRAW_PARENT)==0)
00355         totpart= 0;
00356 
00357     /* count */
00358     cache= psys->pathcache;
00359     for(a=0; a<totpart; a++) {
00360         key= cache[a];
00361 
00362         if(key->steps > 0) {
00363             totvert+= key->steps+1;
00364             totedge+= key->steps;
00365         }
00366     }
00367 
00368     cache= psys->childcache;
00369     for(a=0; a<totchild; a++) {
00370         key= cache[a];
00371 
00372         if(key->steps > 0) {
00373             totvert+= key->steps+1;
00374             totedge+= key->steps;
00375         }
00376     }
00377 
00378     if(totvert==0) return 0;
00379 
00380     /* add new mesh */
00381     obn= add_object(scene, OB_MESH);
00382     me= obn->data;
00383     
00384     me->totvert= totvert;
00385     me->totedge= totedge;
00386     
00387     me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
00388     me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
00389     me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
00390     
00391     mvert= me->mvert;
00392     medge= me->medge;
00393 
00394     /* copy coordinates */
00395     cache= psys->pathcache;
00396     for(a=0; a<totpart; a++) {
00397         key= cache[a];
00398         kmax= key->steps;
00399         for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
00400             copy_v3_v3(mvert->co,key->co);
00401             if(k) {
00402                 medge->v1= cvert-1;
00403                 medge->v2= cvert;
00404                 medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
00405                 medge++;
00406             }
00407             else {
00408                 /* cheap trick to select the roots */
00409                 mvert->flag |= SELECT;
00410             }
00411         }
00412     }
00413 
00414     cache=psys->childcache;
00415     for(a=0; a<totchild; a++) {
00416         key=cache[a];
00417         kmax=key->steps;
00418         for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
00419             copy_v3_v3(mvert->co,key->co);
00420             if(k) {
00421                 medge->v1=cvert-1;
00422                 medge->v2=cvert;
00423                 medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
00424                 medge++;
00425             }
00426             else {
00427                 /* cheap trick to select the roots */
00428                 mvert->flag |= SELECT;
00429             }
00430         }
00431     }
00432 
00433     DAG_scene_sort(bmain, scene);
00434 
00435     return 1;
00436 }
00437 
00438 static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
00439 {
00440     ModifierTypeInfo *mti= modifierType_getInfo(md->type);
00441 
00442     md->scene= scene;
00443 
00444     if (mti->isDisabled && mti->isDisabled(md, 0)) {
00445         BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
00446         return 0;
00447     }
00448 
00449     if (ob->type==OB_MESH) {
00450         DerivedMesh *dm;
00451         Mesh *me= ob->data;
00452         Key *key=me->key;
00453         KeyBlock *kb;
00454         
00455         if(!modifier_sameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) {
00456             BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to Shapes");
00457             return 0;
00458         }
00459         
00460         dm = mesh_create_derived_for_modifier(scene, ob, md);
00461         if (!dm) {
00462             BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
00463             return 0;
00464         }
00465         
00466         if(key == NULL) {
00467             key= me->key= add_key((ID *)me);
00468             key->type= KEY_RELATIVE;
00469             /* if that was the first key block added, then it was the basis.
00470              * Initialise it with the mesh, and add another for the modifier */
00471             kb= add_keyblock(key, NULL);
00472             mesh_to_key(me, kb);
00473         }
00474 
00475         kb= add_keyblock(key, md->name);
00476         DM_to_meshkey(dm, me, kb);
00477         
00478         dm->release(dm);
00479     }
00480     else {
00481         BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
00482         return 0;
00483     }
00484     return 1;
00485 }
00486 
00487 static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, ModifierData *md)
00488 {
00489     ModifierTypeInfo *mti= modifierType_getInfo(md->type);
00490 
00491     md->scene= scene;
00492 
00493     if (mti->isDisabled && mti->isDisabled(md, 0)) {
00494         BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply");
00495         return 0;
00496     }
00497 
00498     if (ob->type==OB_MESH) {
00499         DerivedMesh *dm;
00500         Mesh *me = ob->data;
00501         MultiresModifierData *mmd= find_multires_modifier_before(scene, md);
00502 
00503         if(me->key && mti->type != eModifierTypeType_NonGeometrical) {
00504             BKE_report(reports, RPT_ERROR, "Modifier cannot be applied to Mesh with Shape Keys");
00505             return 0;
00506         }
00507 
00508         /* Multires: ensure that recent sculpting is applied */
00509         if(md->type == eModifierType_Multires)
00510             multires_force_update(ob);
00511 
00512         if (mmd && mmd->totlvl && mti->type==eModifierTypeType_OnlyDeform) {
00513             if(!multiresModifier_reshapeFromDeformMod (scene, mmd, ob, md)) {
00514                 BKE_report(reports, RPT_ERROR, "Multires modifier returned error, skipping apply");
00515                 return 0;
00516             }
00517         } else {
00518             dm = mesh_create_derived_for_modifier(scene, ob, md);
00519             if (!dm) {
00520                 BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
00521                 return 0;
00522             }
00523 
00524             DM_to_mesh(dm, me);
00525 
00526             dm->release(dm);
00527 
00528             if(md->type == eModifierType_Multires) {
00529                 CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
00530                 CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
00531             }
00532         }
00533     }
00534     else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
00535         Curve *cu;
00536         int numVerts;
00537         float (*vertexCos)[3];
00538 
00539         if (mti->type==eModifierTypeType_Constructive) {
00540             BKE_report(reports, RPT_ERROR, "Cannot apply constructive modifiers on curve");
00541             return 0;
00542         }
00543 
00544         cu = ob->data;
00545         BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tesselated/bevel vertices");
00546 
00547         vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts);
00548         mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0, 0);
00549         curve_applyVertexCos(cu, &cu->nurb, vertexCos);
00550 
00551         MEM_freeN(vertexCos);
00552 
00553         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00554     }
00555     else {
00556         BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
00557         return 0;
00558     }
00559 
00560     /* lattice modifier can be applied to particle system too */
00561     if(ob->particlesystem.first) {
00562 
00563         ParticleSystem *psys = ob->particlesystem.first;
00564 
00565         for(; psys; psys=psys->next) {
00566             
00567             if(psys->part->type != PART_HAIR)
00568                 continue;
00569 
00570             psys_apply_hair_lattice(scene, ob, psys);
00571         }
00572     }
00573 
00574     return 1;
00575 }
00576 
00577 int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, ModifierData *md, int mode)
00578 {
00579     int prev_mode;
00580 
00581     if (scene->obedit) {
00582         BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in editmode");
00583         return 0;
00584     } else if (((ID*) ob->data)->us>1) {
00585         BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data");
00586         return 0;
00587     }
00588 
00589     if (md!=ob->modifiers.first)
00590         BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected");
00591 
00592     /* allow apply of a not-realtime modifier, by first re-enabling realtime. */
00593     prev_mode= md->mode;
00594     md->mode |= eModifierMode_Realtime;
00595 
00596     if (mode == MODIFIER_APPLY_SHAPE) {
00597         if (!modifier_apply_shape(reports, scene, ob, md)) {
00598             md->mode= prev_mode;
00599             return 0;
00600         }
00601     } else {
00602         if (!modifier_apply_obdata(reports, scene, ob, md)) {
00603             md->mode= prev_mode;
00604             return 0;
00605         }
00606     }
00607 
00608     BLI_remlink(&ob->modifiers, md);
00609     modifier_free(md);
00610 
00611     return 1;
00612 }
00613 
00614 int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierData *md)
00615 {
00616     ModifierData *nmd;
00617     
00618     nmd = modifier_new(md->type);
00619     modifier_copyData(md, nmd);
00620     BLI_insertlink(&ob->modifiers, md, nmd);
00621     modifier_unique_name(&ob->modifiers, nmd);
00622 
00623     return 1;
00624 }
00625 
00626 /************************ add modifier operator *********************/
00627 
00628 static int modifier_add_exec(bContext *C, wmOperator *op)
00629 {
00630     Main *bmain= CTX_data_main(C);
00631     Scene *scene= CTX_data_scene(C);
00632     Object *ob = ED_object_active_context(C);
00633     int type= RNA_enum_get(op->ptr, "type");
00634 
00635     if(!ED_object_modifier_add(op->reports, bmain, scene, ob, NULL, type))
00636         return OPERATOR_CANCELLED;
00637 
00638     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
00639     
00640     return OPERATOR_FINISHED;
00641 }
00642 
00643 static EnumPropertyItem *modifier_add_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
00644 {   
00645     Object *ob= ED_object_active_context(C);
00646     EnumPropertyItem *item= NULL, *md_item, *group_item= NULL;
00647     ModifierTypeInfo *mti;
00648     int totitem= 0, a;
00649     
00650     if(!ob)
00651         return modifier_type_items;
00652 
00653     for(a=0; modifier_type_items[a].identifier; a++) {
00654         md_item= &modifier_type_items[a];
00655 
00656         if(md_item->identifier[0]) {
00657             mti= modifierType_getInfo(md_item->value);
00658 
00659             if(mti->flags & eModifierTypeFlag_NoUserAdd)
00660                 continue;
00661 
00662             if(!((mti->flags & eModifierTypeFlag_AcceptsCVs) ||
00663                (ob->type==OB_MESH && (mti->flags & eModifierTypeFlag_AcceptsMesh))))
00664                 continue;
00665         }
00666         else {
00667             group_item= md_item;
00668             md_item= NULL;
00669 
00670             continue;
00671         }
00672 
00673         if(group_item) {
00674             RNA_enum_item_add(&item, &totitem, group_item);
00675             group_item= NULL;
00676         }
00677 
00678         RNA_enum_item_add(&item, &totitem, md_item);
00679     }
00680 
00681     RNA_enum_item_end(&item, &totitem);
00682     *free= 1;
00683 
00684     return item;
00685 }
00686 
00687 void OBJECT_OT_modifier_add(wmOperatorType *ot)
00688 {
00689     PropertyRNA *prop;
00690 
00691     /* identifiers */
00692     ot->name= "Add Modifier";
00693     ot->description = "Add a modifier to the active object";
00694     ot->idname= "OBJECT_OT_modifier_add";
00695     
00696     /* api callbacks */
00697     ot->invoke= WM_menu_invoke;
00698     ot->exec= modifier_add_exec;
00699     ot->poll= ED_operator_object_active_editable;
00700     
00701     /* flags */
00702     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00703     
00704     /* properties */
00705     prop= RNA_def_enum(ot->srna, "type", modifier_type_items, eModifierType_Subsurf, "Type", "");
00706     RNA_def_enum_funcs(prop, modifier_add_itemf);
00707     ot->prop= prop;
00708 }
00709 
00710 /************************ generic functions for operators using mod names and data context *********************/
00711 
00712 static int edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, int obtype_flag)
00713 {
00714     PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", rna_type);
00715     Object *ob= (ptr.id.data)?ptr.id.data:ED_object_active_context(C);
00716     
00717     if (!ob || ob->id.lib) return 0;
00718     if (obtype_flag && ((1<<ob->type) & obtype_flag)==0) return 0;
00719     if (ptr.id.data && ((ID*)ptr.id.data)->lib) return 0;
00720     
00721     return 1;
00722 }
00723 
00724 static int edit_modifier_poll(bContext *C)
00725 {
00726     return edit_modifier_poll_generic(C, &RNA_Modifier, 0);
00727 }
00728 
00729 static void edit_modifier_properties(wmOperatorType *ot)
00730 {
00731     RNA_def_string(ot->srna, "modifier", "", MAX_NAME, "Modifier", "Name of the modifier to edit");
00732 }
00733 
00734 static int edit_modifier_invoke_properties(bContext *C, wmOperator *op)
00735 {
00736     PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier);
00737     ModifierData *md;
00738     
00739     if (RNA_struct_property_is_set(op->ptr, "modifier"))
00740         return 1;
00741     
00742     if (ptr.data) {
00743         md = ptr.data;
00744         RNA_string_set(op->ptr, "modifier", md->name);
00745         return 1;
00746     }
00747     
00748     return 0;
00749 }
00750 
00751 static ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
00752 {
00753     char modifier_name[MAX_NAME];
00754     ModifierData *md;
00755     RNA_string_get(op->ptr, "modifier", modifier_name);
00756     
00757     md = modifiers_findByName(ob, modifier_name);
00758     
00759     if (md && type != 0 && md->type != type)
00760         md = NULL;
00761 
00762     return md;
00763 }
00764 
00765 /************************ remove modifier operator *********************/
00766 
00767 static int modifier_remove_exec(bContext *C, wmOperator *op)
00768 {
00769     Main *bmain= CTX_data_main(C);
00770     Scene *scene= CTX_data_scene(C);
00771     Object *ob = ED_object_active_context(C);
00772     ModifierData *md = edit_modifier_property_get(op, ob, 0);
00773     int mode_orig = ob ? ob->mode : 0;
00774     
00775     if(!ob || !md || !ED_object_modifier_remove(op->reports, bmain, scene, ob, md))
00776         return OPERATOR_CANCELLED;
00777 
00778     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
00779 
00780     /* if cloth/softbody was removed, particle mode could be cleared */
00781     if(mode_orig & OB_MODE_PARTICLE_EDIT)
00782         if((ob->mode & OB_MODE_PARTICLE_EDIT)==0)
00783             if(scene->basact && scene->basact->object==ob)
00784                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
00785     
00786     return OPERATOR_FINISHED;
00787 }
00788 
00789 static int modifier_remove_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
00790 {
00791     if (edit_modifier_invoke_properties(C, op))
00792         return modifier_remove_exec(C, op);
00793     else
00794         return OPERATOR_CANCELLED;
00795 }
00796 
00797 void OBJECT_OT_modifier_remove(wmOperatorType *ot)
00798 {
00799     ot->name= "Remove Modifier";
00800     ot->description= "Remove a modifier from the active object";
00801     ot->idname= "OBJECT_OT_modifier_remove";
00802 
00803     ot->invoke= modifier_remove_invoke;
00804     ot->exec= modifier_remove_exec;
00805     ot->poll= edit_modifier_poll;
00806     
00807     /* flags */
00808     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00809     edit_modifier_properties(ot);
00810 }
00811 
00812 /************************ move up modifier operator *********************/
00813 
00814 static int modifier_move_up_exec(bContext *C, wmOperator *op)
00815 {
00816     Object *ob = ED_object_active_context(C);
00817     ModifierData *md = edit_modifier_property_get(op, ob, 0);
00818 
00819     if(!ob || !md || !ED_object_modifier_move_up(op->reports, ob, md))
00820         return OPERATOR_CANCELLED;
00821 
00822     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00823     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
00824     
00825     return OPERATOR_FINISHED;
00826 }
00827 
00828 static int modifier_move_up_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
00829 {
00830     if (edit_modifier_invoke_properties(C, op))
00831         return modifier_move_up_exec(C, op);
00832     else
00833         return OPERATOR_CANCELLED;
00834 }
00835 
00836 void OBJECT_OT_modifier_move_up(wmOperatorType *ot)
00837 {
00838     ot->name= "Move Up Modifier";
00839     ot->description= "Move modifier up in the stack";
00840     ot->idname= "OBJECT_OT_modifier_move_up";
00841 
00842     ot->invoke= modifier_move_up_invoke;
00843     ot->exec= modifier_move_up_exec;
00844     ot->poll= edit_modifier_poll;
00845     
00846     /* flags */
00847     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00848     edit_modifier_properties(ot);
00849 }
00850 
00851 /************************ move down modifier operator *********************/
00852 
00853 static int modifier_move_down_exec(bContext *C, wmOperator *op)
00854 {
00855     Object *ob = ED_object_active_context(C);
00856     ModifierData *md = edit_modifier_property_get(op, ob, 0);
00857 
00858     if(!ob || !md || !ED_object_modifier_move_down(op->reports, ob, md))
00859         return OPERATOR_CANCELLED;
00860 
00861     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00862     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
00863     
00864     return OPERATOR_FINISHED;
00865 }
00866 
00867 static int modifier_move_down_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
00868 {
00869     if (edit_modifier_invoke_properties(C, op))
00870         return modifier_move_down_exec(C, op);
00871     else
00872         return OPERATOR_CANCELLED;
00873 }
00874 
00875 void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
00876 {
00877     ot->name= "Move Down Modifier";
00878     ot->description= "Move modifier down in the stack";
00879     ot->idname= "OBJECT_OT_modifier_move_down";
00880 
00881     ot->invoke= modifier_move_down_invoke;
00882     ot->exec= modifier_move_down_exec;
00883     ot->poll= edit_modifier_poll;
00884     
00885     /* flags */
00886     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00887     edit_modifier_properties(ot);
00888 }
00889 
00890 /************************ apply modifier operator *********************/
00891 
00892 static int modifier_apply_exec(bContext *C, wmOperator *op)
00893 {
00894     Scene *scene= CTX_data_scene(C);
00895     Object *ob = ED_object_active_context(C);
00896     ModifierData *md = edit_modifier_property_get(op, ob, 0);
00897     int apply_as= RNA_enum_get(op->ptr, "apply_as");
00898     
00899     if(!ob || !md || !ED_object_modifier_apply(op->reports, scene, ob, md, apply_as)) {
00900         return OPERATOR_CANCELLED;
00901     }
00902 
00903     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00904     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
00905     
00906     return OPERATOR_FINISHED;
00907 }
00908 
00909 static int modifier_apply_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
00910 {
00911     if (edit_modifier_invoke_properties(C, op))
00912         return modifier_apply_exec(C, op);
00913     else
00914         return OPERATOR_CANCELLED;
00915 }
00916 
00917 static EnumPropertyItem modifier_apply_as_items[] = {
00918     {MODIFIER_APPLY_DATA, "DATA", 0, "Object Data", "Apply modifier to the object's data"},
00919     {MODIFIER_APPLY_SHAPE, "SHAPE", 0, "New Shape", "Apply deform-only modifier to a new shape on this object"},
00920     {0, NULL, 0, NULL, NULL}};
00921 
00922 void OBJECT_OT_modifier_apply(wmOperatorType *ot)
00923 {
00924     ot->name= "Apply Modifier";
00925     ot->description= "Apply modifier and remove from the stack";
00926     ot->idname= "OBJECT_OT_modifier_apply";
00927 
00928     ot->invoke= modifier_apply_invoke;
00929     ot->exec= modifier_apply_exec;
00930     ot->poll= edit_modifier_poll;
00931     
00932     /* flags */
00933     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00934     
00935     RNA_def_enum(ot->srna, "apply_as", modifier_apply_as_items, MODIFIER_APPLY_DATA, "Apply as", "How to apply the modifier to the geometry");
00936     edit_modifier_properties(ot);
00937 }
00938 
00939 /************************ convert modifier operator *********************/
00940 
00941 static int modifier_convert_exec(bContext *C, wmOperator *op)
00942 {
00943     Main *bmain= CTX_data_main(C);
00944     Scene *scene= CTX_data_scene(C);
00945     Object *ob = ED_object_active_context(C);
00946     ModifierData *md = edit_modifier_property_get(op, ob, 0);
00947     
00948     if(!ob || !md || !ED_object_modifier_convert(op->reports, bmain, scene, ob, md))
00949         return OPERATOR_CANCELLED;
00950 
00951     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00952     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
00953     
00954     return OPERATOR_FINISHED;
00955 }
00956 
00957 static int modifier_convert_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
00958 {
00959     if (edit_modifier_invoke_properties(C, op))
00960         return modifier_convert_exec(C, op);
00961     else
00962         return OPERATOR_CANCELLED;
00963 }
00964 
00965 void OBJECT_OT_modifier_convert(wmOperatorType *ot)
00966 {
00967     ot->name= "Convert Modifier";
00968     ot->description= "Convert particles to a mesh object";
00969     ot->idname= "OBJECT_OT_modifier_convert";
00970 
00971     ot->invoke= modifier_convert_invoke;
00972     ot->exec= modifier_convert_exec;
00973     ot->poll= edit_modifier_poll;
00974     
00975     /* flags */
00976     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00977     edit_modifier_properties(ot);
00978 }
00979 
00980 /************************ copy modifier operator *********************/
00981 
00982 static int modifier_copy_exec(bContext *C, wmOperator *op)
00983 {
00984     Object *ob = ED_object_active_context(C);
00985     ModifierData *md = edit_modifier_property_get(op, ob, 0);
00986 
00987     if(!ob || !md || !ED_object_modifier_copy(op->reports, ob, md))
00988         return OPERATOR_CANCELLED;
00989 
00990     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00991     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
00992     
00993     return OPERATOR_FINISHED;
00994 }
00995 
00996 static int modifier_copy_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
00997 {
00998     if (edit_modifier_invoke_properties(C, op))
00999         return modifier_copy_exec(C, op);
01000     else
01001         return OPERATOR_CANCELLED;
01002 }
01003 
01004 void OBJECT_OT_modifier_copy(wmOperatorType *ot)
01005 {
01006     ot->name= "Copy Modifier";
01007     ot->description= "Duplicate modifier at the same position in the stack";
01008     ot->idname= "OBJECT_OT_modifier_copy";
01009 
01010     ot->invoke= modifier_copy_invoke;
01011     ot->exec= modifier_copy_exec;
01012     ot->poll= edit_modifier_poll;
01013     
01014     /* flags */
01015     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01016     edit_modifier_properties(ot);
01017 }
01018 
01019 /************* multires delete higher levels operator ****************/
01020 
01021 static int multires_poll(bContext *C)
01022 {
01023     return edit_modifier_poll_generic(C, &RNA_MultiresModifier, (1<<OB_MESH));
01024 }
01025 
01026 static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op)
01027 {
01028     Object *ob = ED_object_active_context(C);
01029     MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
01030     
01031     if (!mmd)
01032         return OPERATOR_CANCELLED;
01033     
01034     multiresModifier_del_levels(mmd, ob, 1);
01035     
01036     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
01037     
01038     return OPERATOR_FINISHED;
01039 }
01040 
01041 static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
01042 {
01043     if (edit_modifier_invoke_properties(C, op))
01044         return multires_higher_levels_delete_exec(C, op);
01045     else
01046         return OPERATOR_CANCELLED;
01047 }
01048 
01049 void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot)
01050 {
01051     ot->name= "Delete Higher Levels";
01052     ot->description= "Deletes the higher resolution mesh, potential loss of detail";
01053     ot->idname= "OBJECT_OT_multires_higher_levels_delete";
01054 
01055     ot->poll= multires_poll;
01056     ot->invoke= multires_higher_levels_delete_invoke;
01057     ot->exec= multires_higher_levels_delete_exec;
01058     
01059     /* flags */
01060     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01061     edit_modifier_properties(ot);
01062 }
01063 
01064 /****************** multires subdivide operator *********************/
01065 
01066 static int multires_subdivide_exec(bContext *C, wmOperator *op)
01067 {
01068     Object *ob = ED_object_active_context(C);
01069     MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
01070     
01071     if (!mmd)
01072         return OPERATOR_CANCELLED;
01073     
01074     multiresModifier_subdivide(mmd, ob, 0, mmd->simple);
01075 
01076     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
01077     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
01078     
01079     return OPERATOR_FINISHED;
01080 }
01081 
01082 static int multires_subdivide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
01083 {
01084     if (edit_modifier_invoke_properties(C, op))
01085         return multires_subdivide_exec(C, op);
01086     else
01087         return OPERATOR_CANCELLED;
01088 }
01089 
01090 void OBJECT_OT_multires_subdivide(wmOperatorType *ot)
01091 {
01092     ot->name= "Multires Subdivide";
01093     ot->description= "Add a new level of subdivision";
01094     ot->idname= "OBJECT_OT_multires_subdivide";
01095 
01096     ot->poll= multires_poll;
01097     ot->invoke= multires_subdivide_invoke;
01098     ot->exec= multires_subdivide_exec;
01099     
01100     /* flags */
01101     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01102     edit_modifier_properties(ot);
01103 }
01104 
01105 /****************** multires reshape operator *********************/
01106 
01107 static int multires_reshape_exec(bContext *C, wmOperator *op)
01108 {
01109     Object *ob= ED_object_active_context(C), *secondob= NULL;
01110     Scene *scene= CTX_data_scene(C);
01111     MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
01112 
01113     if (!mmd)
01114         return OPERATOR_CANCELLED;
01115 
01116     if(mmd->lvl==0) {
01117         BKE_report(op->reports, RPT_ERROR, "Reshape can work only with higher levels of subdivisions");
01118         return OPERATOR_CANCELLED;
01119     }
01120 
01121     CTX_DATA_BEGIN(C, Object*, selob, selected_editable_objects) {
01122         if(selob->type == OB_MESH && selob != ob) {
01123             secondob= selob;
01124             break;
01125         }
01126     }
01127     CTX_DATA_END;
01128 
01129     if(!secondob) {
01130         BKE_report(op->reports, RPT_ERROR, "Second selected mesh object require to copy shape from");
01131         return OPERATOR_CANCELLED;
01132     }
01133 
01134     if(!multiresModifier_reshape(scene, mmd, ob, secondob)) {
01135         BKE_report(op->reports, RPT_ERROR, "Objects do not have the same number of vertices");
01136         return OPERATOR_CANCELLED;
01137     }
01138 
01139     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
01140     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
01141 
01142     return OPERATOR_FINISHED;
01143 }
01144 
01145 static int multires_reshape_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
01146 {
01147     if (edit_modifier_invoke_properties(C, op))
01148         return multires_reshape_exec(C, op);
01149     else
01150         return OPERATOR_CANCELLED;
01151 }
01152 
01153 void OBJECT_OT_multires_reshape(wmOperatorType *ot)
01154 {
01155     ot->name= "Multires Reshape";
01156     ot->description= "Copy vertex coordinates from other object";
01157     ot->idname= "OBJECT_OT_multires_reshape";
01158 
01159     ot->poll= multires_poll;
01160     ot->invoke= multires_reshape_invoke;
01161     ot->exec= multires_reshape_exec;
01162     
01163     /* flags */
01164     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01165     edit_modifier_properties(ot);
01166 }
01167 
01168 /****************** multires save external operator *********************/
01169 
01170 static int multires_external_save_exec(bContext *C, wmOperator *op)
01171 {
01172     Object *ob = ED_object_active_context(C);
01173     Mesh *me= (ob)? ob->data: op->customdata;
01174     char path[FILE_MAX];
01175     int relative= RNA_boolean_get(op->ptr, "relative_path");
01176 
01177     if(!me)
01178         return OPERATOR_CANCELLED;
01179 
01180     if(CustomData_external_test(&me->fdata, CD_MDISPS))
01181         return OPERATOR_CANCELLED;
01182     
01183     RNA_string_get(op->ptr, "filepath", path);
01184 
01185     if(relative)
01186         BLI_path_rel(path, G.main->name);
01187 
01188     CustomData_external_add(&me->fdata, &me->id, CD_MDISPS, me->totface, path);
01189     CustomData_external_write(&me->fdata, &me->id, CD_MASK_MESH, me->totface, 0);
01190     
01191     return OPERATOR_FINISHED;
01192 }
01193 
01194 static int multires_external_save_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
01195 {
01196     Object *ob = ED_object_active_context(C);
01197     MultiresModifierData *mmd;
01198     Mesh *me= ob->data;
01199     char path[FILE_MAX];
01200 
01201     if (!edit_modifier_invoke_properties(C, op))
01202         return OPERATOR_CANCELLED;
01203     
01204     mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
01205     
01206     if (!mmd)
01207         return OPERATOR_CANCELLED;
01208     
01209     if(CustomData_external_test(&me->fdata, CD_MDISPS))
01210         return OPERATOR_CANCELLED;
01211 
01212     if(RNA_struct_property_is_set(op->ptr, "filepath"))
01213         return multires_external_save_exec(C, op);
01214     
01215     op->customdata= me;
01216 
01217     BLI_snprintf(path, sizeof(path), "//%s.btx", me->id.name+2);
01218     RNA_string_set(op->ptr, "filepath", path);
01219     
01220     WM_event_add_fileselect(C, op);
01221 
01222     return OPERATOR_RUNNING_MODAL;
01223 }
01224 
01225 void OBJECT_OT_multires_external_save(wmOperatorType *ot)
01226 {
01227     ot->name= "Multires Save External";
01228     ot->description= "Save displacements to an external file";
01229     ot->idname= "OBJECT_OT_multires_external_save";
01230 
01231     // XXX modifier no longer in context after file browser .. ot->poll= multires_poll;
01232     ot->exec= multires_external_save_exec;
01233     ot->invoke= multires_external_save_invoke;
01234     ot->poll= multires_poll;
01235     
01236     /* flags */
01237     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01238 
01239     WM_operator_properties_filesel(ot, FOLDERFILE|BTXFILE, FILE_SPECIAL, FILE_SAVE, WM_FILESEL_FILEPATH|WM_FILESEL_RELPATH);
01240     edit_modifier_properties(ot);
01241 }
01242 
01243 /****************** multires pack operator *********************/
01244 
01245 static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op))
01246 {
01247     Object *ob = ED_object_active_context(C);
01248     Mesh *me= ob->data;
01249 
01250     if(!CustomData_external_test(&me->fdata, CD_MDISPS))
01251         return OPERATOR_CANCELLED;
01252 
01253     // XXX don't remove..
01254     CustomData_external_remove(&me->fdata, &me->id, CD_MDISPS, me->totface);
01255     
01256     return OPERATOR_FINISHED;
01257 }
01258 
01259 void OBJECT_OT_multires_external_pack(wmOperatorType *ot)
01260 {
01261     ot->name= "Multires Pack External";
01262     ot->description= "Pack displacements from an external file";
01263     ot->idname= "OBJECT_OT_multires_external_pack";
01264 
01265     ot->poll= multires_poll;
01266     ot->exec= multires_external_pack_exec;
01267     
01268     /* flags */
01269     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01270 }
01271 
01272 /********************* multires apply base ***********************/
01273 static int multires_base_apply_exec(bContext *C, wmOperator *op)
01274 {
01275     Object *ob = ED_object_active_context(C);
01276     MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get(op, ob, eModifierType_Multires);
01277     
01278     if (!mmd)
01279         return OPERATOR_CANCELLED;
01280     
01281     multiresModifier_base_apply(mmd, ob);
01282 
01283     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
01284     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
01285     
01286     return OPERATOR_FINISHED;
01287 }
01288 
01289 static int multires_base_apply_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
01290 {
01291     if (edit_modifier_invoke_properties(C, op))
01292         return multires_base_apply_exec(C, op);
01293     else
01294         return OPERATOR_CANCELLED;
01295 }
01296 
01297 
01298 void OBJECT_OT_multires_base_apply(wmOperatorType *ot)
01299 {
01300     ot->name= "Multires Apply Base";
01301     ot->description= "Modify the base mesh to conform to the displaced mesh";
01302     ot->idname= "OBJECT_OT_multires_base_apply";
01303 
01304     ot->poll= multires_poll;
01305     ot->invoke= multires_base_apply_invoke;
01306     ot->exec= multires_base_apply_exec;
01307     
01308     /* flags */
01309     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01310     edit_modifier_properties(ot);
01311 }
01312 
01313 
01314 /************************ mdef bind operator *********************/
01315 
01316 static int meshdeform_poll(bContext *C)
01317 {
01318     return edit_modifier_poll_generic(C, &RNA_MeshDeformModifier, (1<<OB_MESH));
01319 }
01320 
01321 static int meshdeform_bind_exec(bContext *C, wmOperator *op)
01322 {
01323     Scene *scene= CTX_data_scene(C);
01324     Object *ob = ED_object_active_context(C);
01325     MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_MeshDeform);
01326     
01327     if (!mmd)
01328         return OPERATOR_CANCELLED;
01329 
01330     if(mmd->bindcagecos) {
01331         MEM_freeN(mmd->bindcagecos);
01332         if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
01333         if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
01334         if(mmd->bindinfluences) MEM_freeN(mmd->bindinfluences);
01335         if(mmd->bindoffsets) MEM_freeN(mmd->bindoffsets);
01336         if(mmd->dynverts) MEM_freeN(mmd->dynverts);
01337         if(mmd->bindweights) MEM_freeN(mmd->bindweights); /* deprecated */
01338         if(mmd->bindcos) MEM_freeN(mmd->bindcos); /* deprecated */
01339 
01340         mmd->bindcagecos= NULL;
01341         mmd->dyngrid= NULL;
01342         mmd->dyninfluences= NULL;
01343         mmd->bindoffsets= NULL;
01344         mmd->dynverts= NULL;
01345         mmd->bindweights= NULL; /* deprecated */
01346         mmd->bindcos= NULL; /* deprecated */
01347         mmd->totvert= 0;
01348         mmd->totcagevert= 0;
01349         mmd->totinfluence= 0;
01350         
01351         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
01352         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
01353     }
01354     else {
01355         DerivedMesh *dm;
01356         int mode= mmd->modifier.mode;
01357 
01358         /* force modifier to run, it will call binding routine */
01359         mmd->bindfunc= mesh_deform_bind;
01360         mmd->modifier.mode |= eModifierMode_Realtime;
01361 
01362         if(ob->type == OB_MESH) {
01363             dm= mesh_create_derived_view(scene, ob, 0);
01364             dm->release(dm);
01365         }
01366         else if(ob->type == OB_LATTICE) {
01367             lattice_calc_modifiers(scene, ob);
01368         }
01369         else if(ob->type==OB_MBALL) {
01370             makeDispListMBall(scene, ob);
01371         }
01372         else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
01373             makeDispListCurveTypes(scene, ob, 0);
01374         }
01375 
01376         mmd->bindfunc= NULL;
01377         mmd->modifier.mode= mode;
01378     }
01379     
01380     return OPERATOR_FINISHED;
01381 }
01382 
01383 static int meshdeform_bind_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
01384 {
01385     if (edit_modifier_invoke_properties(C, op))
01386         return meshdeform_bind_exec(C, op);
01387     else 
01388         return OPERATOR_CANCELLED;
01389 }
01390 
01391 void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
01392 {
01393     /* identifiers */
01394     ot->name= "Mesh Deform Bind";
01395     ot->description = "Bind mesh to cage in mesh deform modifier";
01396     ot->idname= "OBJECT_OT_meshdeform_bind";
01397     
01398     /* api callbacks */
01399     ot->poll= meshdeform_poll;
01400     ot->invoke= meshdeform_bind_invoke;
01401     ot->exec= meshdeform_bind_exec;
01402     
01403     /* flags */
01404     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01405     edit_modifier_properties(ot);
01406 }
01407 
01408 /****************** explode refresh operator *********************/
01409 
01410 static int explode_poll(bContext *C)
01411 {
01412     return edit_modifier_poll_generic(C, &RNA_ExplodeModifier, 0);
01413 }
01414 
01415 static int explode_refresh_exec(bContext *C, wmOperator *op)
01416 {
01417     Object *ob = ED_object_active_context(C);
01418     ExplodeModifierData *emd = (ExplodeModifierData *)edit_modifier_property_get(op, ob, eModifierType_Explode);
01419     
01420     if (!emd)
01421         return OPERATOR_CANCELLED;
01422 
01423     emd->flag |= eExplodeFlag_CalcFaces;
01424 
01425     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
01426     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
01427     
01428     return OPERATOR_FINISHED;
01429 }
01430 
01431 static int explode_refresh_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
01432 {
01433     if (edit_modifier_invoke_properties(C, op))
01434         return explode_refresh_exec(C, op);
01435     else
01436         return OPERATOR_CANCELLED;
01437 }
01438 
01439 
01440 void OBJECT_OT_explode_refresh(wmOperatorType *ot)
01441 {
01442     ot->name= "Explode Refresh";
01443     ot->description= "Refresh data in the Explode modifier";
01444     ot->idname= "OBJECT_OT_explode_refresh";
01445 
01446     ot->poll= explode_poll;
01447     ot->invoke= explode_refresh_invoke;
01448     ot->exec= explode_refresh_exec;
01449     
01450     /* flags */
01451     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01452     edit_modifier_properties(ot);
01453 }
01454 
01455 
01456 /****************** ocean bake operator *********************/
01457 
01458 static int ocean_bake_poll(bContext *C)
01459 {
01460     return edit_modifier_poll_generic(C, &RNA_OceanModifier, 0);
01461 }
01462 
01463 /* copied from init_ocean_modifier, MOD_ocean.c */
01464 static void init_ocean_modifier_bake(struct Ocean *oc, struct OceanModifierData *omd)
01465 {
01466     int do_heightfield, do_chop, do_normals, do_jacobian;
01467     
01468     if (!omd || !oc) return; 
01469     
01470     do_heightfield = TRUE;
01471     do_chop = (omd->chop_amount > 0);
01472     do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS);
01473     do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
01474     
01475     BKE_init_ocean(oc, omd->resolution*omd->resolution, omd->resolution*omd->resolution, omd->spatial_size, omd->spatial_size, 
01476                    omd->wind_velocity, omd->smallest_wave, 1.0, omd->wave_direction, omd->damp, omd->wave_alignment, 
01477                    omd->depth, omd->time,
01478                    do_heightfield, do_chop, do_normals, do_jacobian,
01479                    omd->seed);
01480 }
01481 
01482 typedef struct OceanBakeJob {
01483     /* from wmJob */
01484     void *owner;
01485     short *stop, *do_update;
01486     float *progress;
01487     int current_frame;
01488     struct OceanCache *och;
01489     struct Ocean *ocean;
01490     struct OceanModifierData *omd;
01491 } OceanBakeJob;
01492 
01493 static void oceanbake_free(void *customdata)
01494 {
01495     OceanBakeJob *oj= customdata;
01496     MEM_freeN(oj);
01497 }
01498 
01499 /* called by oceanbake, only to check job 'stop' value */
01500 static int oceanbake_breakjob(void *UNUSED(customdata))
01501 {
01502     //OceanBakeJob *ob= (OceanBakeJob *)customdata;
01503     //return *(ob->stop);
01504     
01505     /* this is not nice yet, need to make the jobs list template better 
01506      * for identifying/acting upon various different jobs */
01507     /* but for now we'll reuse the render break... */
01508     return (G.afbreek);
01509 }
01510 
01511 /* called by oceanbake, wmJob sends notifier */
01512 static void oceanbake_update(void *customdata, float progress, int *cancel)
01513 {
01514     OceanBakeJob *oj= customdata;
01515     
01516     if (oceanbake_breakjob(oj))
01517         *cancel = 1;
01518     
01519     *(oj->do_update)= 1;
01520     *(oj->progress)= progress;
01521 }
01522 
01523 static void oceanbake_startjob(void *customdata, short *stop, short *do_update, float *progress)
01524 {
01525     OceanBakeJob *oj= customdata;
01526     
01527     oj->stop= stop;
01528     oj->do_update = do_update;
01529     oj->progress = progress;
01530     
01531     G.afbreek= 0;   /* XXX shared with render - replace with job 'stop' switch */
01532     
01533     BKE_bake_ocean(oj->ocean, oj->och, oceanbake_update, (void *)oj);
01534     
01535     *do_update= 1;
01536     *stop = 0;
01537 }
01538 
01539 static void oceanbake_endjob(void *customdata)
01540 {
01541     OceanBakeJob *oj= customdata;
01542     
01543     if (oj->ocean) {
01544         BKE_free_ocean(oj->ocean);
01545         oj->ocean = NULL;
01546     }
01547     
01548     oj->omd->oceancache = oj->och;
01549     oj->omd->cached = TRUE;
01550 }
01551 
01552 static int ocean_bake_exec(bContext *C, wmOperator *op)
01553 {
01554     Object *ob = ED_object_active_context(C);
01555     OceanModifierData *omd = (OceanModifierData *)edit_modifier_property_get(op, ob, eModifierType_Ocean);
01556     Scene *scene = CTX_data_scene(C);
01557     OceanCache *och;
01558     struct Ocean *ocean;
01559     int f, cfra, i=0;
01560     int free= RNA_boolean_get(op->ptr, "free");
01561     
01562     wmJob *steve;
01563     OceanBakeJob *oj;
01564     
01565     if (!omd)
01566         return OPERATOR_CANCELLED;
01567     
01568     if (free) {
01569         omd->refresh |= MOD_OCEAN_REFRESH_CLEAR_CACHE;
01570         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
01571         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
01572         return OPERATOR_FINISHED;
01573     }
01574 
01575     och = BKE_init_ocean_cache(omd->cachepath, modifier_path_relbase(ob),
01576                                omd->bakestart, omd->bakeend, omd->wave_scale,
01577                                omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
01578     
01579     och->time = MEM_mallocN(och->duration*sizeof(float), "foam bake time");
01580     
01581     cfra = scene->r.cfra;
01582     
01583     /* precalculate time variable before baking */
01584     for (f=omd->bakestart; f<=omd->bakeend; f++) {
01585         /* from physics_fluid.c:
01586          
01587          * XXX: This can't be used due to an anim sys optimisation that ignores recalc object animation,
01588          * leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ )
01589          * --> BKE_animsys_evaluate_all_animation(G.main, eval_time);
01590          * This doesn't work with drivers:
01591          * --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL);
01592          */
01593         
01594         /* Modifying the global scene isn't nice, but we can do it in 
01595          * this part of the process before a threaded job is created */
01596         
01597         //scene->r.cfra = f;
01598         //ED_update_for_newframe(CTX_data_main(C), scene, CTX_wm_screen(C), 1);
01599         
01600         /* ok, this doesn't work with drivers, but is way faster. 
01601          * let's use this for now and hope nobody wants to drive the time value... */
01602         BKE_animsys_evaluate_animdata(scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM);
01603         
01604         och->time[i] = omd->time;
01605         i++;
01606     }
01607     
01608     /* make a copy of ocean to use for baking - threadsafety */
01609     ocean = BKE_add_ocean();
01610     init_ocean_modifier_bake(ocean, omd);
01611     
01612     /*
01613      BKE_bake_ocean(ocean, och);
01614     
01615     omd->oceancache = och;
01616     omd->cached = TRUE;
01617     
01618     scene->r.cfra = cfra;
01619     
01620     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
01621     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
01622     */
01623     
01624     /* job stuff */
01625     
01626     scene->r.cfra = cfra;
01627     
01628     /* setup job */
01629     steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Ocean Simulation", WM_JOB_PROGRESS);
01630     oj= MEM_callocN(sizeof(OceanBakeJob), "ocean bake job");
01631     oj->ocean = ocean;
01632     oj->och = och;
01633     oj->omd = omd;
01634     
01635     WM_jobs_customdata(steve, oj, oceanbake_free);
01636     WM_jobs_timer(steve, 0.1, NC_OBJECT|ND_MODIFIER, NC_OBJECT|ND_MODIFIER);
01637     WM_jobs_callbacks(steve, oceanbake_startjob, NULL, NULL, oceanbake_endjob);
01638     
01639     WM_jobs_start(CTX_wm_manager(C), steve);
01640     
01641     
01642     
01643     return OPERATOR_FINISHED;
01644 }
01645 
01646 static int ocean_bake_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
01647 {
01648     if (edit_modifier_invoke_properties(C, op))
01649         return ocean_bake_exec(C, op);
01650     else
01651         return OPERATOR_CANCELLED;
01652 }
01653 
01654 
01655 void OBJECT_OT_ocean_bake(wmOperatorType *ot)
01656 {
01657     ot->name= "Bake Ocean";
01658     ot->description= "Bake an image sequence of ocean data";
01659     ot->idname= "OBJECT_OT_ocean_bake";
01660     
01661     ot->poll= ocean_bake_poll;
01662     ot->invoke= ocean_bake_invoke;
01663     ot->exec= ocean_bake_exec;
01664     
01665     /* flags */
01666     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01667     edit_modifier_properties(ot);
01668     
01669     RNA_def_boolean(ot->srna, "free", FALSE, "Free", "Free the bake, rather than generating it");
01670 }
01671