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