Mesh Modifiers: refactor copying using a generic function
[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 *lastPossibleCageIndex_r, int virtual_)
341 {
342         VirtualModifierData virtualModifierData;
343         ModifierData *md = (virtual_) ? modifiers_getVirtualModifierList(ob, &virtualModifierData) : ob->modifiers.first;
344         int i, cageIndex = -1;
345
346         if (lastPossibleCageIndex_r) {
347                 /* ensure the value is initialized */
348                 *lastPossibleCageIndex_r = -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 (!(md->mode & eModifierMode_Realtime)) continue;
358                 if (!(md->mode & eModifierMode_Editmode)) continue;
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 (!modifier_supportsMapping(md))
364                         break;
365
366                 if (lastPossibleCageIndex_r) *lastPossibleCageIndex_r = i;
367                 if (md->mode & eModifierMode_OnCage)
368                         cageIndex = i;
369         }
370
371         return cageIndex;
372 }
373
374
375 bool modifiers_isSoftbodyEnabled(Object *ob)
376 {
377         ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
378
379         return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
380 }
381
382 bool modifiers_isClothEnabled(Object *ob)
383 {
384         ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
385
386         return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
387 }
388
389 bool modifiers_isModifierEnabled(Object *ob, int modifierType)
390 {
391         ModifierData *md = modifiers_findByType(ob, modifierType);
392
393         return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
394 }
395
396 bool modifiers_isParticleEnabled(Object *ob)
397 {
398         ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleSystem);
399
400         return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
401 }
402
403 bool modifier_isEnabled(struct Scene *scene, ModifierData *md, int required_mode)
404 {
405         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
406
407         md->scene = scene;
408
409         if ((md->mode & required_mode) != required_mode) return 0;
410         if (mti->isDisabled && mti->isDisabled(md, required_mode == eModifierMode_Render)) return 0;
411         if (md->mode & eModifierMode_DisableTemporary) return 0;
412         if (required_mode & eModifierMode_Editmode)
413                 if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) return 0;
414         
415         return 1;
416 }
417
418 CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, Object *ob, ModifierData *md,
419                                     CustomDataMask dataMask, int required_mode,
420                                     ModifierData *previewmd, CustomDataMask previewmask)
421 {
422         CDMaskLink *dataMasks = NULL;
423         CDMaskLink *curr, *prev;
424
425         /* build a list of modifier data requirements in reverse order */
426         for (; md; md = md->next) {
427                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
428
429                 curr = MEM_callocN(sizeof(CDMaskLink), "CDMaskLink");
430                 
431                 if (modifier_isEnabled(scene, md, required_mode)) {
432                         if (mti->requiredDataMask)
433                                 curr->mask = mti->requiredDataMask(ob, md);
434
435                         if (previewmd == md) {
436                                 curr->mask |= previewmask;
437                         }
438                 }
439
440                 /* prepend new datamask */
441                 curr->next = dataMasks;
442                 dataMasks = curr;
443         }
444
445         /* build the list of required data masks - each mask in the list must
446          * include all elements of the masks that follow it
447          *
448          * note the list is currently in reverse order, so "masks that follow it"
449          * actually means "masks that precede it" at the moment
450          */
451         for (curr = dataMasks, prev = NULL; curr; prev = curr, curr = curr->next) {
452                 if (prev) {
453                         CustomDataMask prev_mask = prev->mask;
454                         CustomDataMask curr_mask = curr->mask;
455
456                         curr->mask = curr_mask | prev_mask;
457                 }
458                 else {
459                         CustomDataMask curr_mask = curr->mask;
460
461                         curr->mask = curr_mask | dataMask;
462                 }
463         }
464
465         /* reverse the list so it's in the correct order */
466         BLI_linklist_reverse((LinkNode **)&dataMasks);
467
468         return dataMasks;
469 }
470
471 ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, int required_mode)
472 {
473         ModifierData *tmp_md = NULL;
474
475         if ((required_mode & ~eModifierMode_Editmode) != eModifierMode_Realtime)
476                 return tmp_md;
477
478         /* Find the latest modifier in stack generating preview. */
479         for (; md; md = md->next) {
480                 if (modifier_isEnabled(scene, md, required_mode) && modifier_isPreview(md))
481                         tmp_md = md;
482         }
483         return tmp_md;
484 }
485
486 /* NOTE: This is to support old files from before Blender supported modifiers,
487  * in some cases versioning code updates these so for new files this will
488  * return an empty list. */
489 ModifierData *modifiers_getVirtualModifierList(Object *ob, VirtualModifierData *virtualModifierData)
490 {
491         ModifierData *md;
492
493         md = ob->modifiers.first;
494
495         *virtualModifierData = virtualModifierCommonData;
496
497         if (ob->parent) {
498                 if (ob->parent->type == OB_ARMATURE && ob->partype == PARSKEL) {
499                         virtualModifierData->amd.object = ob->parent;
500                         virtualModifierData->amd.modifier.next = md;
501                         virtualModifierData->amd.deformflag = ((bArmature *)(ob->parent->data))->deformflag;
502                         md = &virtualModifierData->amd.modifier;
503                 }
504                 else if (ob->parent->type == OB_CURVE && ob->partype == PARSKEL) {
505                         virtualModifierData->cmd.object = ob->parent;
506                         virtualModifierData->cmd.defaxis = ob->trackflag + 1;
507                         virtualModifierData->cmd.modifier.next = md;
508                         md = &virtualModifierData->cmd.modifier;
509                 }
510                 else if (ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) {
511                         virtualModifierData->lmd.object = ob->parent;
512                         virtualModifierData->lmd.modifier.next = md;
513                         md = &virtualModifierData->lmd.modifier;
514                 }
515         }
516
517         /* shape key modifier, not yet for curves */
518         if (ELEM(ob->type, OB_MESH, OB_LATTICE) && BKE_key_from_object(ob)) {
519                 if (ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE))
520                         virtualModifierData->smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage;
521                 else
522                         virtualModifierData->smd.modifier.mode &= ~eModifierMode_Editmode | eModifierMode_OnCage;
523
524                 virtualModifierData->smd.modifier.next = md;
525                 md = &virtualModifierData->smd.modifier;
526         }
527
528         return md;
529 }
530
531 /* Takes an object and returns its first selected armature, else just its armature
532  * This should work for multiple armatures per object
533  */
534 Object *modifiers_isDeformedByArmature(Object *ob)
535 {
536         VirtualModifierData virtualModifierData;
537         ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
538         ArmatureModifierData *amd = NULL;
539         
540         /* return the first selected armature, this lets us use multiple armatures */
541         for (; md; md = md->next) {
542                 if (md->type == eModifierType_Armature) {
543                         amd = (ArmatureModifierData *) md;
544                         if (amd->object && (amd->object->flag & SELECT))
545                                 return amd->object;
546                 }
547         }
548         
549         if (amd) /* if were still here then return the last armature */
550                 return amd->object;
551         
552         return NULL;
553 }
554
555 /* Takes an object and returns its first selected lattice, else just its lattice
556  * This should work for multiple lattices per object
557  */
558 Object *modifiers_isDeformedByLattice(Object *ob)
559 {
560         VirtualModifierData virtualModifierData;
561         ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
562         LatticeModifierData *lmd = NULL;
563         
564         /* return the first selected lattice, this lets us use multiple lattices */
565         for (; md; md = md->next) {
566                 if (md->type == eModifierType_Lattice) {
567                         lmd = (LatticeModifierData *) md;
568                         if (lmd->object && (lmd->object->flag & SELECT))
569                                 return lmd->object;
570                 }
571         }
572         
573         if (lmd) /* if were still here then return the last lattice */
574                 return lmd->object;
575         
576         return NULL;
577 }
578
579 /* Takes an object and returns its first selected curve, else just its curve
580  * This should work for multiple curves per object
581  */
582 Object *modifiers_isDeformedByCurve(Object *ob)
583 {
584         VirtualModifierData virtualModifierData;
585         ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
586         CurveModifierData *cmd = NULL;
587         
588         /* return the first selected curve, this lets us use multiple curves */
589         for (; md; md = md->next) {
590                 if (md->type == eModifierType_Curve) {
591                         cmd = (CurveModifierData *) md;
592                         if (cmd->object && (cmd->object->flag & SELECT))
593                                 return cmd->object;
594                 }
595         }
596         
597         if (cmd) /* if were still here then return the last curve */
598                 return cmd->object;
599         
600         return NULL;
601 }
602
603 bool modifiers_usesArmature(Object *ob, bArmature *arm)
604 {
605         VirtualModifierData virtualModifierData;
606         ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
607
608         for (; md; md = md->next) {
609                 if (md->type == eModifierType_Armature) {
610                         ArmatureModifierData *amd = (ArmatureModifierData *) md;
611                         if (amd->object && amd->object->data == arm)
612                                 return true;
613                 }
614         }
615
616         return false;
617 }
618
619 bool modifier_isCorrectableDeformed(ModifierData *md)
620 {
621         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
622         return (mti->deformMatricesEM != NULL);
623 }
624
625 bool modifiers_isCorrectableDeformed(struct Scene *scene, Object *ob)
626 {
627         VirtualModifierData virtualModifierData;
628         ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
629         int required_mode = eModifierMode_Realtime;
630
631         if (ob->mode == OB_MODE_EDIT)
632                 required_mode |= eModifierMode_Editmode;
633         
634         for (; md; md = md->next) {
635                 if (!modifier_isEnabled(scene, md, required_mode)) {
636                         /* pass */
637                 }
638                 else if (modifier_isCorrectableDeformed(md)) {
639                         return true;
640                 }
641         }
642         return false;
643 }
644
645 /* Check whether the given object has a modifier in its stack that uses WEIGHT_MCOL CD layer
646  * to preview something... Used by DynamicPaint and WeightVG currently. */
647 bool modifiers_isPreview(Object *ob)
648 {
649         ModifierData *md = ob->modifiers.first;
650
651         for (; md; md = md->next) {
652                 if (modifier_isPreview(md))
653                         return true;
654         }
655
656         return false;
657 }
658
659 void modifier_freeTemporaryData(ModifierData *md)
660 {
661         if (md->type == eModifierType_Armature) {
662                 ArmatureModifierData *amd = (ArmatureModifierData *)md;
663
664                 if (amd->prevCos) {
665                         MEM_freeN(amd->prevCos);
666                         amd->prevCos = NULL;
667                 }
668         }
669 }
670
671 /* ensure modifier correctness when changing ob->data */
672 void test_object_modifiers(Object *ob)
673 {
674         ModifierData *md;
675
676         /* just multires checked for now, since only multires
677          * modifies mesh data */
678
679         if (ob->type != OB_MESH) return;
680
681         for (md = ob->modifiers.first; md; md = md->next) {
682                 if (md->type == eModifierType_Multires) {
683                         MultiresModifierData *mmd = (MultiresModifierData *)md;
684
685                         multiresModifier_set_levels_from_disps(mmd, ob);
686                 }
687         }
688 }
689
690 /* where should this go?, it doesnt fit well anywhere :S - campbell */
691
692 /* elubie: changed this to default to the same dir as the render output
693  * to prevent saving to C:\ on Windows */
694
695 /* campbell: logic behind this...
696  *
697  * - if the ID is from a library, return library path
698  * - else if the file has been saved return the blend file path.
699  * - else if the file isn't saved and the ID isn't from a library, return the temp dir.
700  */
701 const char *modifier_path_relbase(Object *ob)
702 {
703         if (G.relbase_valid || ob->id.lib) {
704                 return ID_BLEND_PATH(G.main, &ob->id);
705         }
706         else {
707                 /* last resort, better then using "" which resolves to the current
708                  * working directory */
709                 return BLI_temporary_dir();
710         }
711 }
712
713 /* initializes the path with either */
714 void modifier_path_init(char *path, int path_maxlen, const char *name)
715 {
716         /* elubie: changed this to default to the same dir as the render output
717          * to prevent saving to C:\ on Windows */
718         BLI_join_dirfile(path, path_maxlen,
719                          G.relbase_valid ? "//" : BLI_temporary_dir(),
720                          name);
721 }
722
723
724 /* wrapper around ModifierTypeInfo.applyModifier that ensures valid normals */
725
726 struct DerivedMesh *modwrap_applyModifier(
727         ModifierData *md, Object *ob,
728         struct DerivedMesh *dm,
729         ModifierApplyFlag flag)
730 {
731         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
732         BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
733
734         if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
735                 DM_ensure_normals(dm);
736         }
737         return mti->applyModifier(md, ob, dm, flag);
738 }
739
740 struct DerivedMesh *modwrap_applyModifierEM(
741         ModifierData *md, Object *ob,
742         struct BMEditMesh *em,
743         DerivedMesh *dm,
744         ModifierApplyFlag flag)
745 {
746         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
747         BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
748
749         if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
750                 DM_ensure_normals(dm);
751         }
752         return mti->applyModifierEM(md, ob, em, dm, flag);
753 }
754
755 void modwrap_deformVerts(
756         ModifierData *md, Object *ob,
757         DerivedMesh *dm,
758         float (*vertexCos)[3], int numVerts,
759         ModifierApplyFlag flag)
760 {
761         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
762         BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
763
764         if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
765                 DM_ensure_normals(dm);
766         }
767         mti->deformVerts(md, ob, dm, vertexCos, numVerts, flag);
768 }
769
770 void modwrap_deformVertsEM(
771         ModifierData *md, Object *ob,
772         struct BMEditMesh *em, DerivedMesh *dm,
773         float (*vertexCos)[3], int numVerts)
774 {
775         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
776         BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
777
778         if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
779                 DM_ensure_normals(dm);
780         }
781         mti->deformVertsEM(md, ob, em, dm, vertexCos, numVerts);
782 }
783 /* end modifier callback wrappers */