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