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