Blender V4.3
blenkernel/intern/modifier.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11/* Allow using deprecated functionality for .blend file I/O. */
12#define DNA_DEPRECATED_ALLOW
13
14#include <cfloat>
15#include <chrono>
16#include <cmath>
17#include <cstdarg>
18#include <cstddef>
19#include <cstdlib>
20#include <cstring>
21
22#include "MEM_guardedalloc.h"
23
24#include "DNA_armature_types.h"
25#include "DNA_cloth_types.h"
27#include "DNA_fluid_types.h"
29#include "DNA_mesh_types.h"
32#include "DNA_object_types.h"
33#include "DNA_particle_types.h"
34#include "DNA_scene_types.h"
35#include "DNA_screen_types.h"
36
37#include "BLI_linklist.h"
38#include "BLI_listbase.h"
39#include "BLI_path_utils.hh"
40#include "BLI_rand.hh"
41#include "BLI_session_uid.h"
42#include "BLI_string.h"
43#include "BLI_string_utf8.h"
44#include "BLI_string_utils.hh"
45#include "BLI_utildefines.h"
46
47#include "BLT_translation.hh"
48
49#include "BKE_appdir.hh"
50#include "BKE_editmesh.hh"
51#include "BKE_editmesh_cache.hh"
52#include "BKE_effect.h"
53#include "BKE_fluid.h"
54#include "BKE_global.hh"
55#include "BKE_idtype.hh"
56#include "BKE_key.hh"
57#include "BKE_lib_id.hh"
58#include "BKE_lib_query.hh"
59#include "BKE_mesh.hh"
60#include "BKE_mesh_wrapper.hh"
61#include "BKE_multires.hh"
62#include "BKE_object.hh"
63#include "BKE_pointcache.h"
64#include "BKE_screen.hh"
65
66/* may move these, only for BKE_modifier_path_relbase */
67#include "BKE_main.hh"
68/* end */
69
70#include "DEG_depsgraph.hh"
72
73#include "MOD_modifiertypes.hh"
74
75#include "BLO_read_write.hh"
76
77#include "CLG_log.h"
78
79static CLG_LogRef LOG = {"bke.modifier"};
82
112
114{
115 /* type unsigned, no need to check < 0 */
116 if (type < NUM_MODIFIER_TYPES && modifier_types[type] && modifier_types[type]->name[0] != '\0') {
117 return modifier_types[type];
118 }
119
120 return nullptr;
121}
122
123void BKE_modifier_type_panel_id(ModifierType type, char *r_idname)
124{
125 const ModifierTypeInfo *mti = BKE_modifier_get_info(type);
127}
128
133
134/***/
135
137{
138 const ModifierTypeInfo *mti = BKE_modifier_get_info(type);
139 ModifierData *md = static_cast<ModifierData *>(MEM_callocN(mti->struct_size, mti->struct_name));
140
141 /* NOTE: this name must be made unique later. */
142 STRNCPY_UTF8(md->name, DATA_(mti->name));
143
144 md->type = type;
147 /* Only open the main panel at the beginning, not the sub-panels. */
149
152 }
153
154 if (mti->init_data) {
155 mti->init_data(md);
156 }
157
158 return md;
159}
160
162{
164 return md;
165}
166
167static void modifier_free_data_id_us_cb(void * /*user_data*/,
168 Object * /*ob*/,
169 ID **idpoin,
170 int cb_flag)
171{
172 ID *id = *idpoin;
173 if (id != nullptr && (cb_flag & IDWALK_CB_USER) != 0) {
174 id_us_min(id);
175 }
176}
177
179{
181
183 if (mti->foreach_ID_link) {
184 mti->foreach_ID_link(md, nullptr, modifier_free_data_id_us_cb, nullptr);
185 }
186 }
187
188 if (mti->free_data) {
189 mti->free_data(md);
190 }
191 if (md->error) {
192 MEM_freeN(md->error);
193 }
194
195 MEM_freeN(md);
196}
197
202
204{
205 BLI_assert(BLI_findindex(&ob->modifiers, md) != -1);
206
207 if (md->flag & eModifierFlag_Active) {
208 /* Prefer the previous modifier but use the next if this modifier is the first in the list. */
209 if (md->next != nullptr) {
211 }
212 else if (md->prev != nullptr) {
214 }
215 }
216
217 BLI_remlink(&ob->modifiers, md);
218}
219
221{
222 if (modifiers && md) {
224
226 modifiers, md, DATA_(mti->name), '.', offsetof(ModifierData, name), sizeof(md->name));
227 }
228}
229
231{
233
234 return mti->depends_on_time && mti->depends_on_time(scene, md);
235}
236
244
246{
248 if (md->type == type) {
249 return md;
250 }
251 }
252 return nullptr;
253}
254
255ModifierData *BKE_modifiers_findby_name(const Object *ob, const char *name)
256{
257 return static_cast<ModifierData *>(
258 BLI_findstring(&(ob->modifiers), name, offsetof(ModifierData, name)));
259}
260
261ModifierData *BKE_modifiers_findby_persistent_uid(const Object *ob, const int persistent_uid)
262{
264 if (md->persistent_uid == persistent_uid) {
265 return md;
266 }
267 }
268 return nullptr;
269}
270
272{
274 if (md->error) {
275 MEM_freeN(md->error);
276 md->error = nullptr;
277 }
278 }
279}
280
281void BKE_modifiers_foreach_ID_link(Object *ob, IDWalkFunc walk, void *user_data)
282{
285
286 if (mti->foreach_ID_link) {
287 mti->foreach_ID_link(md, ob, walk, user_data);
288 }
289 }
290}
291
292void BKE_modifiers_foreach_tex_link(Object *ob, TexWalkFunc walk, void *user_data)
293{
296
297 if (mti->foreach_tex_link) {
298 mti->foreach_tex_link(md, ob, walk, user_data);
299 }
300 }
301}
302
304{
306
307 STRNCPY(md_dst->name, md->name);
308 BKE_modifier_copydata_ex(md, md_dst, flag);
309
310 return md_dst;
311}
312
314 ModifierData *md_dst,
315 const int /*flag*/)
316{
318
319 /* `md_dst` may have already be fully initialized with some extra allocated data,
320 * we need to free it now to avoid a memory leak. */
321 if (mti->free_data) {
322 mti->free_data(md_dst);
323 }
324
325 const size_t data_size = sizeof(ModifierData);
326 const char *md_src_data = ((const char *)md_src) + data_size;
327 char *md_dst_data = ((char *)md_dst) + data_size;
328 BLI_assert(data_size <= size_t(mti->struct_size));
329 memcpy(md_dst_data, md_src_data, size_t(mti->struct_size) - data_size);
330
331 /* Runtime fields are never to be preserved. */
332 md_dst->runtime = nullptr;
333}
334
335static void modifier_copy_data_id_us_cb(void * /*user_data*/,
336 Object * /*ob*/,
337 ID **idpoin,
338 int cb_flag)
339{
340 ID *id = *idpoin;
341 if (id != nullptr && (cb_flag & IDWALK_CB_USER) != 0) {
342 id_us_plus(id);
343 }
344}
345
346void BKE_modifier_copydata_ex(const ModifierData *md, ModifierData *target, const int flag)
347{
349
350 target->mode = md->mode;
351 target->flag = md->flag;
352 target->ui_expand_flag = md->ui_expand_flag;
353 target->persistent_uid = md->persistent_uid;
354
355 if (mti->copy_data) {
356 mti->copy_data(md, target, flag);
357 }
358
360 if (mti->foreach_ID_link) {
361 mti->foreach_ID_link(target, nullptr, modifier_copy_data_id_us_cb, nullptr);
362 }
363 }
364}
365
367{
368 BKE_modifier_copydata_ex(md, target, 0);
369}
370
372{
374
375 return ((!mti->is_disabled || !mti->is_disabled(scene, md, false)) &&
377}
378
380{
382
383 return ((md->mode & eModifierMode_Realtime) && (md->mode & eModifierMode_Editmode) &&
384 (!mti->is_disabled || !mti->is_disabled(scene, md, false)) &&
386}
387
393
399
400void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *_format, ...)
401{
402 char buffer[512];
403 va_list ap;
404 const char *format = RPT_(_format);
405
406 va_start(ap, _format);
407 vsnprintf(buffer, sizeof(buffer), format, ap);
408 va_end(ap);
409 buffer[sizeof(buffer) - 1] = '\0';
410
411 if (md->error) {
412 MEM_freeN(md->error);
413 }
414
415 md->error = BLI_strdup(buffer);
416
417#ifndef NDEBUG
418 if ((md->mode & eModifierMode_Virtual) == 0) {
419 /* Ensure correct object is passed in. */
420 BLI_assert(BKE_modifier_get_original(ob, md) != nullptr);
421 }
422#endif
423
424 CLOG_WARN(&LOG, "Object: \"%s\", Modifier: \"%s\", %s", ob->id.name + 2, md->name, md->error);
425}
426
427void BKE_modifier_set_warning(const Object *ob, ModifierData *md, const char *_format, ...)
428{
429 char buffer[512];
430 va_list ap;
431 const char *format = RPT_(_format);
432
433 va_start(ap, _format);
434 vsnprintf(buffer, sizeof(buffer), format, ap);
435 va_end(ap);
436 buffer[sizeof(buffer) - 1] = '\0';
437
438 /* Store the warning in the same field as the error.
439 * It is not expected to have both error and warning and having a single place to store the
440 * message simplifies interface code. */
441
442 if (md->error) {
443 MEM_freeN(md->error);
444 }
445
446 md->error = BLI_strdup(buffer);
447
448#ifndef NDEBUG
449 if ((md->mode & eModifierMode_Virtual) == 0) {
450 /* Ensure correct object is passed in. */
451 BLI_assert(BKE_modifier_get_original(ob, md) != nullptr);
452 }
453#endif
454
456}
457
459 Object *ob,
460 int *r_lastPossibleCageIndex,
461 bool is_virtual)
462{
463 VirtualModifierData virtual_modifier_data;
464 ModifierData *md = (is_virtual) ?
465 BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data) :
466 static_cast<ModifierData *>(ob->modifiers.first);
467
468 if (r_lastPossibleCageIndex) {
469 /* ensure the value is initialized */
470 *r_lastPossibleCageIndex = -1;
471 }
472
473 /* Find the last modifier acting on the cage. */
474 int cageIndex = -1;
475 for (int i = 0; md; i++, md = md->next) {
477 bool supports_mapping;
478
479 if (mti->is_disabled && mti->is_disabled(scene, md, false)) {
480 continue;
481 }
483 continue;
484 }
486 continue;
487 }
488
489 supports_mapping = BKE_modifier_supports_mapping(md);
490 if (r_lastPossibleCageIndex && supports_mapping) {
491 *r_lastPossibleCageIndex = i;
492 }
493
494 if (!(md->mode & eModifierMode_Realtime)) {
495 continue;
496 }
497 if (!(md->mode & eModifierMode_Editmode)) {
498 continue;
499 }
500
501 if (!supports_mapping) {
502 break;
503 }
504
505 if (md->mode & eModifierMode_OnCage) {
506 cageIndex = i;
507 }
508 }
509
510 return cageIndex;
511}
512
513bool BKE_modifier_is_enabled(const Scene *scene, ModifierData *md, int required_mode)
514{
516
517 if ((md->mode & required_mode) != required_mode) {
518 return false;
519 }
520 if (scene != nullptr && mti->is_disabled &&
521 mti->is_disabled(scene, md, required_mode == eModifierMode_Render))
522 {
523 return false;
524 }
526 return false;
527 }
528 if ((required_mode & eModifierMode_Editmode) &&
530 {
531 return false;
532 }
533
534 return true;
535}
536
538{
539 return (ID_IS_OVERRIDE_LIBRARY(ob) &&
540 (md == nullptr || (md->flag & eModifierFlag_OverrideLibrary_Local) == 0));
541}
542
544 ModifierData *md,
545 CustomData_MeshMasks *final_datamask,
546 int required_mode)
547{
548 CDMaskLink *dataMasks = nullptr;
549 CDMaskLink *curr, *prev;
550 bool have_deform_modifier = false;
551
552 /* build a list of modifier data requirements in reverse order */
553 for (; md; md = md->next) {
555
556 curr = MEM_cnew<CDMaskLink>(__func__);
557
558 if (BKE_modifier_is_enabled(scene, md, required_mode)) {
560 have_deform_modifier = true;
561 }
562
563 if (mti->required_data_mask) {
564 mti->required_data_mask(md, &curr->mask);
565 }
566 }
567
568 if (!have_deform_modifier) {
569 /* Don't create orco layer when there is no deformation, we fall
570 * back to regular vertex coordinates */
571 curr->mask.vmask &= ~CD_MASK_ORCO;
572 }
573
574 /* prepend new datamask */
575 curr->next = dataMasks;
576 dataMasks = curr;
577 }
578
579 if (!have_deform_modifier) {
580 final_datamask->vmask &= ~CD_MASK_ORCO;
581 }
582
583 /* build the list of required data masks - each mask in the list must
584 * include all elements of the masks that follow it
585 *
586 * note the list is currently in reverse order, so "masks that follow it"
587 * actually means "masks that precede it" at the moment
588 */
589 for (curr = dataMasks, prev = nullptr; curr; prev = curr, curr = curr->next) {
590 if (prev) {
591 CustomData_MeshMasks_update(&curr->mask, &prev->mask);
592 }
593 else {
594 CustomData_MeshMasks_update(&curr->mask, final_datamask);
595 }
596 }
597
598 /* reverse the list so it's in the correct order */
599 BLI_linklist_reverse((LinkNode **)&dataMasks);
600
601 return dataMasks;
602}
603
605 VirtualModifierData *virtual_modifier_data)
606{
607 ModifierData *md = static_cast<ModifierData *>(ob->modifiers.first);
608
609 *virtual_modifier_data = virtualModifierCommonData;
610
611 if (ob->parent) {
612 if (ob->parent->type == OB_ARMATURE && ob->partype == PARSKEL) {
613 virtual_modifier_data->amd.object = ob->parent;
614 virtual_modifier_data->amd.modifier.next = md;
615 virtual_modifier_data->amd.deformflag = ((bArmature *)(ob->parent->data))->deformflag;
616 md = &virtual_modifier_data->amd.modifier;
617 }
618 else if (ob->parent->type == OB_CURVES_LEGACY && ob->partype == PARSKEL) {
619 virtual_modifier_data->cmd.object = ob->parent;
620 virtual_modifier_data->cmd.defaxis = ob->trackflag + 1;
621 virtual_modifier_data->cmd.modifier.next = md;
622 md = &virtual_modifier_data->cmd.modifier;
623 }
624 else if (ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) {
625 virtual_modifier_data->lmd.object = ob->parent;
626 virtual_modifier_data->lmd.modifier.next = md;
627 md = &virtual_modifier_data->lmd.modifier;
628 }
629 }
630
631 /* shape key modifier, not yet for curves */
632 if (ELEM(ob->type, OB_MESH, OB_LATTICE) && BKE_key_from_object((Object *)ob)) {
633 if (ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE)) {
634 virtual_modifier_data->smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage;
635 }
636 else {
637 virtual_modifier_data->smd.modifier.mode &= ~eModifierMode_Editmode | eModifierMode_OnCage;
638 }
639
640 virtual_modifier_data->smd.modifier.next = md;
641 md = &virtual_modifier_data->smd.modifier;
642 }
643
644 return md;
645}
646
648{
649 VirtualModifierData virtual_modifier_data;
650 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
651
652 Object *armature = nullptr;
653 /* return the first selected armature, this lets us use multiple armatures */
654 if (ob->type == OB_GREASE_PENCIL) {
655 for (; md; md = md->next) {
657 auto *amd = reinterpret_cast<GreasePencilArmatureModifierData *>(md);
658 armature = amd->object;
659 if (armature && (armature->base_flag & BASE_SELECTED)) {
660 return armature;
661 }
662 }
663 }
664 }
665 else {
666 for (; md; md = md->next) {
667 if (md->type == eModifierType_Armature) {
668 auto *amd = reinterpret_cast<ArmatureModifierData *>(md);
669 armature = amd->object;
670 if (armature && (armature->base_flag & BASE_SELECTED)) {
671 return armature;
672 }
673 }
674 }
675 }
676 /* If we're still here then return the last armature. */
677 return armature;
678}
679
681{
682 VirtualModifierData virtual_modifier_data;
683 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
684 MeshDeformModifierData *mdmd = nullptr;
685
686 /* return the first selected armature, this lets us use multiple armatures */
687 for (; md; md = md->next) {
688 if (md->type == eModifierType_MeshDeform) {
689 mdmd = (MeshDeformModifierData *)md;
690 if (mdmd->object && (mdmd->object->base_flag & BASE_SELECTED)) {
691 return mdmd->object;
692 }
693 }
694 }
695
696 if (mdmd) { /* if we're still here then return the last armature */
697 return mdmd->object;
698 }
699
700 return nullptr;
701}
702
704{
705 VirtualModifierData virtual_modifier_data;
706 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
707 LatticeModifierData *lmd = nullptr;
708
709 /* return the first selected lattice, this lets us use multiple lattices */
710 for (; md; md = md->next) {
711 if (md->type == eModifierType_Lattice) {
712 lmd = (LatticeModifierData *)md;
713 if (lmd->object && (lmd->object->base_flag & BASE_SELECTED)) {
714 return lmd->object;
715 }
716 }
717 }
718
719 if (lmd) { /* if we're still here then return the last lattice */
720 return lmd->object;
721 }
722
723 return nullptr;
724}
725
727{
728 VirtualModifierData virtual_modifier_data;
729 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
730 CurveModifierData *cmd = nullptr;
731
732 /* return the first selected curve, this lets us use multiple curves */
733 for (; md; md = md->next) {
734 if (md->type == eModifierType_Curve) {
735 cmd = (CurveModifierData *)md;
736 if (cmd->object && (cmd->object->base_flag & BASE_SELECTED)) {
737 return cmd->object;
738 }
739 }
740 }
741
742 if (cmd) { /* if we're still here then return the last curve */
743 return cmd->object;
744 }
745
746 return nullptr;
747}
748
750{
751 VirtualModifierData virtual_modifier_data;
752 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
753 MultiresModifierData *mmd = nullptr;
754
755 for (; md; md = md->next) {
756 if (md->type == eModifierType_Multires) {
757 mmd = (MultiresModifierData *)md;
758 if (mmd->totlvl != 0) {
759 return true;
760 }
761 }
762 }
763 return false;
764}
765
767{
768 VirtualModifierData virtual_modifier_data;
769 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
770
771 for (; md; md = md->next) {
772 if (md->type == eModifierType_Armature) {
773 ArmatureModifierData *amd = reinterpret_cast<ArmatureModifierData *>(md);
774 if (amd->object && amd->object->data == arm) {
775 return true;
776 }
777 }
780 md);
781 if (amd->object && amd->object->data == arm) {
782 return true;
783 }
784 }
785 }
786
787 return false;
788}
789
795
797{
798 VirtualModifierData virtual_modifier_data;
799 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
800 int required_mode = eModifierMode_Realtime;
801
802 if (ob->mode == OB_MODE_EDIT) {
803 required_mode |= eModifierMode_Editmode;
804 }
805 for (; md; md = md->next) {
806 if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
807 /* pass */
808 }
810 return true;
811 }
812 }
813 return false;
814}
815
824
826{
827 /* just multires checked for now, since only multires
828 * modifies mesh data */
829
830 if (ob->type != OB_MESH) {
831 return;
832 }
833
835 if (md->type == eModifierType_Multires) {
837
839 }
840 }
841}
842
843const char *BKE_modifier_path_relbase(Main *bmain, Object *ob)
844{
845 /* - If the ID is from a library, return library path.
846 * - Else if the file has been saved return the blend file path.
847 * - Else if the file isn't saved and the ID isn't from a library, return the temp directory.
848 */
849 if ((bmain->filepath[0] != '\0') || ID_IS_LINKED(ob)) {
850 return ID_BLEND_PATH(bmain, &ob->id);
851 }
852
853 /* Last resort, better than using "" which resolves to the current working directory. */
854 return BKE_tempdir_session();
855}
856
861
862void BKE_modifier_path_init(char *path, int path_maxncpy, const char *name)
863{
864 const char *blendfile_path = BKE_main_blendfile_path_from_global();
865 BLI_path_join(path, path_maxncpy, blendfile_path[0] ? "//" : BKE_tempdir_session(), name);
866}
867
874{
875 switch (mesh->runtime->wrapper_type) {
877 blender::bke::EditMeshData &edit_data = *mesh->runtime->edit_data;
878 if (!edit_data.vert_positions.is_empty()) {
879 /* Note that 'ensure' is acceptable here since these values aren't modified in-place.
880 * If that changes we'll need to recalculate. */
881 BKE_editmesh_cache_ensure_vert_normals(*mesh->runtime->edit_mesh, edit_data);
882 }
883 else {
884 BM_mesh_normals_update(mesh->runtime->edit_mesh->bm);
885 }
886 break;
887 }
889 /* Not an expected case. */
890 break;
892 /* Normals are calculated lazily. */
893 break;
894 }
895}
896
897/* wrapper around ModifierTypeInfo.modify_mesh that ensures valid normals */
898
900{
902
903 if (mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
904 if ((mti->flags & eModifierTypeFlag_AcceptsBMesh) == 0) {
906 }
907 }
908
909 return mti->modify_mesh(md, ctx, mesh);
910}
911
913 const ModifierEvalContext *ctx,
914 Mesh *mesh,
916{
918 mti->deform_verts(md, ctx, mesh, positions);
919 if (mesh) {
920 mesh->tag_positions_changed();
921 }
922}
923
925 const ModifierEvalContext *ctx,
926 const BMEditMesh *em,
927 Mesh *mesh,
929{
931 if (mesh && mti->depends_on_normals && mti->depends_on_normals(md)) {
933 }
934 mti->deform_verts_EM(md, ctx, em, mesh, positions);
935}
936
937/* end modifier callback wrappers */
938
940{
941 if (!DEG_object_geometry_is_evaluated(*ob_eval)) {
942 return nullptr;
943 }
944
945 Mesh *mesh = nullptr;
946
947 if ((ob_eval->type == OB_MESH) && (ob_eval->mode & OB_MODE_EDIT)) {
948 /* In EditMode, evaluated mesh is stored in BMEditMesh, not the object... */
949 const BMEditMesh *em = BKE_editmesh_from_object(ob_eval);
950 /* 'em' might not exist yet in some cases, just after loading a .blend file, see #57878. */
951 if (em != nullptr) {
952 mesh = const_cast<Mesh *>(BKE_object_get_editmesh_eval_final(ob_eval));
953 }
954 }
955 if (mesh == nullptr) {
956 mesh = BKE_object_get_evaluated_mesh(ob_eval);
957 }
958
959 return mesh;
960}
961
963{
964 const Object *object_orig = DEG_get_original_object((Object *)object);
966}
967
969{
970 Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
971 if (object_eval == object) {
972 return md;
973 }
975}
976
978{
980 if (ID_IS_LINKED(&object)) {
982 blender::StringRef(object.id.lib->runtime.filepath_abs));
983 }
984 if (ID_IS_OVERRIDE_LIBRARY_REAL(&object)) {
985 BLI_assert(ID_IS_LINKED(object.id.override_library->reference));
987 hash,
988 blender::StringRef(object.id.override_library->reference->lib->runtime.filepath_abs));
989 }
991 while (true) {
992 const int new_uid = rng.get_int32();
993 if (new_uid <= 0) {
994 continue;
995 }
996 if (BKE_modifiers_findby_persistent_uid(&object, new_uid) != nullptr) {
997 continue;
998 }
999 md.persistent_uid = new_uid;
1000 break;
1001 }
1002}
1003
1005{
1006 blender::Set<int> uids;
1007 int modifiers_num = 0;
1008 LISTBASE_FOREACH (const ModifierData *, md, &object.modifiers) {
1009 if (md->persistent_uid <= 0) {
1010 return false;
1011 }
1012 uids.add(md->persistent_uid);
1013 modifiers_num++;
1014 }
1015 if (uids.size() != modifiers_num) {
1016 return false;
1017 }
1018 return true;
1019}
1020
1021void BKE_modifier_blend_write(BlendWriter *writer, const ID *id_owner, ListBase *modbase)
1022{
1023 if (modbase == nullptr) {
1024 return;
1025 }
1026
1027 LISTBASE_FOREACH (ModifierData *, md, modbase) {
1028 const ModifierTypeInfo *mti = BKE_modifier_get_info(ModifierType(md->type));
1029 if (mti == nullptr) {
1030 continue;
1031 }
1032
1033 /* If the blend_write callback is defined, it should handle the whole writing process. */
1034 if (mti->blend_write != nullptr) {
1035 mti->blend_write(writer, id_owner, md);
1036 continue;
1037 }
1038
1039 BLO_write_struct_by_name(writer, mti->struct_name, md);
1040
1041 if (md->type == eModifierType_Cloth) {
1043
1047 BKE_ptcache_blend_write(writer, &clmd->ptcaches);
1048 }
1049 else if (md->type == eModifierType_Fluid) {
1051
1052 if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
1054
1055 if (fmd->domain) {
1056 BKE_ptcache_blend_write(writer, &(fmd->domain->ptcaches[0]));
1057
1058 /* create fake pointcache so that old blender versions can read it */
1059 fmd->domain->point_cache[1] = BKE_ptcache_add(&fmd->domain->ptcaches[1]);
1061 fmd->domain->point_cache[1]->step = 1;
1062
1063 BKE_ptcache_blend_write(writer, &(fmd->domain->ptcaches[1]));
1064
1065 if (fmd->domain->coba) {
1066 BLO_write_struct(writer, ColorBand, fmd->domain->coba);
1067 }
1068
1069 /* cleanup the fake pointcache */
1071 fmd->domain->point_cache[1] = nullptr;
1072
1074 }
1075 }
1076 else if (fmd->type & MOD_FLUID_TYPE_FLOW) {
1078 }
1079 else if (fmd->type & MOD_FLUID_TYPE_EFFEC) {
1081 }
1082 }
1083 else if (md->type == eModifierType_Fluidsim) {
1084 BLI_assert_unreachable(); /* Deprecated data, should never be written. */
1085 }
1086 else if (md->type == eModifierType_DynamicPaint) {
1088
1089 if (pmd->canvas) {
1091
1092 /* write surfaces */
1094 BLO_write_struct(writer, DynamicPaintSurface, surface);
1095 }
1096 /* write caches and effector weights */
1098 BKE_ptcache_blend_write(writer, &(surface->ptcaches));
1099
1100 BLO_write_struct(writer, EffectorWeights, surface->effector_weights);
1101 }
1102 }
1103 if (pmd->brush) {
1106 BLO_write_struct(writer, ColorBand, pmd->brush->vel_ramp);
1107 }
1108 }
1109 else if (md->type == eModifierType_Collision) {
1110
1111#if 0
1113 /* TODO: CollisionModifier should use pointcache
1114 * + have proper reset events before enabling this. */
1115 writestruct(wd, DATA, float[3], collmd->numverts, collmd->x);
1116 writestruct(wd, DATA, float[3], collmd->numverts, collmd->xnew);
1117 writestruct(wd, DATA, MFace, collmd->numfaces, collmd->mfaces);
1118#endif
1119 }
1120 }
1121}
1122
1123/* TODO(sergey): Find a better place for this.
1124 *
1125 * Unfortunately, this can not be done as a regular do_versions() since the modifier type is
1126 * set to NONE, so the do_versions code wouldn't know where the modifier came from.
1127 *
1128 * The best approach seems to have the functionality in `versioning_280.cc` but still call the
1129 * function from #BKE_modifier_blend_read_data().
1130 */
1131
1132/* Domain, inflow, ... */
1133static void modifier_ensure_type(FluidModifierData *fluid_modifier_data, int type)
1134{
1135 fluid_modifier_data->type = type;
1136 BKE_fluid_modifier_free(fluid_modifier_data);
1137 BKE_fluid_modifier_create_type_data(fluid_modifier_data);
1138}
1139
1146 Object *object,
1147 ListBase *modifiers,
1148 ModifierData *old_modifier_data)
1149{
1151 FluidModifierData *fluid_modifier_data = (FluidModifierData *)new_modifier_data;
1152
1153 if (old_modifier_data->type == eModifierType_Fluidsim) {
1154 FluidsimModifierData *old_fluidsim_modifier_data = (FluidsimModifierData *)old_modifier_data;
1155 /* Only get access to the data, do not mark it as used, otherwise there will be memory leak
1156 * since readfile code won't free it. */
1157 FluidsimSettings *old_fluidsim_settings = static_cast<FluidsimSettings *>(
1159 reader, old_fluidsim_modifier_data->fss, sizeof(FluidsimSettings)));
1160 switch (old_fluidsim_settings->type) {
1161 case OB_FLUIDSIM_ENABLE:
1162 modifier_ensure_type(fluid_modifier_data, 0);
1163 break;
1164 case OB_FLUIDSIM_DOMAIN:
1165 modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_DOMAIN);
1166 BKE_fluid_domain_type_set(object, fluid_modifier_data->domain, FLUID_DOMAIN_TYPE_LIQUID);
1167 break;
1168 case OB_FLUIDSIM_FLUID:
1169 modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_FLOW);
1170 BKE_fluid_flow_type_set(object, fluid_modifier_data->flow, FLUID_FLOW_TYPE_LIQUID);
1171 /* No need to emit liquid far away from surface. */
1172 fluid_modifier_data->flow->surface_distance = 0.0f;
1173 break;
1175 modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_EFFEC);
1177 object, fluid_modifier_data->effector, FLUID_EFFECTOR_TYPE_COLLISION);
1178 break;
1179 case OB_FLUIDSIM_INFLOW:
1180 modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_FLOW);
1181 BKE_fluid_flow_type_set(object, fluid_modifier_data->flow, FLUID_FLOW_TYPE_LIQUID);
1182 BKE_fluid_flow_behavior_set(object, fluid_modifier_data->flow, FLUID_FLOW_BEHAVIOR_INFLOW);
1183 /* No need to emit liquid far away from surface. */
1184 fluid_modifier_data->flow->surface_distance = 0.0f;
1185 break;
1187 modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_FLOW);
1188 BKE_fluid_flow_type_set(object, fluid_modifier_data->flow, FLUID_FLOW_TYPE_LIQUID);
1190 object, fluid_modifier_data->flow, FLUID_FLOW_BEHAVIOR_OUTFLOW);
1191 break;
1193 /* "Particle" type objects not being used by Mantaflow fluid simulations.
1194 * Skip this object, secondary particles can only be enabled through the domain object. */
1195 break;
1197 /* "Control" type objects not being used by Mantaflow fluid simulations.
1198 * Use guiding type instead which is similar. */
1199 modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_EFFEC);
1201 object, fluid_modifier_data->effector, FLUID_EFFECTOR_TYPE_GUIDE);
1202 break;
1203 }
1204 }
1205 else if (old_modifier_data->type == eModifierType_Smoke) {
1206 SmokeModifierData *old_smoke_modifier_data = (SmokeModifierData *)old_modifier_data;
1207 modifier_ensure_type(fluid_modifier_data, old_smoke_modifier_data->type);
1208 if (fluid_modifier_data->type == MOD_FLUID_TYPE_DOMAIN) {
1209 BKE_fluid_domain_type_set(object, fluid_modifier_data->domain, FLUID_DOMAIN_TYPE_GAS);
1210 }
1211 else if (fluid_modifier_data->type == MOD_FLUID_TYPE_FLOW) {
1212 BKE_fluid_flow_type_set(object, fluid_modifier_data->flow, FLUID_FLOW_TYPE_SMOKE);
1213 }
1214 else if (fluid_modifier_data->type == MOD_FLUID_TYPE_EFFEC) {
1216 object, fluid_modifier_data->effector, FLUID_EFFECTOR_TYPE_COLLISION);
1217 }
1218 }
1219
1220 /* Replace modifier data in the stack. */
1221 new_modifier_data->next = old_modifier_data->next;
1222 new_modifier_data->prev = old_modifier_data->prev;
1223 if (new_modifier_data->prev != nullptr) {
1224 new_modifier_data->prev->next = new_modifier_data;
1225 }
1226 if (new_modifier_data->next != nullptr) {
1227 new_modifier_data->next->prev = new_modifier_data;
1228 }
1229 if (modifiers->first == old_modifier_data) {
1230 modifiers->first = new_modifier_data;
1231 }
1232 if (modifiers->last == old_modifier_data) {
1233 modifiers->last = new_modifier_data;
1234 }
1235
1236 /* Free old modifier data. */
1237 MEM_freeN(old_modifier_data);
1238
1239 return new_modifier_data;
1240}
1241
1243{
1245
1246 LISTBASE_FOREACH (ModifierData *, md, lb) {
1247 md->error = nullptr;
1248 md->runtime = nullptr;
1249
1250 /* If linking from a library, clear 'local' library override flag. */
1251 if (ID_IS_LINKED(ob)) {
1252 md->flag &= ~eModifierFlag_OverrideLibrary_Local;
1253 }
1254
1255 /* Modifier data has been allocated as a part of data migration process and
1256 * no reading of nested fields from file is needed. */
1257 bool is_allocated = false;
1258
1259 if (md->type == eModifierType_Fluidsim) {
1261 BLO_read_data_reports(reader),
1263 RPT_("Possible data loss when saving this file! %s modifier is deprecated (Object: %s)"),
1264 md->name,
1265 ob->id.name + 2);
1266 md = modifier_replace_with_fluid(reader, ob, lb, md);
1267 is_allocated = true;
1268 }
1269 else if (md->type == eModifierType_Smoke) {
1271 BLO_read_data_reports(reader),
1273 RPT_("Possible data loss when saving this file! %s modifier is deprecated (Object: %s)"),
1274 md->name,
1275 ob->id.name + 2);
1276 md = modifier_replace_with_fluid(reader, ob, lb, md);
1277 is_allocated = true;
1278 }
1279
1280 const ModifierTypeInfo *mti = BKE_modifier_get_info(ModifierType(md->type));
1281
1282 /* if modifiers disappear, or for upward compatibility */
1283 if (mti == nullptr) {
1284 md->type = eModifierType_None;
1285 }
1286
1287 if (is_allocated) {
1288 /* All the fields has been properly allocated. */
1289 }
1290 else if (md->type == eModifierType_Cloth) {
1292
1293 clmd->clothObject = nullptr;
1294 clmd->hairdata = nullptr;
1295
1298
1299 BKE_ptcache_blend_read_data(reader, &clmd->ptcaches, &clmd->point_cache, 0);
1300
1301 if (clmd->sim_parms) {
1302 if (clmd->sim_parms->presets > 10) {
1303 clmd->sim_parms->presets = 0;
1304 }
1305
1306 clmd->sim_parms->reset = 0;
1307
1309
1310 if (!clmd->sim_parms->effector_weights) {
1312 }
1313 }
1314
1315 clmd->solver_result = nullptr;
1316 }
1317 else if (md->type == eModifierType_Fluid) {
1318
1320
1321 if (fmd->type == MOD_FLUID_TYPE_DOMAIN) {
1322 fmd->flow = nullptr;
1323 fmd->effector = nullptr;
1325 fmd->domain->fmd = fmd;
1326
1327 fmd->domain->fluid = nullptr;
1329 fmd->domain->tex_density = nullptr;
1330 fmd->domain->tex_color = nullptr;
1331 fmd->domain->tex_shadow = nullptr;
1332 fmd->domain->tex_flame = nullptr;
1333 fmd->domain->tex_flame_coba = nullptr;
1334 fmd->domain->tex_coba = nullptr;
1335 fmd->domain->tex_field = nullptr;
1336 fmd->domain->tex_velocity_x = nullptr;
1337 fmd->domain->tex_velocity_y = nullptr;
1338 fmd->domain->tex_velocity_z = nullptr;
1339 fmd->domain->tex_wt = nullptr;
1340 BLO_read_struct(reader, ColorBand, &fmd->domain->coba);
1341
1343 if (!fmd->domain->effector_weights) {
1345 }
1346
1348 reader, &(fmd->domain->ptcaches[0]), &(fmd->domain->point_cache[0]), 1);
1349
1350 /* Manta sim uses only one cache from now on, so store pointer convert */
1351 if (fmd->domain->ptcaches[1].first || fmd->domain->point_cache[1]) {
1352 if (fmd->domain->point_cache[1]) {
1354 reader, fmd->domain->point_cache[1], sizeof(PointCache)));
1355 if (cache->flag & PTCACHE_FAKE_SMOKE) {
1356 /* Manta-sim/smoke was already saved in "new format" and this cache is a fake one. */
1357 }
1358 else {
1359 printf(
1360 "High resolution manta cache not available due to pointcache update. Please "
1361 "reset the simulation.\n");
1362 }
1363 }
1365 fmd->domain->point_cache[1] = nullptr;
1366 }
1367
1368 /* Flag for refreshing the simulation after loading */
1370 }
1371 else if (fmd->type == MOD_FLUID_TYPE_FLOW) {
1372 fmd->domain = nullptr;
1373 fmd->effector = nullptr;
1374 BLO_read_struct(reader, FluidFlowSettings, &fmd->flow);
1375 fmd->flow->fmd = fmd;
1376 fmd->flow->mesh = nullptr;
1377 fmd->flow->verts_old = nullptr;
1378 fmd->flow->numverts = 0;
1379 BLO_read_struct(reader, ParticleSystem, &fmd->flow->psys);
1380
1381 fmd->flow->flags &= ~FLUID_FLOW_NEEDS_UPDATE;
1382 }
1383 else if (fmd->type == MOD_FLUID_TYPE_EFFEC) {
1384 fmd->flow = nullptr;
1385 fmd->domain = nullptr;
1387 if (fmd->effector) {
1388 fmd->effector->fmd = fmd;
1389 fmd->effector->verts_old = nullptr;
1390 fmd->effector->numverts = 0;
1391 fmd->effector->mesh = nullptr;
1392
1393 fmd->effector->flags &= ~FLUID_EFFECTOR_NEEDS_UPDATE;
1394 }
1395 else {
1396 fmd->type = 0;
1397 fmd->flow = nullptr;
1398 fmd->domain = nullptr;
1399 fmd->effector = nullptr;
1400 }
1401 }
1402 }
1403 else if (md->type == eModifierType_DynamicPaint) {
1405
1406 if (pmd->canvas) {
1408 pmd->canvas->pmd = pmd;
1409 pmd->canvas->flags &= ~MOD_DPAINT_BAKING; /* just in case */
1410
1411 if (pmd->canvas->surfaces.first) {
1413
1415 surface->canvas = pmd->canvas;
1416 surface->data = nullptr;
1417 BKE_ptcache_blend_read_data(reader, &(surface->ptcaches), &(surface->pointcache), 1);
1418
1419 BLO_read_struct(reader, EffectorWeights, &surface->effector_weights);
1420 if (surface->effector_weights == nullptr) {
1421 surface->effector_weights = BKE_effector_add_weights(nullptr);
1422 }
1423 }
1424 }
1425 }
1426 if (pmd->brush) {
1428 pmd->brush->pmd = pmd;
1429 BLO_read_struct(reader, ParticleSystem, &pmd->brush->psys);
1430 BLO_read_struct(reader, ColorBand, &pmd->brush->paint_ramp);
1431 BLO_read_struct(reader, ColorBand, &pmd->brush->vel_ramp);
1432 }
1433 }
1434
1435 if ((mti != nullptr) && (mti->blend_read != nullptr)) {
1436 mti->blend_read(reader, md);
1437 }
1438 }
1439}
1440
1441namespace blender::bke {
1442
1443using Clock = std::chrono::high_resolution_clock;
1444
1446{
1447 return std::chrono::duration<double, std::chrono::seconds::period>(
1448 Clock::now().time_since_epoch())
1449 .count();
1450}
1451
1456
1458{
1459 const double end_time = get_current_time_in_seconds();
1460 const double duration = end_time - start_time_;
1461 md_.execution_time = duration;
1462}
1463
1464} // namespace blender::bke
void CustomData_MeshMasks_update(CustomData_MeshMasks *mask_dst, const CustomData_MeshMasks *mask_src)
Definition customdata.cc:91
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:63
blender::Span< blender::float3 > BKE_editmesh_cache_ensure_vert_normals(BMEditMesh &em, blender::bke::EditMeshData &emd)
struct EffectorWeights * BKE_effector_add_weights(struct Collection *collection)
Definition effect.cc:57
void BKE_fluid_flow_behavior_set(struct Object *object, struct FluidFlowSettings *settings, int behavior)
Definition fluid.cc:4616
void BKE_fluid_effector_type_set(struct Object *object, struct FluidEffectorSettings *settings, int type)
Definition fluid.cc:4636
void BKE_fluid_domain_type_set(struct Object *object, struct FluidDomainSettings *settings, int type)
Definition fluid.cc:4589
void BKE_fluid_modifier_create_type_data(struct FluidModifierData *fmd)
Definition fluid.cc:4806
void BKE_fluid_flow_type_set(struct Object *object, struct FluidFlowSettings *settings, int type)
Definition fluid.cc:4621
void BKE_fluid_modifier_free(struct FluidModifierData *fmd)
Definition fluid.cc:4795
#define G_MAIN
Key * BKE_key_from_object(Object *ob)
Definition key.cc:1820
@ LIB_ID_CREATE_NO_USER_REFCOUNT
void id_us_plus(ID *id)
Definition lib_id.cc:351
void id_us_min(ID *id)
Definition lib_id.cc:359
@ IDWALK_CB_USER
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:837
@ ME_WRAPPER_TYPE_MDATA
@ ME_WRAPPER_TYPE_SUBD
@ ME_WRAPPER_TYPE_BMESH
void BKE_mesh_wrapper_ensure_mdata(Mesh *mesh)
#define MODIFIER_TYPE_PANEL_PREFIX
void(*)(void *user_data, Object *ob, ModifierData *md, const PointerRNA *ptr, PropertyRNA *texture_prop) TexWalkFunc
@ eModifierTypeFlag_AcceptsBMesh
@ eModifierTypeFlag_SupportsMapping
@ eModifierTypeFlag_EnableInEditmode
@ eModifierTypeFlag_SupportsEditmode
void(*)(void *user_data, Object *ob, ID **idpoin, int cb_flag) IDWalkFunc
void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *ob)
Definition multires.cc:509
General operations, lookup, etc. for blender objects.
void BKE_object_modifier_set_active(Object *ob, ModifierData *md)
Mesh * BKE_object_get_evaluated_mesh(const Object *object_eval)
const Mesh * BKE_object_get_editmesh_eval_final(const Object *object)
struct PointCache * BKE_ptcache_add(struct ListBase *ptcaches)
void BKE_ptcache_blend_read_data(struct BlendDataReader *reader, struct ListBase *ptcaches, struct PointCache **ocache, int force_disk)
void BKE_ptcache_free_list(struct ListBase *ptcaches)
void BKE_ptcache_blend_write(struct BlendWriter *writer, struct ListBase *ptcaches)
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define BLI_path_join(...)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.c:40
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define STRNCPY_UTF8(dst, src)
void BLI_uniquename(const struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_maxncpy) ATTR_NONNULL(1
#define BLI_string_join(...)
ThreadRWMutex * BLI_rw_mutex_alloc(void)
Definition threads.cc:487
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
void * BLO_read_get_new_data_address_no_us(BlendDataReader *reader, const void *old_address, size_t expected_size)
Definition readfile.cc:4857
BlendFileReadReport * BLO_read_data_reports(BlendDataReader *reader)
Definition readfile.cc:5150
void BLO_write_struct_by_name(BlendWriter *writer, const char *struct_name, const void *data_ptr)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_read_struct(reader, struct_name, ptr_p)
void BLO_reportf_wrap(BlendFileReadReport *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define RPT_(msgid)
#define DATA_(msgid)
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
bool DEG_object_geometry_is_evaluated(const Object &object)
Object * DEG_get_original_object(Object *object)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
Definition DNA_ID.h:676
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:654
#define ID_BLEND_PATH(_bmain, _id)
Definition DNA_ID.h:647
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:683
@ FLUID_DOMAIN_TYPE_GAS
@ FLUID_DOMAIN_TYPE_LIQUID
@ FLUID_DOMAIN_FILE_LOAD
@ FLUID_FLOW_TYPE_LIQUID
@ FLUID_FLOW_TYPE_SMOKE
@ FLUID_EFFECTOR_TYPE_GUIDE
@ FLUID_EFFECTOR_TYPE_COLLISION
@ FLUID_FLOW_BEHAVIOR_OUTFLOW
@ FLUID_FLOW_BEHAVIOR_INFLOW
@ eModifierFlag_OverrideLibrary_Local
@ eModifierFlag_Active
@ eModifierMode_Virtual
@ eModifierMode_Render
@ eModifierMode_Editmode
@ eModifierMode_DisableTemporary
@ eModifierMode_Realtime
@ eModifierMode_OnCage
@ MOD_FLUID_TYPE_EFFEC
@ MOD_FLUID_TYPE_DOMAIN
@ MOD_FLUID_TYPE_FLOW
struct ModifierData ModifierData
@ eModifierType_MeshDeform
@ eModifierType_Fluidsim
@ eModifierType_Curve
@ eModifierType_Lattice
@ eModifierType_GreasePencilArmature
@ eModifierType_Cloth
@ eModifierType_Fluid
@ NUM_MODIFIER_TYPES
@ eModifierType_ShapeKey
@ eModifierType_Armature
@ eModifierType_Collision
@ eModifierType_DynamicPaint
@ eModifierType_None
@ eModifierType_Multires
@ OB_MODE_EDIT
Object is a sort of wrapper for general info.
@ PARSKEL
@ OB_SHAPE_EDIT_MODE
@ OB_LATTICE
@ OB_GREASE_PENCIL
@ OB_ARMATURE
@ OB_MESH
@ OB_CURVES_LEGACY
@ PTCACHE_FAKE_SMOKE
@ PTCACHE_DISK_CACHE
#define BASE_SELECTED(v3d, base)
@ UI_PANEL_DATA_EXPAND_ROOT
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
void modifier_type_init(ModifierTypeInfo *types[])
Definition MOD_util.cc:205
bool BKE_modifier_depends_ontime(Scene *scene, ModifierData *md)
void BKE_modifier_panel_expand(ModifierData *md)
bool BKE_modifier_is_non_geometrical(ModifierData *md)
Object * BKE_modifiers_is_deformed_by_curve(Object *ob)
static void modifier_ensure_type(FluidModifierData *fluid_modifier_data, int type)
void BKE_modifier_path_init(char *path, int path_maxncpy, const char *name)
void BKE_modifiers_clear_errors(Object *ob)
void BKE_modifier_blend_write(BlendWriter *writer, const ID *id_owner, ListBase *modbase)
Mesh * BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval)
void BKE_modifiers_foreach_ID_link(Object *ob, IDWalkFunc walk, void *user_data)
bool BKE_modifier_is_enabled(const Scene *scene, ModifierData *md, int required_mode)
int BKE_modifiers_get_cage_index(const Scene *scene, Object *ob, int *r_lastPossibleCageIndex, bool is_virtual)
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
void BKE_modifier_copydata_ex(const ModifierData *md, ModifierData *target, const int flag)
void BKE_modifier_copydata_generic(const ModifierData *md_src, ModifierData *md_dst, const int)
bool BKE_modifiers_uses_multires(Object *ob)
static void modifier_free_data_id_us_cb(void *, Object *, ID **idpoin, int cb_flag)
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
static ModifierTypeInfo * modifier_types[NUM_MODIFIER_TYPES]
CDMaskLink * BKE_modifier_calc_data_masks(const Scene *scene, ModifierData *md, CustomData_MeshMasks *final_datamask, int required_mode)
void BKE_modifiers_persistent_uid_init(const Object &object, ModifierData &md)
Object * BKE_modifiers_is_deformed_by_lattice(Object *ob)
void BKE_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb, Object *ob)
void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *_format,...)
const char * BKE_modifier_path_relbase_from_global(Object *ob)
bool BKE_modifiers_uses_armature(Object *ob, bArmature *arm)
ModifierData * BKE_modifiers_get_virtual_modifierlist(const Object *ob, VirtualModifierData *virtual_modifier_data)
ModifierData * BKE_modifier_get_original(const Object *object, ModifierData *md)
bool BKE_modifier_supports_mapping(ModifierData *md)
static ModifierData * modifier_allocate_and_init(ModifierType type)
ModifierData * BKE_modifiers_findby_name(const Object *ob, const char *name)
static ModifierData * modifier_replace_with_fluid(BlendDataReader *reader, Object *object, ListBase *modifiers, ModifierData *old_modifier_data)
bool BKE_modifier_supports_cage(Scene *scene, ModifierData *md)
void BKE_modifier_init()
static void modifier_copy_data_id_us_cb(void *, Object *, ID **idpoin, int cb_flag)
const char * BKE_modifier_path_relbase(Main *bmain, Object *ob)
void BKE_modifier_free_temporary_data(ModifierData *md)
ModifierData * BKE_modifier_copy_ex(const ModifierData *md, int flag)
bool BKE_modifier_is_same_topology(ModifierData *md)
void BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md)
Mesh * BKE_modifier_modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
void BKE_modifier_free(ModifierData *md)
bool BKE_modifier_is_nonlocal_in_liboverride(const Object *ob, const ModifierData *md)
void BKE_modifiers_test_object(Object *ob)
Object * BKE_modifiers_is_deformed_by_meshdeform(Object *ob)
void BKE_modifier_remove_from_list(Object *ob, ModifierData *md)
bool BKE_modifiers_persistent_uids_are_valid(const Object &object)
static CLG_LogRef LOG
static VirtualModifierData virtualModifierCommonData
void BKE_modifier_deform_vertsEM(ModifierData *md, const ModifierEvalContext *ctx, const BMEditMesh *em, Mesh *mesh, blender::MutableSpan< blender::float3 > positions)
bool BKE_modifier_is_correctable_deformed(ModifierData *md)
ModifierData * BKE_modifier_get_evaluated(Depsgraph *depsgraph, Object *object, ModifierData *md)
void BKE_modifier_free_ex(ModifierData *md, const int flag)
bool BKE_modifiers_is_correctable_deformed(const Scene *scene, Object *ob)
void BKE_modifier_type_panel_id(ModifierType type, char *r_idname)
ModifierData * BKE_modifier_new(int type)
bool BKE_modifier_couldbe_cage(Scene *scene, ModifierData *md)
Object * BKE_modifiers_is_deformed_by_armature(Object *ob)
void BKE_modifier_set_warning(const Object *ob, ModifierData *md, const char *_format,...)
void BKE_modifier_deform_verts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, blender::MutableSpan< blender::float3 > positions)
void BKE_modifier_copydata(const ModifierData *md, ModifierData *target)
ModifierData * BKE_modifiers_findby_persistent_uid(const Object *ob, const int persistent_uid)
static void ensure_non_lazy_normals(Mesh *mesh)
void BKE_modifiers_foreach_tex_link(Object *ob, TexWalkFunc walk, void *user_data)
void BM_mesh_normals_update(BMesh *bm)
bool is_empty() const
Definition BLI_array.hh:253
int64_t size() const
Definition BLI_set.hh:564
bool add(const Key &key)
Definition BLI_set.hh:248
#define printf
const Depsgraph * depsgraph
#define offsetof(t, d)
#define DATA(_y, _x)
format
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
static double get_current_time_in_seconds()
std::chrono::high_resolution_clock Clock
uint64_t get_default_hash(const T &v)
Definition BLI_hash.hh:219
#define hash
Definition noise.c:154
unsigned int uint32_t
Definition stdint.h:80
unsigned __int64 uint64_t
Definition stdint.h:90
struct ListBase ptcaches
struct ClothSolverResult * solver_result
struct ClothHairData * hairdata
struct Cloth * clothObject
struct PointCache * point_cache
struct ClothSimSettings * sim_parms
struct ClothCollSettings * coll_parms
struct EffectorWeights * effector_weights
struct Object * object
struct DynamicPaintModifierData * pmd
struct DynamicPaintModifierData * pmd
struct DynamicPaintCanvasSettings * canvas
struct DynamicPaintBrushSettings * brush
struct ListBase ptcaches[2]
struct FluidModifierData * fmd
struct GPUTexture * tex_density
struct GPUTexture * tex_velocity_x
struct GPUTexture * tex_color
struct GPUTexture * tex_wt
struct GPUTexture * tex_velocity_y
struct GPUTexture * tex_field
struct GPUTexture * tex_velocity_z
struct PointCache * point_cache[2]
struct GPUTexture * tex_shadow
struct ColorBand * coba
struct GPUTexture * tex_coba
struct GPUTexture * tex_flame
struct EffectorWeights * effector_weights
struct GPUTexture * tex_flame_coba
struct FluidModifierData * fmd
struct FluidModifierData * fmd
struct ParticleSystem * psys
struct FluidDomainSettings * domain
struct FluidEffectorSettings * effector
struct FluidFlowSettings * flow
struct FluidsimSettings * fss
Definition DNA_ID.h:413
char name[66]
Definition DNA_ID.h:425
void * last
void * first
char filepath[1024]
Definition BKE_main.hh:136
struct ModifierData * next
struct ModifierData * prev
void(* copy_data)(const ModifierData *md, ModifierData *target, int flag)
bool(* depends_on_time)(Scene *scene, ModifierData *md)
void(* blend_write)(BlendWriter *writer, const ID *id_owner, const ModifierData *md)
void(* foreach_ID_link)(ModifierData *md, Object *ob, IDWalkFunc walk, void *user_data)
void(* required_data_mask)(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
void(* deform_verts)(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, blender::MutableSpan< blender::float3 > positions)
void(* free_data)(ModifierData *md)
void(* deform_matrices_EM)(ModifierData *md, const ModifierEvalContext *ctx, const BMEditMesh *em, Mesh *mesh, blender::MutableSpan< blender::float3 > positions, blender::MutableSpan< blender::float3x3 > matrices)
bool(* is_disabled)(const Scene *scene, ModifierData *md, bool use_render_params)
ModifierTypeFlag flags
ModifierTypeType type
bool(* depends_on_normals)(ModifierData *md)
Mesh *(* modify_mesh)(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
void(* deform_verts_EM)(ModifierData *md, const ModifierEvalContext *ctx, const BMEditMesh *em, Mesh *mesh, blender::MutableSpan< blender::float3 > positions)
void(* blend_read)(BlendDataReader *reader, ModifierData *md)
void(* init_data)(ModifierData *md)
void(* foreach_tex_link)(ModifierData *md, Object *ob, TexWalkFunc walk, void *user_data)
short base_flag
ListBase modifiers
struct Object * parent
short trackflag
char idname[BKE_ST_MAXNAME]
ArmatureModifierData amd
CurveModifierData cmd
LatticeModifierData lmd
ShapeKeyModifierData smd
void * BKE_tempdir_session
Definition stubs.c:38
static DynamicLibrary lib
uint8_t flag
Definition wm_window.cc:138
#define writestruct(wd, filecode, struct_id, nr, adr)
Definition writefile.cc:830