Cleanup: use const for typeinfo
[blender-staging.git] / source / blender / blenkernel / intern / 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) 2005 by the Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Daniel Dunbar
22  *                 Ton Roosendaal,
23  *                 Ben Batt,
24  *                 Brecht Van Lommel,
25  *                 Campbell Barton
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  *
29  * Modifier stack implementation.
30  *
31  * BKE_modifier.h contains the function prototypes for this file.
32  *
33  */
34
35 /** \file blender/blenkernel/intern/modifier.c
36  *  \ingroup bke
37  */
38
39 #include <stdlib.h>
40 #include <stddef.h>
41 #include <string.h>
42 #include <stdarg.h>
43 #include <math.h>
44 #include <float.h>
45
46 #include "MEM_guardedalloc.h"
47
48 #include "DNA_armature_types.h"
49 #include "DNA_object_types.h"
50
51 #include "BLI_utildefines.h"
52 #include "BLI_path_util.h"
53 #include "BLI_listbase.h"
54 #include "BLI_linklist.h"
55 #include "BLI_string.h"
56
57 #include "BLF_translation.h"
58
59 #include "BKE_appdir.h"
60 #include "BKE_key.h"
61 #include "BKE_multires.h"
62 #include "BKE_DerivedMesh.h"
63
64 /* may move these, only for modifier_path_relbase */
65 #include "BKE_global.h" /* ugh, G.main->name only */
66 #include "BKE_main.h"
67 /* end */
68
69 #include "MOD_modifiertypes.h"
70
71 static ModifierTypeInfo *modifier_types[NUM_MODIFIER_TYPES] = {NULL};
72 static VirtualModifierData virtualModifierCommonData;
73
74 void BKE_modifier_init(void)
75 {
76         ModifierData *md;
77
78         /* Initialize modifier types */
79         modifier_type_init(modifier_types); /* MOD_utils.c */
80
81         /* Initialize global cmmon storage used for virtual modifier list */
82         md = modifier_new(eModifierType_Armature);
83         virtualModifierCommonData.amd = *((ArmatureModifierData *) md);
84         modifier_free(md);
85
86         md = modifier_new(eModifierType_Curve);
87         virtualModifierCommonData.cmd = *((CurveModifierData *) md);
88         modifier_free(md);
89
90         md = modifier_new(eModifierType_Lattice);
91         virtualModifierCommonData.lmd = *((LatticeModifierData *) md);
92         modifier_free(md);
93
94         md = modifier_new(eModifierType_ShapeKey);
95         virtualModifierCommonData.smd = *((ShapeKeyModifierData *) md);
96         modifier_free(md);
97
98         virtualModifierCommonData.amd.modifier.mode |= eModifierMode_Virtual;
99         virtualModifierCommonData.cmd.modifier.mode |= eModifierMode_Virtual;
100         virtualModifierCommonData.lmd.modifier.mode |= eModifierMode_Virtual;
101         virtualModifierCommonData.smd.modifier.mode |= eModifierMode_Virtual;
102 }
103
104 const ModifierTypeInfo *modifierType_getInfo(ModifierType type)
105 {
106         /* type unsigned, no need to check < 0 */
107         if (type < NUM_MODIFIER_TYPES && modifier_types[type]->name[0] != '\0') {
108                 return modifier_types[type];
109         }
110         else {
111                 return NULL;
112         }
113 }
114
115 /***/
116
117 ModifierData *modifier_new(int type)
118 {
119         const ModifierTypeInfo *mti = modifierType_getInfo(type);
120         ModifierData *md = MEM_callocN(mti->structSize, mti->structName);
121         
122         /* note, this name must be made unique later */
123         BLI_strncpy(md->name, DATA_(mti->name), sizeof(md->name));
124
125         md->type = type;
126         md->mode = eModifierMode_Realtime | eModifierMode_Render | eModifierMode_Expanded;
127
128         if (mti->flags & eModifierTypeFlag_EnableInEditmode)
129                 md->mode |= eModifierMode_Editmode;
130
131         if (mti->initData) mti->initData(md);
132
133         return md;
134 }
135
136 void modifier_free(ModifierData *md) 
137 {
138         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
139
140         if (mti->freeData) mti->freeData(md);
141         if (md->error) MEM_freeN(md->error);
142
143         MEM_freeN(md);
144 }
145
146 bool modifier_unique_name(ListBase *modifiers, ModifierData *md)
147 {
148         if (modifiers && md) {
149                 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
150
151                 return BLI_uniquename(modifiers, md, DATA_(mti->name), '.', offsetof(ModifierData, name), sizeof(md->name));
152         }
153         return false;
154 }
155
156 bool modifier_dependsOnTime(ModifierData *md)
157 {
158         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
159
160         return mti->dependsOnTime && mti->dependsOnTime(md);
161 }
162
163 bool modifier_supportsMapping(ModifierData *md)
164 {
165         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
166
167         return (mti->type == eModifierTypeType_OnlyDeform ||
168                 (mti->flags & eModifierTypeFlag_SupportsMapping));
169 }
170
171 bool modifier_isPreview(ModifierData *md)
172 {
173         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
174
175         /* Constructive modifiers are highly likely to also modify data like vgroups or vcol! */
176         if (!((mti->flags & eModifierTypeFlag_UsesPreview) || (mti->type == eModifierTypeType_Constructive))) {
177                 return false;
178         }
179
180         if (md->mode & eModifierMode_Realtime) {
181                 return true;
182         }
183
184         return false;
185 }
186
187 ModifierData *modifiers_findByType(Object *ob, ModifierType type)
188 {
189         ModifierData *md = ob->modifiers.first;
190
191         for (; md; md = md->next)
192                 if (md->type == type)
193                         break;
194
195         return md;
196 }
197
198 ModifierData *modifiers_findByName(Object *ob, const char *name)
199 {
200         return BLI_findstring(&(ob->modifiers), name, offsetof(ModifierData, name));
201 }
202
203 void modifiers_clearErrors(Object *ob)
204 {
205         ModifierData *md = ob->modifiers.first;
206         /* int qRedraw = 0; */
207
208         for (; md; md = md->next) {
209                 if (md->error) {
210                         MEM_freeN(md->error);
211                         md->error = NULL;
212
213                         /* qRedraw = 1; */
214                 }
215         }
216 }
217
218 void modifiers_foreachObjectLink(Object *ob, ObjectWalkFunc walk,
219                                  void *userData)
220 {
221         ModifierData *md = ob->modifiers.first;
222
223         for (; md; md = md->next) {
224                 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
225
226                 if (mti->foreachObjectLink)
227                         mti->foreachObjectLink(md, ob, walk, userData);
228         }
229 }
230
231 void modifiers_foreachIDLink(Object *ob, IDWalkFunc walk, void *userData)
232 {
233         ModifierData *md = ob->modifiers.first;
234
235         for (; md; md = md->next) {
236                 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
237
238                 if (mti->foreachIDLink) mti->foreachIDLink(md, ob, walk, userData);
239                 else if (mti->foreachObjectLink) {
240                         /* each Object can masquerade as an ID, so this should be OK */
241                         ObjectWalkFunc fp = (ObjectWalkFunc)walk;
242                         mti->foreachObjectLink(md, ob, fp, userData);
243                 }
244         }
245 }
246
247 void modifiers_foreachTexLink(Object *ob, TexWalkFunc walk, void *userData)
248 {
249         ModifierData *md = ob->modifiers.first;
250
251         for (; md; md = md->next) {
252                 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
253
254                 if (mti->foreachTexLink)
255                         mti->foreachTexLink(md, ob, walk, userData);
256         }
257 }
258
259 /* callback's can use this
260  * to avoid copying every member.
261  */
262 void modifier_copyData_generic(const ModifierData *md_src, ModifierData *md_dst)
263 {
264         const ModifierTypeInfo *mti = modifierType_getInfo(md_src->type);
265         const size_t data_size = sizeof(ModifierData);
266         const char *md_src_data = ((const char *)md_src) + data_size;
267         char       *md_dst_data =       ((char *)md_dst) + data_size;
268         BLI_assert(data_size <= (size_t)mti->structSize);
269         memcpy(md_dst_data, md_src_data, (size_t)mti->structSize - data_size);
270 }
271
272 void modifier_copyData(ModifierData *md, ModifierData *target)
273 {
274         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
275
276         target->mode = md->mode;
277
278         if (mti->copyData)
279                 mti->copyData(md, target);
280 }
281
282
283 bool modifier_supportsCage(struct Scene *scene, ModifierData *md)
284 {
285         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
286
287         md->scene = scene;
288
289         return ((!mti->isDisabled || !mti->isDisabled(md, 0)) &&
290                 (mti->flags & eModifierTypeFlag_SupportsEditmode) &&
291                 modifier_supportsMapping(md));
292 }
293
294 bool modifier_couldBeCage(struct Scene *scene, ModifierData *md)
295 {
296         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
297
298         md->scene = scene;
299
300         return ((md->mode & eModifierMode_Realtime) &&
301                 (md->mode & eModifierMode_Editmode) &&
302                 (!mti->isDisabled || !mti->isDisabled(md, 0)) &&
303                 modifier_supportsMapping(md));
304 }
305
306 bool modifier_isSameTopology(ModifierData *md)
307 {
308         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
309         return ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical);
310 }
311
312 bool modifier_isNonGeometrical(ModifierData *md)
313 {
314         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
315         return (mti->type == eModifierTypeType_NonGeometrical);
316 }
317
318 void modifier_setError(ModifierData *md, const char *_format, ...)
319 {
320         char buffer[512];
321         va_list ap;
322         const char *format = TIP_(_format);
323
324         va_start(ap, _format);
325         vsnprintf(buffer, sizeof(buffer), format, ap);
326         va_end(ap);
327         buffer[sizeof(buffer) - 1] = '\0';
328
329         if (md->error)
330                 MEM_freeN(md->error);
331
332         md->error = BLI_strdup(buffer);
333
334 }
335
336 /* used for buttons, to find out if the 'draw deformed in editmode' option is
337  * there
338  * 
339  * also used in transform_conversion.c, to detect CrazySpace [tm] (2nd arg
340  * then is NULL) 
341  * also used for some mesh tools to give warnings
342  */
343 int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *r_lastPossibleCageIndex, bool is_virtual)
344 {
345         VirtualModifierData virtualModifierData;
346         ModifierData *md = (is_virtual) ? modifiers_getVirtualModifierList(ob, &virtualModifierData) : ob->modifiers.first;
347         int i, cageIndex = -1;
348
349         if (r_lastPossibleCageIndex) {
350                 /* ensure the value is initialized */
351                 *r_lastPossibleCageIndex = -1;
352         }
353
354         /* Find the last modifier acting on the cage. */
355         for (i = 0; md; i++, md = md->next) {
356                 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
357                 bool supports_mapping;
358
359                 md->scene = scene;
360
361                 if (mti->isDisabled && mti->isDisabled(md, 0)) continue;
362                 if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) continue;
363                 if (md->mode & eModifierMode_DisableTemporary) continue;
364
365                 supports_mapping = modifier_supportsMapping(md);
366                 if (r_lastPossibleCageIndex && supports_mapping) {
367                         *r_lastPossibleCageIndex = i;
368                 }
369
370                 if (!(md->mode & eModifierMode_Realtime)) continue;
371                 if (!(md->mode & eModifierMode_Editmode)) continue;
372
373                 if (!supports_mapping)
374                         break;
375
376                 if (md->mode & eModifierMode_OnCage)
377                         cageIndex = i;
378         }
379
380         return cageIndex;
381 }
382
383
384 bool modifiers_isSoftbodyEnabled(Object *ob)
385 {
386         ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
387
388         return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
389 }
390
391 bool modifiers_isClothEnabled(Object *ob)
392 {
393         ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
394
395         return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
396 }
397
398 bool modifiers_isModifierEnabled(Object *ob, int modifierType)
399 {
400         ModifierData *md = modifiers_findByType(ob, modifierType);
401
402         return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
403 }
404
405 bool modifiers_isParticleEnabled(Object *ob)
406 {
407         ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleSystem);
408
409         return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
410 }
411
412 bool modifier_isEnabled(struct Scene *scene, ModifierData *md, int required_mode)
413 {
414         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
415
416         md->scene = scene;
417
418         if ((md->mode & required_mode) != required_mode) return false;
419         if (mti->isDisabled && mti->isDisabled(md, required_mode == eModifierMode_Render)) return false;
420         if (md->mode & eModifierMode_DisableTemporary) return false;
421         if ((required_mode & eModifierMode_Editmode) && !(mti->flags & eModifierTypeFlag_SupportsEditmode)) return false;
422         
423         return true;
424 }
425
426 CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, Object *ob, ModifierData *md,
427                                     CustomDataMask dataMask, int required_mode,
428                                     ModifierData *previewmd, CustomDataMask previewmask)
429 {
430         CDMaskLink *dataMasks = NULL;
431         CDMaskLink *curr, *prev;
432
433         /* build a list of modifier data requirements in reverse order */
434         for (; md; md = md->next) {
435                 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
436
437                 curr = MEM_callocN(sizeof(CDMaskLink), "CDMaskLink");
438                 
439                 if (modifier_isEnabled(scene, md, required_mode)) {
440                         if (mti->requiredDataMask)
441                                 curr->mask = mti->requiredDataMask(ob, md);
442
443                         if (previewmd == md) {
444                                 curr->mask |= previewmask;
445                         }
446                 }
447
448                 /* prepend new datamask */
449                 curr->next = dataMasks;
450                 dataMasks = curr;
451         }
452
453         /* build the list of required data masks - each mask in the list must
454          * include all elements of the masks that follow it
455          *
456          * note the list is currently in reverse order, so "masks that follow it"
457          * actually means "masks that precede it" at the moment
458          */
459         for (curr = dataMasks, prev = NULL; curr; prev = curr, curr = curr->next) {
460                 if (prev) {
461                         CustomDataMask prev_mask = prev->mask;
462                         CustomDataMask curr_mask = curr->mask;
463
464                         curr->mask = curr_mask | prev_mask;
465                 }
466                 else {
467                         CustomDataMask curr_mask = curr->mask;
468
469                         curr->mask = curr_mask | dataMask;
470                 }
471         }
472
473         /* reverse the list so it's in the correct order */
474         BLI_linklist_reverse((LinkNode **)&dataMasks);
475
476         return dataMasks;
477 }
478
479 ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, int required_mode)
480 {
481         ModifierData *tmp_md = NULL;
482
483         if ((required_mode & ~eModifierMode_Editmode) != eModifierMode_Realtime)
484                 return tmp_md;
485
486         /* Find the latest modifier in stack generating preview. */
487         for (; md; md = md->next) {
488                 if (modifier_isEnabled(scene, md, required_mode) && modifier_isPreview(md))
489                         tmp_md = md;
490         }
491         return tmp_md;
492 }
493
494 /* NOTE: This is to support old files from before Blender supported modifiers,
495  * in some cases versioning code updates these so for new files this will
496  * return an empty list. */
497 ModifierData *modifiers_getVirtualModifierList(Object *ob, VirtualModifierData *virtualModifierData)
498 {
499         ModifierData *md;
500
501         md = ob->modifiers.first;
502
503         *virtualModifierData = virtualModifierCommonData;
504
505         if (ob->parent) {
506                 if (ob->parent->type == OB_ARMATURE && ob->partype == PARSKEL) {
507                         virtualModifierData->amd.object = ob->parent;
508                         virtualModifierData->amd.modifier.next = md;
509                         virtualModifierData->amd.deformflag = ((bArmature *)(ob->parent->data))->deformflag;
510                         md = &virtualModifierData->amd.modifier;
511                 }
512                 else if (ob->parent->type == OB_CURVE && ob->partype == PARSKEL) {
513                         virtualModifierData->cmd.object = ob->parent;
514                         virtualModifierData->cmd.defaxis = ob->trackflag + 1;
515                         virtualModifierData->cmd.modifier.next = md;
516                         md = &virtualModifierData->cmd.modifier;
517                 }
518                 else if (ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) {
519                         virtualModifierData->lmd.object = ob->parent;
520                         virtualModifierData->lmd.modifier.next = md;
521                         md = &virtualModifierData->lmd.modifier;
522                 }
523         }
524
525         /* shape key modifier, not yet for curves */
526         if (ELEM(ob->type, OB_MESH, OB_LATTICE) && BKE_key_from_object(ob)) {
527                 if (ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE))
528                         virtualModifierData->smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage;
529                 else
530                         virtualModifierData->smd.modifier.mode &= ~eModifierMode_Editmode | eModifierMode_OnCage;
531
532                 virtualModifierData->smd.modifier.next = md;
533                 md = &virtualModifierData->smd.modifier;
534         }
535
536         return md;
537 }
538
539 /* Takes an object and returns its first selected armature, else just its armature
540  * This should work for multiple armatures per object
541  */
542 Object *modifiers_isDeformedByArmature(Object *ob)
543 {
544         VirtualModifierData virtualModifierData;
545         ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
546         ArmatureModifierData *amd = NULL;
547         
548         /* return the first selected armature, this lets us use multiple armatures */
549         for (; md; md = md->next) {
550                 if (md->type == eModifierType_Armature) {
551                         amd = (ArmatureModifierData *) md;
552                         if (amd->object && (amd->object->flag & SELECT))
553                                 return amd->object;
554                 }
555         }
556         
557         if (amd) /* if were still here then return the last armature */
558                 return amd->object;
559         
560         return NULL;
561 }
562
563 /* Takes an object and returns its first selected lattice, else just its lattice
564  * This should work for multiple lattices per object
565  */
566 Object *modifiers_isDeformedByLattice(Object *ob)
567 {
568         VirtualModifierData virtualModifierData;
569         ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
570         LatticeModifierData *lmd = NULL;
571         
572         /* return the first selected lattice, this lets us use multiple lattices */
573         for (; md; md = md->next) {
574                 if (md->type == eModifierType_Lattice) {
575                         lmd = (LatticeModifierData *) md;
576                         if (lmd->object && (lmd->object->flag & SELECT))
577                                 return lmd->object;
578                 }
579         }
580         
581         if (lmd) /* if were still here then return the last lattice */
582                 return lmd->object;
583         
584         return NULL;
585 }
586
587 /* Takes an object and returns its first selected curve, else just its curve
588  * This should work for multiple curves per object
589  */
590 Object *modifiers_isDeformedByCurve(Object *ob)
591 {
592         VirtualModifierData virtualModifierData;
593         ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
594         CurveModifierData *cmd = NULL;
595         
596         /* return the first selected curve, this lets us use multiple curves */
597         for (; md; md = md->next) {
598                 if (md->type == eModifierType_Curve) {
599                         cmd = (CurveModifierData *) md;
600                         if (cmd->object && (cmd->object->flag & SELECT))
601                                 return cmd->object;
602                 }
603         }
604         
605         if (cmd) /* if were still here then return the last curve */
606                 return cmd->object;
607         
608         return NULL;
609 }
610
611 bool modifiers_usesArmature(Object *ob, bArmature *arm)
612 {
613         VirtualModifierData virtualModifierData;
614         ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
615
616         for (; md; md = md->next) {
617                 if (md->type == eModifierType_Armature) {
618                         ArmatureModifierData *amd = (ArmatureModifierData *) md;
619                         if (amd->object && amd->object->data == arm)
620                                 return true;
621                 }
622         }
623
624         return false;
625 }
626
627 bool modifier_isCorrectableDeformed(ModifierData *md)
628 {
629         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
630         return (mti->deformMatricesEM != NULL);
631 }
632
633 bool modifiers_isCorrectableDeformed(struct Scene *scene, Object *ob)
634 {
635         VirtualModifierData virtualModifierData;
636         ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
637         int required_mode = eModifierMode_Realtime;
638
639         if (ob->mode == OB_MODE_EDIT)
640                 required_mode |= eModifierMode_Editmode;
641         
642         for (; md; md = md->next) {
643                 if (!modifier_isEnabled(scene, md, required_mode)) {
644                         /* pass */
645                 }
646                 else if (modifier_isCorrectableDeformed(md)) {
647                         return true;
648                 }
649         }
650         return false;
651 }
652
653 /* Check whether the given object has a modifier in its stack that uses WEIGHT_MCOL CD layer
654  * to preview something... Used by DynamicPaint and WeightVG currently. */
655 bool modifiers_isPreview(Object *ob)
656 {
657         ModifierData *md = ob->modifiers.first;
658
659         for (; md; md = md->next) {
660                 if (modifier_isPreview(md))
661                         return true;
662         }
663
664         return false;
665 }
666
667 void modifier_freeTemporaryData(ModifierData *md)
668 {
669         if (md->type == eModifierType_Armature) {
670                 ArmatureModifierData *amd = (ArmatureModifierData *)md;
671
672                 if (amd->prevCos) {
673                         MEM_freeN(amd->prevCos);
674                         amd->prevCos = NULL;
675                 }
676         }
677 }
678
679 /* ensure modifier correctness when changing ob->data */
680 void test_object_modifiers(Object *ob)
681 {
682         ModifierData *md;
683
684         /* just multires checked for now, since only multires
685          * modifies mesh data */
686
687         if (ob->type != OB_MESH) return;
688
689         for (md = ob->modifiers.first; md; md = md->next) {
690                 if (md->type == eModifierType_Multires) {
691                         MultiresModifierData *mmd = (MultiresModifierData *)md;
692
693                         multiresModifier_set_levels_from_disps(mmd, ob);
694                 }
695         }
696 }
697
698 /* where should this go?, it doesnt fit well anywhere :S - campbell */
699
700 /* elubie: changed this to default to the same dir as the render output
701  * to prevent saving to C:\ on Windows */
702
703 /* campbell: logic behind this...
704  *
705  * - if the ID is from a library, return library path
706  * - else if the file has been saved return the blend file path.
707  * - else if the file isn't saved and the ID isn't from a library, return the temp dir.
708  */
709 const char *modifier_path_relbase(Object *ob)
710 {
711         if (G.relbase_valid || ob->id.lib) {
712                 return ID_BLEND_PATH(G.main, &ob->id);
713         }
714         else {
715                 /* last resort, better then using "" which resolves to the current
716                  * working directory */
717                 return BKE_tempdir_session();
718         }
719 }
720
721 /* initializes the path with either */
722 void modifier_path_init(char *path, int path_maxlen, const char *name)
723 {
724         /* elubie: changed this to default to the same dir as the render output
725          * to prevent saving to C:\ on Windows */
726         BLI_join_dirfile(path, path_maxlen,
727                          G.relbase_valid ? "//" : BKE_tempdir_session(),
728                          name);
729 }
730
731
732 /* wrapper around ModifierTypeInfo.applyModifier that ensures valid normals */
733
734 struct DerivedMesh *modwrap_applyModifier(
735         ModifierData *md, Object *ob,
736         struct DerivedMesh *dm,
737         ModifierApplyFlag flag)
738 {
739         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
740         BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
741
742         if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
743                 DM_ensure_normals(dm);
744         }
745         return mti->applyModifier(md, ob, dm, flag);
746 }
747
748 struct DerivedMesh *modwrap_applyModifierEM(
749         ModifierData *md, Object *ob,
750         struct BMEditMesh *em,
751         DerivedMesh *dm,
752         ModifierApplyFlag flag)
753 {
754         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
755         BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
756
757         if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
758                 DM_ensure_normals(dm);
759         }
760         return mti->applyModifierEM(md, ob, em, dm, flag);
761 }
762
763 void modwrap_deformVerts(
764         ModifierData *md, Object *ob,
765         DerivedMesh *dm,
766         float (*vertexCos)[3], int numVerts,
767         ModifierApplyFlag flag)
768 {
769         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
770         BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
771
772         if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
773                 DM_ensure_normals(dm);
774         }
775         mti->deformVerts(md, ob, dm, vertexCos, numVerts, flag);
776 }
777
778 void modwrap_deformVertsEM(
779         ModifierData *md, Object *ob,
780         struct BMEditMesh *em, DerivedMesh *dm,
781         float (*vertexCos)[3], int numVerts)
782 {
783         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
784         BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
785
786         if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
787                 DM_ensure_normals(dm);
788         }
789         mti->deformVertsEM(md, ob, em, dm, vertexCos, numVerts);
790 }
791 /* end modifier callback wrappers */