2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
19 * All rights reserved.
21 * Contributor(s): Daniel Dunbar
27 * ***** END GPL LICENSE BLOCK *****
29 * Modifier stack implementation.
31 * BKE_modifier.h contains the function prototypes for this file.
35 /** \file blender/blenkernel/intern/modifier.c
46 #include "MEM_guardedalloc.h"
48 #include "DNA_armature_types.h"
49 #include "DNA_object_types.h"
51 #include "BLI_utildefines.h"
52 #include "BLI_listbase.h"
53 #include "BLI_linklist.h"
54 #include "BLI_path_util.h"
55 #include "BLI_string.h"
56 #include "BLI_string_utils.h"
58 #include "BLT_translation.h"
60 #include "BKE_appdir.h"
62 #include "BKE_library.h"
63 #include "BKE_library_query.h"
64 #include "BKE_multires.h"
65 #include "BKE_DerivedMesh.h"
67 /* may move these, only for modifier_path_relbase */
68 #include "BKE_global.h" /* ugh, G.main->name only */
72 #include "MOD_modifiertypes.h"
74 static ModifierTypeInfo *modifier_types[NUM_MODIFIER_TYPES] = {NULL};
75 static VirtualModifierData virtualModifierCommonData;
77 void BKE_modifier_init(void)
81 /* Initialize modifier types */
82 modifier_type_init(modifier_types); /* MOD_utils.c */
84 /* Initialize global cmmon storage used for virtual modifier list */
85 md = modifier_new(eModifierType_Armature);
86 virtualModifierCommonData.amd = *((ArmatureModifierData *) md);
89 md = modifier_new(eModifierType_Curve);
90 virtualModifierCommonData.cmd = *((CurveModifierData *) md);
93 md = modifier_new(eModifierType_Lattice);
94 virtualModifierCommonData.lmd = *((LatticeModifierData *) md);
97 md = modifier_new(eModifierType_ShapeKey);
98 virtualModifierCommonData.smd = *((ShapeKeyModifierData *) md);
101 virtualModifierCommonData.amd.modifier.mode |= eModifierMode_Virtual;
102 virtualModifierCommonData.cmd.modifier.mode |= eModifierMode_Virtual;
103 virtualModifierCommonData.lmd.modifier.mode |= eModifierMode_Virtual;
104 virtualModifierCommonData.smd.modifier.mode |= eModifierMode_Virtual;
107 const ModifierTypeInfo *modifierType_getInfo(ModifierType type)
109 /* type unsigned, no need to check < 0 */
110 if (type < NUM_MODIFIER_TYPES && modifier_types[type]->name[0] != '\0') {
111 return modifier_types[type];
120 ModifierData *modifier_new(int type)
122 const ModifierTypeInfo *mti = modifierType_getInfo(type);
123 ModifierData *md = MEM_callocN(mti->structSize, mti->structName);
125 /* note, this name must be made unique later */
126 BLI_strncpy(md->name, DATA_(mti->name), sizeof(md->name));
129 md->mode = eModifierMode_Realtime | eModifierMode_Render | eModifierMode_Expanded;
131 if (mti->flags & eModifierTypeFlag_EnableInEditmode)
132 md->mode |= eModifierMode_Editmode;
134 if (mti->initData) mti->initData(md);
139 static void modifier_free_data_id_us_cb(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int cb_flag)
142 if (id != NULL && (cb_flag & IDWALK_CB_USER) != 0) {
147 void modifier_free_ex(ModifierData *md, const int flag)
149 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
151 if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
152 if (mti->foreachIDLink) {
153 mti->foreachIDLink(md, NULL, modifier_free_data_id_us_cb, NULL);
155 else if (mti->foreachObjectLink) {
156 mti->foreachObjectLink(md, NULL, (ObjectWalkFunc)modifier_free_data_id_us_cb, NULL);
160 if (mti->freeData) mti->freeData(md);
161 if (md->error) MEM_freeN(md->error);
166 void modifier_free(ModifierData *md)
168 modifier_free_ex(md, 0);
171 bool modifier_unique_name(ListBase *modifiers, ModifierData *md)
173 if (modifiers && md) {
174 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
176 return BLI_uniquename(modifiers, md, DATA_(mti->name), '.', offsetof(ModifierData, name), sizeof(md->name));
181 bool modifier_dependsOnTime(ModifierData *md)
183 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
185 return mti->dependsOnTime && mti->dependsOnTime(md);
188 bool modifier_supportsMapping(ModifierData *md)
190 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
192 return (mti->type == eModifierTypeType_OnlyDeform ||
193 (mti->flags & eModifierTypeFlag_SupportsMapping));
196 bool modifier_isPreview(ModifierData *md)
198 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
200 /* Constructive modifiers are highly likely to also modify data like vgroups or vcol! */
201 if (!((mti->flags & eModifierTypeFlag_UsesPreview) || (mti->type == eModifierTypeType_Constructive))) {
205 if (md->mode & eModifierMode_Realtime) {
212 ModifierData *modifiers_findByType(Object *ob, ModifierType type)
214 ModifierData *md = ob->modifiers.first;
216 for (; md; md = md->next)
217 if (md->type == type)
223 ModifierData *modifiers_findByName(Object *ob, const char *name)
225 return BLI_findstring(&(ob->modifiers), name, offsetof(ModifierData, name));
228 void modifiers_clearErrors(Object *ob)
230 ModifierData *md = ob->modifiers.first;
231 /* int qRedraw = 0; */
233 for (; md; md = md->next) {
235 MEM_freeN(md->error);
243 void modifiers_foreachObjectLink(Object *ob, ObjectWalkFunc walk, void *userData)
245 ModifierData *md = ob->modifiers.first;
247 for (; md; md = md->next) {
248 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
250 if (mti->foreachObjectLink)
251 mti->foreachObjectLink(md, ob, walk, userData);
255 void modifiers_foreachIDLink(Object *ob, IDWalkFunc walk, void *userData)
257 ModifierData *md = ob->modifiers.first;
259 for (; md; md = md->next) {
260 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
262 if (mti->foreachIDLink) mti->foreachIDLink(md, ob, walk, userData);
263 else if (mti->foreachObjectLink) {
264 /* each Object can masquerade as an ID, so this should be OK */
265 ObjectWalkFunc fp = (ObjectWalkFunc)walk;
266 mti->foreachObjectLink(md, ob, fp, userData);
271 void modifiers_foreachTexLink(Object *ob, TexWalkFunc walk, void *userData)
273 ModifierData *md = ob->modifiers.first;
275 for (; md; md = md->next) {
276 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
278 if (mti->foreachTexLink)
279 mti->foreachTexLink(md, ob, walk, userData);
283 /* callback's can use this
284 * to avoid copying every member.
286 void modifier_copyData_generic(const ModifierData *md_src, ModifierData *md_dst)
288 const ModifierTypeInfo *mti = modifierType_getInfo(md_src->type);
290 /* md_dst may have alredy be fully initialized with some extra allocated data,
291 * we need to free it now to avoid memleak. */
293 mti->freeData(md_dst);
296 const size_t data_size = sizeof(ModifierData);
297 const char *md_src_data = ((const char *)md_src) + data_size;
298 char *md_dst_data = ((char *)md_dst) + data_size;
299 BLI_assert(data_size <= (size_t)mti->structSize);
300 memcpy(md_dst_data, md_src_data, (size_t)mti->structSize - data_size);
303 static void modifier_copy_data_id_us_cb(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int cb_flag)
306 if (id != NULL && (cb_flag & IDWALK_CB_USER) != 0) {
311 void modifier_copyData_ex(ModifierData *md, ModifierData *target, const int flag)
313 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
315 target->mode = md->mode;
318 mti->copyData(md, target);
321 if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
322 if (mti->foreachIDLink) {
323 mti->foreachIDLink(target, NULL, modifier_copy_data_id_us_cb, NULL);
325 else if (mti->foreachObjectLink) {
326 mti->foreachObjectLink(target, NULL, (ObjectWalkFunc)modifier_copy_data_id_us_cb, NULL);
331 void modifier_copyData(ModifierData *md, ModifierData *target)
333 modifier_copyData_ex(md, target, 0);
337 bool modifier_supportsCage(struct Scene *scene, ModifierData *md)
339 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
343 return ((!mti->isDisabled || !mti->isDisabled(md, 0)) &&
344 (mti->flags & eModifierTypeFlag_SupportsEditmode) &&
345 modifier_supportsMapping(md));
348 bool modifier_couldBeCage(struct Scene *scene, ModifierData *md)
350 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
354 return ((md->mode & eModifierMode_Realtime) &&
355 (md->mode & eModifierMode_Editmode) &&
356 (!mti->isDisabled || !mti->isDisabled(md, 0)) &&
357 modifier_supportsMapping(md));
360 bool modifier_isSameTopology(ModifierData *md)
362 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
363 return ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical);
366 bool modifier_isNonGeometrical(ModifierData *md)
368 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
369 return (mti->type == eModifierTypeType_NonGeometrical);
372 void modifier_setError(ModifierData *md, const char *_format, ...)
376 const char *format = TIP_(_format);
378 va_start(ap, _format);
379 vsnprintf(buffer, sizeof(buffer), format, ap);
381 buffer[sizeof(buffer) - 1] = '\0';
384 MEM_freeN(md->error);
386 md->error = BLI_strdup(buffer);
390 /* used for buttons, to find out if the 'draw deformed in editmode' option is
393 * also used in transform_conversion.c, to detect CrazySpace [tm] (2nd arg
395 * also used for some mesh tools to give warnings
397 int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *r_lastPossibleCageIndex, bool is_virtual)
399 VirtualModifierData virtualModifierData;
400 ModifierData *md = (is_virtual) ? modifiers_getVirtualModifierList(ob, &virtualModifierData) : ob->modifiers.first;
401 int i, cageIndex = -1;
403 if (r_lastPossibleCageIndex) {
404 /* ensure the value is initialized */
405 *r_lastPossibleCageIndex = -1;
408 /* Find the last modifier acting on the cage. */
409 for (i = 0; md; i++, md = md->next) {
410 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
411 bool supports_mapping;
415 if (mti->isDisabled && mti->isDisabled(md, 0)) continue;
416 if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) continue;
417 if (md->mode & eModifierMode_DisableTemporary) continue;
419 supports_mapping = modifier_supportsMapping(md);
420 if (r_lastPossibleCageIndex && supports_mapping) {
421 *r_lastPossibleCageIndex = i;
424 if (!(md->mode & eModifierMode_Realtime)) continue;
425 if (!(md->mode & eModifierMode_Editmode)) continue;
427 if (!supports_mapping)
430 if (md->mode & eModifierMode_OnCage)
438 bool modifiers_isSoftbodyEnabled(Object *ob)
440 ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
442 return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
445 bool modifiers_isClothEnabled(Object *ob)
447 ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
449 return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
452 bool modifiers_isModifierEnabled(Object *ob, int modifierType)
454 ModifierData *md = modifiers_findByType(ob, modifierType);
456 return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
459 bool modifiers_isParticleEnabled(Object *ob)
461 ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleSystem);
463 return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
467 * Check whether is enabled.
469 * \param scene Current scene, may be NULL, in which case isDisabled callback of the modifier is never called.
471 bool modifier_isEnabled(struct Scene *scene, ModifierData *md, int required_mode)
473 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
477 if ((md->mode & required_mode) != required_mode) return false;
478 if (scene != NULL && mti->isDisabled && mti->isDisabled(md, required_mode == eModifierMode_Render)) return false;
479 if (md->mode & eModifierMode_DisableTemporary) return false;
480 if ((required_mode & eModifierMode_Editmode) && !(mti->flags & eModifierTypeFlag_SupportsEditmode)) return false;
485 CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, Object *ob, ModifierData *md,
486 CustomDataMask dataMask, int required_mode,
487 ModifierData *previewmd, CustomDataMask previewmask)
489 CDMaskLink *dataMasks = NULL;
490 CDMaskLink *curr, *prev;
492 /* build a list of modifier data requirements in reverse order */
493 for (; md; md = md->next) {
494 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
496 curr = MEM_callocN(sizeof(CDMaskLink), "CDMaskLink");
498 if (modifier_isEnabled(scene, md, required_mode)) {
499 if (mti->requiredDataMask)
500 curr->mask = mti->requiredDataMask(ob, md);
502 if (previewmd == md) {
503 curr->mask |= previewmask;
507 /* prepend new datamask */
508 curr->next = dataMasks;
512 /* build the list of required data masks - each mask in the list must
513 * include all elements of the masks that follow it
515 * note the list is currently in reverse order, so "masks that follow it"
516 * actually means "masks that precede it" at the moment
518 for (curr = dataMasks, prev = NULL; curr; prev = curr, curr = curr->next) {
520 CustomDataMask prev_mask = prev->mask;
521 CustomDataMask curr_mask = curr->mask;
523 curr->mask = curr_mask | prev_mask;
526 CustomDataMask curr_mask = curr->mask;
528 curr->mask = curr_mask | dataMask;
532 /* reverse the list so it's in the correct order */
533 BLI_linklist_reverse((LinkNode **)&dataMasks);
538 ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, int required_mode)
540 ModifierData *tmp_md = NULL;
542 if ((required_mode & ~eModifierMode_Editmode) != eModifierMode_Realtime)
545 /* Find the latest modifier in stack generating preview. */
546 for (; md; md = md->next) {
547 if (modifier_isEnabled(scene, md, required_mode) && modifier_isPreview(md))
553 /* NOTE: This is to support old files from before Blender supported modifiers,
554 * in some cases versioning code updates these so for new files this will
555 * return an empty list. */
556 ModifierData *modifiers_getVirtualModifierList(Object *ob, VirtualModifierData *virtualModifierData)
560 md = ob->modifiers.first;
562 *virtualModifierData = virtualModifierCommonData;
565 if (ob->parent->type == OB_ARMATURE && ob->partype == PARSKEL) {
566 virtualModifierData->amd.object = ob->parent;
567 virtualModifierData->amd.modifier.next = md;
568 virtualModifierData->amd.deformflag = ((bArmature *)(ob->parent->data))->deformflag;
569 md = &virtualModifierData->amd.modifier;
571 else if (ob->parent->type == OB_CURVE && ob->partype == PARSKEL) {
572 virtualModifierData->cmd.object = ob->parent;
573 virtualModifierData->cmd.defaxis = ob->trackflag + 1;
574 virtualModifierData->cmd.modifier.next = md;
575 md = &virtualModifierData->cmd.modifier;
577 else if (ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) {
578 virtualModifierData->lmd.object = ob->parent;
579 virtualModifierData->lmd.modifier.next = md;
580 md = &virtualModifierData->lmd.modifier;
584 /* shape key modifier, not yet for curves */
585 if (ELEM(ob->type, OB_MESH, OB_LATTICE) && BKE_key_from_object(ob)) {
586 if (ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE))
587 virtualModifierData->smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage;
589 virtualModifierData->smd.modifier.mode &= ~eModifierMode_Editmode | eModifierMode_OnCage;
591 virtualModifierData->smd.modifier.next = md;
592 md = &virtualModifierData->smd.modifier;
598 /* Takes an object and returns its first selected armature, else just its armature
599 * This should work for multiple armatures per object
601 Object *modifiers_isDeformedByArmature(Object *ob)
603 VirtualModifierData virtualModifierData;
604 ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
605 ArmatureModifierData *amd = NULL;
607 /* return the first selected armature, this lets us use multiple armatures */
608 for (; md; md = md->next) {
609 if (md->type == eModifierType_Armature) {
610 amd = (ArmatureModifierData *) md;
611 if (amd->object && (amd->object->flag & SELECT))
616 if (amd) /* if were still here then return the last armature */
622 /* Takes an object and returns its first selected lattice, else just its lattice
623 * This should work for multiple lattices per object
625 Object *modifiers_isDeformedByLattice(Object *ob)
627 VirtualModifierData virtualModifierData;
628 ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
629 LatticeModifierData *lmd = NULL;
631 /* return the first selected lattice, this lets us use multiple lattices */
632 for (; md; md = md->next) {
633 if (md->type == eModifierType_Lattice) {
634 lmd = (LatticeModifierData *) md;
635 if (lmd->object && (lmd->object->flag & SELECT))
640 if (lmd) /* if were still here then return the last lattice */
646 /* Takes an object and returns its first selected curve, else just its curve
647 * This should work for multiple curves per object
649 Object *modifiers_isDeformedByCurve(Object *ob)
651 VirtualModifierData virtualModifierData;
652 ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
653 CurveModifierData *cmd = NULL;
655 /* return the first selected curve, this lets us use multiple curves */
656 for (; md; md = md->next) {
657 if (md->type == eModifierType_Curve) {
658 cmd = (CurveModifierData *) md;
659 if (cmd->object && (cmd->object->flag & SELECT))
664 if (cmd) /* if were still here then return the last curve */
670 bool modifiers_usesArmature(Object *ob, bArmature *arm)
672 VirtualModifierData virtualModifierData;
673 ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
675 for (; md; md = md->next) {
676 if (md->type == eModifierType_Armature) {
677 ArmatureModifierData *amd = (ArmatureModifierData *) md;
678 if (amd->object && amd->object->data == arm)
686 bool modifier_isCorrectableDeformed(ModifierData *md)
688 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
689 return (mti->deformMatricesEM != NULL);
692 bool modifiers_isCorrectableDeformed(struct Scene *scene, Object *ob)
694 VirtualModifierData virtualModifierData;
695 ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
696 int required_mode = eModifierMode_Realtime;
698 if (ob->mode == OB_MODE_EDIT)
699 required_mode |= eModifierMode_Editmode;
701 for (; md; md = md->next) {
702 if (!modifier_isEnabled(scene, md, required_mode)) {
705 else if (modifier_isCorrectableDeformed(md)) {
712 /* Check whether the given object has a modifier in its stack that uses WEIGHT_MCOL CD layer
713 * to preview something... Used by DynamicPaint and WeightVG currently. */
714 bool modifiers_isPreview(Object *ob)
716 ModifierData *md = ob->modifiers.first;
718 for (; md; md = md->next) {
719 if (modifier_isPreview(md))
726 void modifier_freeTemporaryData(ModifierData *md)
728 if (md->type == eModifierType_Armature) {
729 ArmatureModifierData *amd = (ArmatureModifierData *)md;
732 MEM_freeN(amd->prevCos);
738 /* ensure modifier correctness when changing ob->data */
739 void test_object_modifiers(Object *ob)
743 /* just multires checked for now, since only multires
744 * modifies mesh data */
746 if (ob->type != OB_MESH) return;
748 for (md = ob->modifiers.first; md; md = md->next) {
749 if (md->type == eModifierType_Multires) {
750 MultiresModifierData *mmd = (MultiresModifierData *)md;
752 multiresModifier_set_levels_from_disps(mmd, ob);
757 /* where should this go?, it doesnt fit well anywhere :S - campbell */
759 /* elubie: changed this to default to the same dir as the render output
760 * to prevent saving to C:\ on Windows */
762 /* campbell: logic behind this...
764 * - if the ID is from a library, return library path
765 * - else if the file has been saved return the blend file path.
766 * - else if the file isn't saved and the ID isn't from a library, return the temp dir.
768 const char *modifier_path_relbase(Object *ob)
770 if (G.relbase_valid || ID_IS_LINKED(ob)) {
771 return ID_BLEND_PATH(G.main, &ob->id);
774 /* last resort, better then using "" which resolves to the current
775 * working directory */
776 return BKE_tempdir_session();
780 /* initializes the path with either */
781 void modifier_path_init(char *path, int path_maxlen, const char *name)
783 /* elubie: changed this to default to the same dir as the render output
784 * to prevent saving to C:\ on Windows */
785 BLI_join_dirfile(path, path_maxlen,
786 G.relbase_valid ? "//" : BKE_tempdir_session(),
791 /* wrapper around ModifierTypeInfo.applyModifier that ensures valid normals */
793 struct DerivedMesh *modwrap_applyModifier(
794 ModifierData *md, Object *ob,
795 struct DerivedMesh *dm,
796 ModifierApplyFlag flag)
798 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
799 BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
801 if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
802 DM_ensure_normals(dm);
804 return mti->applyModifier(md, ob, dm, flag);
807 struct DerivedMesh *modwrap_applyModifierEM(
808 ModifierData *md, Object *ob,
809 struct BMEditMesh *em,
811 ModifierApplyFlag flag)
813 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
814 BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
816 if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
817 DM_ensure_normals(dm);
819 return mti->applyModifierEM(md, ob, em, dm, flag);
822 void modwrap_deformVerts(
823 ModifierData *md, Object *ob,
825 float (*vertexCos)[3], int numVerts,
826 ModifierApplyFlag flag)
828 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
829 BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
831 if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
832 DM_ensure_normals(dm);
834 mti->deformVerts(md, ob, dm, vertexCos, numVerts, flag);
837 void modwrap_deformVertsEM(
838 ModifierData *md, Object *ob,
839 struct BMEditMesh *em, DerivedMesh *dm,
840 float (*vertexCos)[3], int numVerts)
842 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
843 BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false);
845 if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
846 DM_ensure_normals(dm);
848 mti->deformVertsEM(md, ob, em, dm, vertexCos, numVerts);
850 /* end modifier callback wrappers */