Blender V5.0
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
10
11/* Allow using deprecated functionality for .blend file I/O. */
12#define DNA_DEPRECATED_ALLOW
13
14#include <cfloat>
15#include <chrono>
16#include <cstdarg>
17#include <cstddef>
18#include <cstdlib>
19#include <cstring>
20
21#include "MEM_guardedalloc.h"
22
23#include "DNA_armature_types.h"
24#include "DNA_cloth_types.h"
25#include "DNA_colorband_types.h"
27#include "DNA_fluid_types.h"
28#include "DNA_mesh_types.h"
31#include "DNA_object_types.h"
32#include "DNA_particle_types.h"
33#include "DNA_scene_types.h"
34#include "DNA_screen_types.h"
35
36#include "BLI_linklist.h"
37#include "BLI_listbase.h"
38#include "BLI_path_utils.hh"
39#include "BLI_rand.hh"
40#include "BLI_string.h"
41#include "BLI_string_utf8.h"
42#include "BLI_string_utils.hh"
43#include "BLI_threads.h"
44#include "BLI_utildefines.h"
45
46#include "BLT_translation.hh"
47
48#include "BKE_appdir.hh"
49#include "BKE_editmesh.hh"
50#include "BKE_editmesh_cache.hh"
51#include "BKE_effect.h"
52#include "BKE_fluid.h"
53#include "BKE_geometry_set.hh"
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_library.hh"
60#include "BKE_mesh.hh"
62#include "BKE_mesh_wrapper.hh"
63#include "BKE_multires.hh"
64#include "BKE_object.hh"
65#include "BKE_pointcache.h"
66#include "BKE_report.hh"
67#include "BKE_screen.hh"
68
69/* may move these, only for BKE_modifier_path_relbase */
70#include "BKE_main.hh"
71/* end */
72
73#include "DEG_depsgraph.hh"
75
76#include "MOD_modifiertypes.hh"
77
78#include "BLO_read_write.hh"
79
80#include "CLG_log.h"
81
82static CLG_LogRef LOG = {"object.modifier"};
85
87{
88 ModifierData *md;
89
90 /* Initialize modifier types */
91 modifier_type_init(modifier_types); /* MOD_utils.c */
92
93 /* Initialize global common storage used for virtual modifier list. */
97
101
105
109
114}
115
117{
118 /* type unsigned, no need to check < 0 */
119 if (type < NUM_MODIFIER_TYPES && modifier_types[type] && modifier_types[type]->name[0] != '\0') {
120 return modifier_types[type];
121 }
122
123 return nullptr;
124}
125
126void BKE_modifier_type_panel_id(ModifierType type, char *r_idname)
127{
128 const ModifierTypeInfo *mti = BKE_modifier_get_info(type);
130}
131
136
137/***/
138
140{
141 const ModifierTypeInfo *mti = BKE_modifier_get_info(type);
142 ModifierData *md = static_cast<ModifierData *>(MEM_callocN(mti->struct_size, mti->struct_name));
143
144 /* NOTE: this name must be made unique later. */
145 STRNCPY_UTF8(md->name, DATA_(mti->name));
146
147 md->type = type;
150 /* Only open the main panel at the beginning, not the sub-panels. */
152
155 }
156
157 if (mti->init_data) {
158 mti->init_data(md);
159 }
160
161 return md;
162}
163
165{
167 return md;
168}
169
170static void modifier_free_data_id_us_cb(void * /*user_data*/,
171 Object * /*ob*/,
172 ID **idpoin,
173 const LibraryForeachIDCallbackFlag cb_flag)
174{
175 ID *id = *idpoin;
176 if (id != nullptr && (cb_flag & IDWALK_CB_USER) != 0) {
177 id_us_min(id);
178 }
179}
180
182{
184
186 if (mti->foreach_ID_link) {
187 mti->foreach_ID_link(md, nullptr, modifier_free_data_id_us_cb, nullptr);
188 }
189 }
190
191 if (mti->free_data) {
192 mti->free_data(md);
193 }
194 if (md->error) {
195 MEM_freeN(md->error);
196 }
197
198 MEM_freeN(md);
199}
200
205
207{
208 BLI_assert(BLI_findindex(&ob->modifiers, md) != -1);
209
210 if (md->flag & eModifierFlag_Active) {
211 /* Prefer the previous modifier but use the next if this modifier is the first in the list. */
212 if (md->next != nullptr) {
214 }
215 else if (md->prev != nullptr) {
217 }
218 }
219
220 BLI_remlink(&ob->modifiers, md);
221}
222
224{
225 if (modifiers && md) {
227
229 modifiers, md, DATA_(mti->name), '.', offsetof(ModifierData, name), sizeof(md->name));
230 }
231}
232
234{
236
237 return mti->depends_on_time && mti->depends_on_time(scene, md);
238}
239
247
249{
251 if (md->type == type) {
252 return md;
253 }
254 }
255 return nullptr;
256}
257
259{
260 return static_cast<ModifierData *>(
262}
263
264ModifierData *BKE_modifiers_findby_persistent_uid(const Object *ob, const int persistent_uid)
265{
267 if (md->persistent_uid == persistent_uid) {
268 return md;
269 }
270 }
271 return nullptr;
272}
273
275{
277 if (md->error) {
278 MEM_freeN(md->error);
279 md->error = nullptr;
280 }
281 }
282}
283
284void BKE_modifiers_foreach_ID_link(Object *ob, IDWalkFunc walk, void *user_data)
285{
288
289 if (mti->foreach_ID_link) {
290 mti->foreach_ID_link(md, ob, walk, user_data);
291 }
292 }
293}
294
295void BKE_modifiers_foreach_tex_link(Object *ob, TexWalkFunc walk, void *user_data)
296{
299
300 if (mti->foreach_tex_link) {
301 mti->foreach_tex_link(md, ob, walk, user_data);
302 }
303 }
304}
305
307{
309
310 STRNCPY_UTF8(md_dst->name, md->name);
311 BKE_modifier_copydata_ex(md, md_dst, flag);
312
313 return md_dst;
314}
315
317 ModifierData *md_dst,
318 const int /*flag*/)
319{
321
322 /* `md_dst` may have already be fully initialized with some extra allocated data,
323 * we need to free it now to avoid a memory leak. */
324 if (mti->free_data) {
325 mti->free_data(md_dst);
326 }
327
328 const size_t data_size = sizeof(ModifierData);
329 const char *md_src_data = ((const char *)md_src) + data_size;
330 char *md_dst_data = ((char *)md_dst) + data_size;
331 BLI_assert(data_size <= size_t(mti->struct_size));
332 memcpy(md_dst_data, md_src_data, size_t(mti->struct_size) - data_size);
333
334 /* Runtime fields are never to be preserved. */
335 md_dst->runtime = nullptr;
336}
337
338static void modifier_copy_data_id_us_cb(void * /*user_data*/,
339 Object * /*ob*/,
340 ID **idpoin,
341 const LibraryForeachIDCallbackFlag cb_flag)
342{
343 ID *id = *idpoin;
344 if (id != nullptr && (cb_flag & IDWALK_CB_USER) != 0) {
345 id_us_plus(id);
346 }
347}
348
349void BKE_modifier_copydata_ex(const ModifierData *md, ModifierData *target, const int flag)
350{
352
353 target->mode = md->mode;
354 target->flag = md->flag;
355 target->ui_expand_flag = md->ui_expand_flag;
356 target->persistent_uid = md->persistent_uid;
357
358 if (mti->copy_data) {
359 mti->copy_data(md, target, flag);
360 }
361
363 if (mti->foreach_ID_link) {
364 mti->foreach_ID_link(target, nullptr, modifier_copy_data_id_us_cb, nullptr);
365 }
366 }
367}
368
370{
371 BKE_modifier_copydata_ex(md, target, 0);
372}
373
375{
377
378 return ((!mti->is_disabled || !mti->is_disabled(scene, md, false)) &&
380}
381
383{
385
386 return ((md->mode & eModifierMode_Realtime) && (md->mode & eModifierMode_Editmode) &&
387 (!mti->is_disabled || !mti->is_disabled(scene, md, false)) &&
389}
390
396
402
403void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *_format, ...)
404{
405 char buffer[512];
406 va_list ap;
407 const char *format = RPT_(_format);
408
409 va_start(ap, _format);
410 vsnprintf(buffer, sizeof(buffer), format, ap);
411 va_end(ap);
412 buffer[sizeof(buffer) - 1] = '\0';
413
414 if (md->error) {
415 MEM_freeN(md->error);
416 }
417
418 md->error = BLI_strdup(buffer);
419
420#ifndef NDEBUG
421 if ((md->mode & eModifierMode_Virtual) == 0) {
422 /* Ensure correct object is passed in. */
423 BLI_assert(BKE_modifier_get_original(ob, md) != nullptr);
424 }
425#endif
426
427 CLOG_WARN(&LOG, "Object: \"%s\", Modifier: \"%s\", %s", ob->id.name + 2, md->name, md->error);
428}
429
430void BKE_modifier_set_warning(const Object *ob, ModifierData *md, const char *_format, ...)
431{
432 char buffer[512];
433 va_list ap;
434 const char *format = RPT_(_format);
435
436 va_start(ap, _format);
437 vsnprintf(buffer, sizeof(buffer), format, ap);
438 va_end(ap);
439 buffer[sizeof(buffer) - 1] = '\0';
440
441 /* Store the warning in the same field as the error.
442 * It is not expected to have both error and warning and having a single place to store the
443 * message simplifies interface code. */
444
445 if (md->error) {
446 MEM_freeN(md->error);
447 }
448
449 md->error = BLI_strdup(buffer);
450
451#ifndef NDEBUG
452 if ((md->mode & eModifierMode_Virtual) == 0) {
453 /* Ensure correct object is passed in. */
454 BLI_assert(BKE_modifier_get_original(ob, md) != nullptr);
455 }
456#endif
457
459}
460
462 Object *ob,
463 int *r_lastPossibleCageIndex,
464 bool is_virtual)
465{
466 VirtualModifierData virtual_modifier_data;
467 ModifierData *md = (is_virtual) ?
468 BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data) :
469 static_cast<ModifierData *>(ob->modifiers.first);
470
471 if (r_lastPossibleCageIndex) {
472 /* ensure the value is initialized */
473 *r_lastPossibleCageIndex = -1;
474 }
475
476 /* Find the last modifier acting on the cage. */
477 int cageIndex = -1;
478 for (int i = 0; md; i++, md = md->next) {
480 bool supports_mapping;
481
482 if (mti->is_disabled && mti->is_disabled(scene, md, false)) {
483 continue;
484 }
486 continue;
487 }
489 continue;
490 }
491
492 supports_mapping = BKE_modifier_supports_mapping(md);
493 if (r_lastPossibleCageIndex && supports_mapping) {
494 *r_lastPossibleCageIndex = i;
495 }
496
497 if (!(md->mode & eModifierMode_Realtime)) {
498 continue;
499 }
500 if (!(md->mode & eModifierMode_Editmode)) {
501 continue;
502 }
503
504 if (!supports_mapping) {
505 break;
506 }
507
508 if (md->mode & eModifierMode_OnCage) {
509 cageIndex = i;
510 }
511 }
512
513 return cageIndex;
514}
515
516bool BKE_modifier_is_enabled(const Scene *scene, ModifierData *md, int required_mode)
517{
519
520 if ((md->mode & required_mode) != required_mode) {
521 return false;
522 }
523 if (scene != nullptr && mti->is_disabled &&
524 mti->is_disabled(scene, md, required_mode == eModifierMode_Render))
525 {
526 return false;
527 }
529 return false;
530 }
531 if ((required_mode & eModifierMode_Editmode) &&
533 {
534 return false;
535 }
536
537 return true;
538}
539
541{
542 return (ID_IS_OVERRIDE_LIBRARY(ob) &&
543 (md == nullptr || (md->flag & eModifierFlag_OverrideLibrary_Local) == 0));
544}
545
547 ModifierData *md,
548 CustomData_MeshMasks *final_datamask,
549 int required_mode)
550{
551 CDMaskLink *dataMasks = nullptr;
552 CDMaskLink *curr, *prev;
553 bool have_deform_modifier = false;
554
555 /* build a list of modifier data requirements in reverse order */
556 for (; md; md = md->next) {
558
559 curr = MEM_callocN<CDMaskLink>(__func__);
560
561 if (BKE_modifier_is_enabled(scene, md, required_mode)) {
563 have_deform_modifier = true;
564 }
565
566 if (mti->required_data_mask) {
567 mti->required_data_mask(md, &curr->mask);
568 }
569 }
570
571 if (!have_deform_modifier) {
572 /* Don't create orco layer when there is no deformation, we fall
573 * back to regular vertex coordinates */
574 curr->mask.vmask &= ~CD_MASK_ORCO;
575 }
576
577 /* prepend new datamask */
578 curr->next = dataMasks;
579 dataMasks = curr;
580 }
581
582 if (!have_deform_modifier) {
583 final_datamask->vmask &= ~CD_MASK_ORCO;
584 }
585
586 /* build the list of required data masks - each mask in the list must
587 * include all elements of the masks that follow it
588 *
589 * note the list is currently in reverse order, so "masks that follow it"
590 * actually means "masks that precede it" at the moment
591 */
592 for (curr = dataMasks, prev = nullptr; curr; prev = curr, curr = curr->next) {
593 if (prev) {
594 CustomData_MeshMasks_update(&curr->mask, &prev->mask);
595 }
596 else {
597 CustomData_MeshMasks_update(&curr->mask, final_datamask);
598 }
599 }
600
601 /* reverse the list so it's in the correct order */
602 BLI_linklist_reverse((LinkNode **)&dataMasks);
603
604 return dataMasks;
605}
606
608 VirtualModifierData *virtual_modifier_data)
609{
610 ModifierData *md = static_cast<ModifierData *>(ob->modifiers.first);
611
612 *virtual_modifier_data = virtualModifierCommonData;
613
614 if (ob->parent) {
615 if (ob->parent->type == OB_ARMATURE && ob->partype == PARSKEL) {
616 virtual_modifier_data->amd.object = ob->parent;
617 virtual_modifier_data->amd.modifier.next = md;
618 virtual_modifier_data->amd.deformflag = ((bArmature *)(ob->parent->data))->deformflag;
619 md = &virtual_modifier_data->amd.modifier;
620 }
621 else if (ob->parent->type == OB_CURVES_LEGACY && ob->partype == PARSKEL) {
622 virtual_modifier_data->cmd.object = ob->parent;
623 virtual_modifier_data->cmd.defaxis = ob->trackflag + 1;
624 virtual_modifier_data->cmd.modifier.next = md;
625 md = &virtual_modifier_data->cmd.modifier;
626 }
627 else if (ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) {
628 virtual_modifier_data->lmd.object = ob->parent;
629 virtual_modifier_data->lmd.modifier.next = md;
630 md = &virtual_modifier_data->lmd.modifier;
631 }
632 }
633
634 /* shape key modifier, not yet for curves */
635 if (ELEM(ob->type, OB_MESH, OB_LATTICE) && BKE_key_from_object((Object *)ob)) {
636 if (ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE)) {
637 virtual_modifier_data->smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage;
638 }
639 else {
641 }
642
643 virtual_modifier_data->smd.modifier.next = md;
644 md = &virtual_modifier_data->smd.modifier;
645 }
646
647 return md;
648}
649
651{
652 VirtualModifierData virtual_modifier_data;
653 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
654
655 Object *armature = nullptr;
656 /* return the first selected armature, this lets us use multiple armatures */
657 if (ob->type == OB_GREASE_PENCIL) {
658 for (; md; md = md->next) {
660 auto *amd = reinterpret_cast<GreasePencilArmatureModifierData *>(md);
661 armature = amd->object;
662 if (armature && (armature->base_flag & BASE_SELECTED)) {
663 return armature;
664 }
665 }
666 }
667 }
668 else {
669 for (; md; md = md->next) {
670 if (md->type == eModifierType_Armature) {
671 auto *amd = reinterpret_cast<ArmatureModifierData *>(md);
672 armature = amd->object;
673 if (armature && (armature->base_flag & BASE_SELECTED)) {
674 return armature;
675 }
676 }
677 }
678 }
679 /* If we're still here then return the last armature. */
680 return armature;
681}
682
684{
685 VirtualModifierData virtual_modifier_data;
686 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
687 MeshDeformModifierData *mdmd = nullptr;
688
689 /* return the first selected armature, this lets us use multiple armatures */
690 for (; md; md = md->next) {
691 if (md->type == eModifierType_MeshDeform) {
692 mdmd = (MeshDeformModifierData *)md;
693 if (mdmd->object && (mdmd->object->base_flag & BASE_SELECTED)) {
694 return mdmd->object;
695 }
696 }
697 }
698
699 if (mdmd) { /* if we're still here then return the last armature */
700 return mdmd->object;
701 }
702
703 return nullptr;
704}
705
707{
708 VirtualModifierData virtual_modifier_data;
709 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
710 LatticeModifierData *lmd = nullptr;
711
712 /* return the first selected lattice, this lets us use multiple lattices */
713 for (; md; md = md->next) {
714 if (md->type == eModifierType_Lattice) {
715 lmd = (LatticeModifierData *)md;
716 if (lmd->object && (lmd->object->base_flag & BASE_SELECTED)) {
717 return lmd->object;
718 }
719 }
720 }
721
722 if (lmd) { /* if we're still here then return the last lattice */
723 return lmd->object;
724 }
725
726 return nullptr;
727}
728
730{
731 VirtualModifierData virtual_modifier_data;
732 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
733 CurveModifierData *cmd = nullptr;
734
735 /* return the first selected curve, this lets us use multiple curves */
736 for (; md; md = md->next) {
737 if (md->type == eModifierType_Curve) {
738 cmd = (CurveModifierData *)md;
739 if (cmd->object && (cmd->object->base_flag & BASE_SELECTED)) {
740 return cmd->object;
741 }
742 }
743 }
744
745 if (cmd) { /* if we're still here then return the last curve */
746 return cmd->object;
747 }
748
749 return nullptr;
750}
751
753{
754 VirtualModifierData virtual_modifier_data;
755 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
756 MultiresModifierData *mmd = nullptr;
757
758 for (; md; md = md->next) {
759 if (md->type == eModifierType_Multires) {
760 mmd = (MultiresModifierData *)md;
761 if (mmd->totlvl != 0) {
762 return true;
763 }
764 }
765 }
766 return false;
767}
768
770{
771 VirtualModifierData virtual_modifier_data;
772 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
773
774 for (; md; md = md->next) {
775 if (md->type == eModifierType_Armature) {
776 ArmatureModifierData *amd = reinterpret_cast<ArmatureModifierData *>(md);
777 if (amd->object && amd->object->data == arm) {
778 return true;
779 }
780 }
783 md);
784 if (amd->object && amd->object->data == arm) {
785 return true;
786 }
787 }
788 }
789
790 return false;
791}
792
798
800{
801 VirtualModifierData virtual_modifier_data;
802 ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
803 int required_mode = eModifierMode_Realtime;
804
805 if (ob->mode == OB_MODE_EDIT) {
806 required_mode |= eModifierMode_Editmode;
807 }
808 for (; md; md = md->next) {
809 if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
810 /* pass */
811 }
813 return true;
814 }
815 }
816 return false;
817}
818
827
829{
830 /* just multires checked for now, since only multires
831 * modifies mesh data */
832
833 if (ob->type != OB_MESH) {
834 return;
835 }
836
838 if (md->type == eModifierType_Multires) {
840
842 }
843 }
844}
845
846const char *BKE_modifier_path_relbase(Main *bmain, Object *ob)
847{
848 /* - If the ID is from a library, return library path.
849 * - Else if the file has been saved return the blend file path.
850 * - Else if the file isn't saved and the ID isn't from a library, return the temp directory.
851 */
852 if ((bmain->filepath[0] != '\0') || ID_IS_LINKED(ob)) {
853 return ID_BLEND_PATH(bmain, &ob->id);
854 }
855
856 /* Last resort, better than using "" which resolves to the current working directory. */
857 return BKE_tempdir_session();
858}
859
864
865void BKE_modifier_path_init(char *path, int path_maxncpy, const char *name)
866{
867 const char *blendfile_path = BKE_main_blendfile_path_from_global();
868 BLI_path_join(path, path_maxncpy, blendfile_path[0] ? "//" : BKE_tempdir_session(), name);
869}
870
877{
878 switch (mesh->runtime->wrapper_type) {
880 blender::bke::EditMeshData &edit_data = *mesh->runtime->edit_data;
881 if (!edit_data.vert_positions.is_empty()) {
882 /* Note that 'ensure' is acceptable here since these values aren't modified in-place.
883 * If that changes we'll need to recalculate. */
884 BKE_editmesh_cache_ensure_vert_normals(*mesh->runtime->edit_mesh, edit_data);
885 }
886 else {
887 BM_mesh_normals_update(mesh->runtime->edit_mesh->bm);
888 }
889 break;
890 }
892 /* Not an expected case. */
893 break;
895 /* Normals are calculated lazily. */
896 break;
897 }
898}
899
900/* wrapper around ModifierTypeInfo.modify_mesh that ensures valid normals */
901
903{
905
906 if (mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
907 if ((mti->flags & eModifierTypeFlag_AcceptsBMesh) == 0) {
909 }
910 }
911
912 return mti->modify_mesh(md, ctx, mesh);
913}
914
916 const ModifierEvalContext *ctx,
917 Mesh *mesh,
919{
920 using namespace blender::bke;
922
923 if (mti->deform_verts) {
924 mti->deform_verts(md, ctx, mesh, positions);
925 if (mesh) {
926 mesh->tag_positions_changed();
927 }
928 return true;
929 }
930 /* Try to emulate #deform_verts by deforming a mesh. */
931 if (mti->modify_geometry_set) {
932 /* Prepare mesh with vertices at the given positions. */
934 if (mesh) {
936 }
937 else {
939 }
940 Mesh *mesh_to_deform = geometry.get_mesh_for_write();
941 mesh_to_deform->vert_positions_for_write().copy_from(positions);
942 mesh_to_deform->tag_positions_changed();
943
944 /* Remember the topology of the mesh before passing it to the modifier. */
945 const MeshTopologyState old_topology{*mesh_to_deform};
946
947 /* Call the modifier and "hope" that it just deforms the mesh. */
948 mti->modify_geometry_set(md, ctx, &geometry);
949
950 /* Extract the deformed vertex positions if the topology has not changed. */
951 if (const Mesh *deformed_mesh = geometry.get_mesh()) {
952 if (old_topology.same_topology_as(*deformed_mesh)) {
953 positions.copy_from(deformed_mesh->vert_positions());
954 if (mesh) {
955 mesh->tag_positions_changed();
956 }
957 return true;
958 }
959 }
960 }
961 return false;
962}
963
965 const ModifierEvalContext *ctx,
966 const BMEditMesh *em,
967 Mesh *mesh,
969{
971 if (mesh && mti->depends_on_normals && mti->depends_on_normals(md)) {
973 }
974 mti->deform_verts_EM(md, ctx, em, mesh, positions);
975}
976
977/* end modifier callback wrappers */
978
980{
981 if (!DEG_object_geometry_is_evaluated(*ob_eval)) {
982 return nullptr;
983 }
984
985 Mesh *mesh = nullptr;
986
987 if ((ob_eval->type == OB_MESH) && (ob_eval->mode & OB_MODE_EDIT)) {
988 /* In EditMode, evaluated mesh is stored in BMEditMesh, not the object... */
989 const BMEditMesh *em = BKE_editmesh_from_object(ob_eval);
990 /* 'em' might not exist yet in some cases, just after loading a .blend file, see #57878. */
991 if (em != nullptr) {
992 mesh = const_cast<Mesh *>(BKE_object_get_editmesh_eval_final(ob_eval));
993 if (mesh != nullptr) {
995 }
996 }
997 }
998 if (mesh == nullptr) {
1000 }
1001
1002 return mesh;
1003}
1004
1006{
1007 const Object *object_orig = DEG_get_original((Object *)object);
1008 return BKE_modifiers_findby_persistent_uid(object_orig, md->persistent_uid);
1009}
1010
1012{
1013 Object *object_eval = DEG_get_evaluated(depsgraph, object);
1014 if (object_eval == object) {
1015 return md;
1016 }
1017 return BKE_modifiers_findby_persistent_uid(object_eval, md->persistent_uid);
1018}
1019
1021{
1023 if (ID_IS_LINKED(&object)) {
1025 blender::StringRef(object.id.lib->runtime->filepath_abs));
1026 }
1027 if (ID_IS_OVERRIDE_LIBRARY_REAL(&object)) {
1028 BLI_assert(ID_IS_LINKED(object.id.override_library->reference));
1030 hash,
1031 blender::StringRef(object.id.override_library->reference->lib->runtime->filepath_abs));
1032 }
1033 blender::RandomNumberGenerator rng{uint32_t(hash)};
1034 while (true) {
1035 const int new_uid = rng.get_int32();
1036 if (new_uid <= 0) {
1037 continue;
1038 }
1039 if (BKE_modifiers_findby_persistent_uid(&object, new_uid) != nullptr) {
1040 continue;
1041 }
1042 md.persistent_uid = new_uid;
1043 break;
1044 }
1045}
1046
1048{
1049 blender::Set<int> uids;
1050 int modifiers_num = 0;
1051 LISTBASE_FOREACH (const ModifierData *, md, &object.modifiers) {
1052 if (md->persistent_uid <= 0) {
1053 return false;
1054 }
1055 uids.add(md->persistent_uid);
1056 modifiers_num++;
1057 }
1058 if (uids.size() != modifiers_num) {
1059 return false;
1060 }
1061 return true;
1062}
1063
1064void BKE_modifier_blend_write(BlendWriter *writer, const ID *id_owner, ListBase *modbase)
1065{
1066 if (modbase == nullptr) {
1067 return;
1068 }
1069
1070 LISTBASE_FOREACH (ModifierData *, md, modbase) {
1071 const ModifierTypeInfo *mti = BKE_modifier_get_info(ModifierType(md->type));
1072 if (mti == nullptr) {
1073 continue;
1074 }
1075
1076 /* If the blend_write callback is defined, it should handle the whole writing process. */
1077 if (mti->blend_write != nullptr) {
1078 mti->blend_write(writer, id_owner, md);
1079 continue;
1080 }
1081
1082 BLO_write_struct_by_name(writer, mti->struct_name, md);
1083
1084 if (md->type == eModifierType_Cloth) {
1086
1090 BKE_ptcache_blend_write(writer, &clmd->ptcaches);
1091 }
1092 else if (md->type == eModifierType_Fluid) {
1094
1095 if (fmd->type & MOD_FLUID_TYPE_DOMAIN) {
1097
1098 if (fmd->domain) {
1099 BKE_ptcache_blend_write(writer, &(fmd->domain->ptcaches[0]));
1100
1101 /* create fake pointcache so that old blender versions can read it */
1102 fmd->domain->point_cache[1] = BKE_ptcache_add(&fmd->domain->ptcaches[1]);
1104 fmd->domain->point_cache[1]->step = 1;
1105
1106 BKE_ptcache_blend_write(writer, &(fmd->domain->ptcaches[1]));
1107
1108 if (fmd->domain->coba) {
1109 BLO_write_struct(writer, ColorBand, fmd->domain->coba);
1110 }
1111
1112 /* cleanup the fake pointcache */
1114 fmd->domain->point_cache[1] = nullptr;
1115
1117 }
1118 }
1119 else if (fmd->type & MOD_FLUID_TYPE_FLOW) {
1121 }
1122 else if (fmd->type & MOD_FLUID_TYPE_EFFEC) {
1124 }
1125 }
1126 else if (md->type == eModifierType_Fluidsim) {
1127 BLI_assert_unreachable(); /* Deprecated data, should never be written. */
1128 }
1129 else if (md->type == eModifierType_DynamicPaint) {
1131
1132 if (pmd->canvas) {
1134
1135 /* write surfaces */
1137 BLO_write_struct(writer, DynamicPaintSurface, surface);
1138 }
1139 /* write caches and effector weights */
1141 BKE_ptcache_blend_write(writer, &(surface->ptcaches));
1142
1143 BLO_write_struct(writer, EffectorWeights, surface->effector_weights);
1144 }
1145 }
1146 if (pmd->brush) {
1149 BLO_write_struct(writer, ColorBand, pmd->brush->vel_ramp);
1150 }
1151 }
1152 else if (md->type == eModifierType_Collision) {
1153
1154#if 0
1156 /* TODO: CollisionModifier should use pointcache
1157 * + have proper reset events before enabling this. */
1158 writestruct(wd, DATA, float[3], collmd->numverts, collmd->x);
1159 writestruct(wd, DATA, float[3], collmd->numverts, collmd->xnew);
1160 writestruct(wd, DATA, MFace, collmd->numfaces, collmd->mfaces);
1161#endif
1162 }
1163 }
1164}
1165
1166/* TODO(sergey): Find a better place for this.
1167 *
1168 * Unfortunately, this can not be done as a regular do_versions() since the modifier type is
1169 * set to NONE, so the do_versions code wouldn't know where the modifier came from.
1170 *
1171 * The best approach seems to have the functionality in `versioning_280.cc` but still call the
1172 * function from #BKE_modifier_blend_read_data().
1173 */
1174
1175/* Domain, inflow, ... */
1176static void modifier_ensure_type(FluidModifierData *fluid_modifier_data, int type)
1177{
1178 fluid_modifier_data->type = type;
1179 BKE_fluid_modifier_free(fluid_modifier_data);
1180 BKE_fluid_modifier_create_type_data(fluid_modifier_data);
1181}
1182
1189 Object *object,
1190 ListBase *modifiers,
1191 ModifierData *old_modifier_data)
1192{
1194 FluidModifierData *fluid_modifier_data = (FluidModifierData *)new_modifier_data;
1195
1196 if (old_modifier_data->type == eModifierType_Fluidsim) {
1197 FluidsimModifierData *old_fluidsim_modifier_data = (FluidsimModifierData *)old_modifier_data;
1198 /* Only get access to the data, do not mark it as used, otherwise there will be memory leak
1199 * since readfile code won't free it. */
1200 FluidsimSettings *old_fluidsim_settings = static_cast<FluidsimSettings *>(
1202 reader, old_fluidsim_modifier_data->fss, sizeof(FluidsimSettings)));
1203 switch (old_fluidsim_settings->type) {
1204 case OB_FLUIDSIM_ENABLE:
1205 modifier_ensure_type(fluid_modifier_data, 0);
1206 break;
1207 case OB_FLUIDSIM_DOMAIN:
1208 modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_DOMAIN);
1209 BKE_fluid_domain_type_set(object, fluid_modifier_data->domain, FLUID_DOMAIN_TYPE_LIQUID);
1210 break;
1211 case OB_FLUIDSIM_FLUID:
1212 modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_FLOW);
1213 BKE_fluid_flow_type_set(object, fluid_modifier_data->flow, FLUID_FLOW_TYPE_LIQUID);
1214 /* No need to emit liquid far away from surface. */
1215 fluid_modifier_data->flow->surface_distance = 0.0f;
1216 break;
1218 modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_EFFEC);
1220 object, fluid_modifier_data->effector, FLUID_EFFECTOR_TYPE_COLLISION);
1221 break;
1222 case OB_FLUIDSIM_INFLOW:
1223 modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_FLOW);
1224 BKE_fluid_flow_type_set(object, fluid_modifier_data->flow, FLUID_FLOW_TYPE_LIQUID);
1225 BKE_fluid_flow_behavior_set(object, fluid_modifier_data->flow, FLUID_FLOW_BEHAVIOR_INFLOW);
1226 /* No need to emit liquid far away from surface. */
1227 fluid_modifier_data->flow->surface_distance = 0.0f;
1228 break;
1230 modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_FLOW);
1231 BKE_fluid_flow_type_set(object, fluid_modifier_data->flow, FLUID_FLOW_TYPE_LIQUID);
1233 object, fluid_modifier_data->flow, FLUID_FLOW_BEHAVIOR_OUTFLOW);
1234 break;
1236 /* "Particle" type objects not being used by Mantaflow fluid simulations.
1237 * Skip this object, secondary particles can only be enabled through the domain object. */
1238 break;
1240 /* "Control" type objects not being used by Mantaflow fluid simulations.
1241 * Use guiding type instead which is similar. */
1242 modifier_ensure_type(fluid_modifier_data, MOD_FLUID_TYPE_EFFEC);
1244 object, fluid_modifier_data->effector, FLUID_EFFECTOR_TYPE_GUIDE);
1245 break;
1246 }
1247 }
1248 else if (old_modifier_data->type == eModifierType_Smoke) {
1249 SmokeModifierData *old_smoke_modifier_data = (SmokeModifierData *)old_modifier_data;
1250 modifier_ensure_type(fluid_modifier_data, old_smoke_modifier_data->type);
1251 if (fluid_modifier_data->type == MOD_FLUID_TYPE_DOMAIN) {
1252 BKE_fluid_domain_type_set(object, fluid_modifier_data->domain, FLUID_DOMAIN_TYPE_GAS);
1253 }
1254 else if (fluid_modifier_data->type == MOD_FLUID_TYPE_FLOW) {
1255 BKE_fluid_flow_type_set(object, fluid_modifier_data->flow, FLUID_FLOW_TYPE_SMOKE);
1256 }
1257 else if (fluid_modifier_data->type == MOD_FLUID_TYPE_EFFEC) {
1259 object, fluid_modifier_data->effector, FLUID_EFFECTOR_TYPE_COLLISION);
1260 }
1261 }
1262
1263 /* Replace modifier data in the stack. */
1264 new_modifier_data->next = old_modifier_data->next;
1265 new_modifier_data->prev = old_modifier_data->prev;
1266 if (new_modifier_data->prev != nullptr) {
1267 new_modifier_data->prev->next = new_modifier_data;
1268 }
1269 if (new_modifier_data->next != nullptr) {
1270 new_modifier_data->next->prev = new_modifier_data;
1271 }
1272 if (modifiers->first == old_modifier_data) {
1273 modifiers->first = new_modifier_data;
1274 }
1275 if (modifiers->last == old_modifier_data) {
1276 modifiers->last = new_modifier_data;
1277 }
1278
1279 /* Free old modifier data. */
1280 MEM_freeN(old_modifier_data);
1281
1282 return new_modifier_data;
1283}
1284
1286{
1288
1289 LISTBASE_FOREACH (ModifierData *, md, lb) {
1290 md->error = nullptr;
1291 md->runtime = nullptr;
1292
1293 /* If linking from a library, clear 'local' library override flag. */
1294 if (ID_IS_LINKED(ob)) {
1296 }
1297
1298 /* Modifier data has been allocated as a part of data migration process and
1299 * no reading of nested fields from file is needed. */
1300 bool is_allocated = false;
1301
1302 if (md->type == eModifierType_Fluidsim) {
1304 BLO_read_data_reports(reader),
1306 RPT_("Possible data loss when saving this file! %s modifier is deprecated (Object: %s)"),
1307 md->name,
1308 ob->id.name + 2);
1309 md = modifier_replace_with_fluid(reader, ob, lb, md);
1310 is_allocated = true;
1311 }
1312 else if (md->type == eModifierType_Smoke) {
1314 BLO_read_data_reports(reader),
1316 RPT_("Possible data loss when saving this file! %s modifier is deprecated (Object: %s)"),
1317 md->name,
1318 ob->id.name + 2);
1319 md = modifier_replace_with_fluid(reader, ob, lb, md);
1320 is_allocated = true;
1321 }
1322
1323 const ModifierTypeInfo *mti = BKE_modifier_get_info(ModifierType(md->type));
1324
1325 /* if modifiers disappear, or for upward compatibility */
1326 if (mti == nullptr) {
1327 md->type = eModifierType_None;
1328 }
1329
1330 if (is_allocated) {
1331 /* All the fields has been properly allocated. */
1332 }
1333 else if (md->type == eModifierType_Cloth) {
1335
1336 clmd->clothObject = nullptr;
1337 clmd->hairdata = nullptr;
1338
1341
1342 BKE_ptcache_blend_read_data(reader, &clmd->ptcaches, &clmd->point_cache, 0);
1343
1344 if (clmd->sim_parms) {
1345 if (clmd->sim_parms->presets > 10) {
1346 clmd->sim_parms->presets = 0;
1347 }
1348
1349 clmd->sim_parms->reset = 0;
1350
1352
1353 if (!clmd->sim_parms->effector_weights) {
1355 }
1356 }
1357
1358 clmd->solver_result = nullptr;
1359 }
1360 else if (md->type == eModifierType_Fluid) {
1361
1363
1364 if (fmd->type == MOD_FLUID_TYPE_DOMAIN) {
1365 fmd->flow = nullptr;
1366 fmd->effector = nullptr;
1368 fmd->domain->fmd = fmd;
1369
1370 fmd->domain->fluid = nullptr;
1372 fmd->domain->tex_density = nullptr;
1373 fmd->domain->tex_color = nullptr;
1374 fmd->domain->tex_shadow = nullptr;
1375 fmd->domain->tex_flame = nullptr;
1376 fmd->domain->tex_flame_coba = nullptr;
1377 fmd->domain->tex_coba = nullptr;
1378 fmd->domain->tex_field = nullptr;
1379 fmd->domain->tex_velocity_x = nullptr;
1380 fmd->domain->tex_velocity_y = nullptr;
1381 fmd->domain->tex_velocity_z = nullptr;
1382 fmd->domain->tex_wt = nullptr;
1383 BLO_read_struct(reader, ColorBand, &fmd->domain->coba);
1384
1386 if (!fmd->domain->effector_weights) {
1388 }
1389
1391 reader, &(fmd->domain->ptcaches[0]), &(fmd->domain->point_cache[0]), 1);
1392
1393 /* Manta sim uses only one cache from now on, so store pointer convert */
1394 if (fmd->domain->ptcaches[1].first || fmd->domain->point_cache[1]) {
1395 if (fmd->domain->point_cache[1]) {
1397 reader, fmd->domain->point_cache[1], sizeof(PointCache)));
1398 if (cache->flag & PTCACHE_FAKE_SMOKE) {
1399 /* Manta-sim/smoke was already saved in "new format" and this cache is a fake one. */
1400 }
1401 else {
1402 printf(
1403 "High resolution manta cache not available due to pointcache update. Please "
1404 "reset the simulation.\n");
1405 }
1406 }
1408 fmd->domain->point_cache[1] = nullptr;
1409 }
1410
1411 /* Flag for refreshing the simulation after loading */
1413 }
1414 else if (fmd->type == MOD_FLUID_TYPE_FLOW) {
1415 fmd->domain = nullptr;
1416 fmd->effector = nullptr;
1417 BLO_read_struct(reader, FluidFlowSettings, &fmd->flow);
1418 fmd->flow->fmd = fmd;
1419 fmd->flow->mesh = nullptr;
1420 fmd->flow->verts_old = nullptr;
1421 fmd->flow->numverts = 0;
1422 BLO_read_struct(reader, ParticleSystem, &fmd->flow->psys);
1423
1425 }
1426 else if (fmd->type == MOD_FLUID_TYPE_EFFEC) {
1427 fmd->flow = nullptr;
1428 fmd->domain = nullptr;
1430 if (fmd->effector) {
1431 fmd->effector->fmd = fmd;
1432 fmd->effector->verts_old = nullptr;
1433 fmd->effector->numverts = 0;
1434 fmd->effector->mesh = nullptr;
1435
1437 }
1438 else {
1439 fmd->type = 0;
1440 fmd->flow = nullptr;
1441 fmd->domain = nullptr;
1442 fmd->effector = nullptr;
1443 }
1444 }
1445 }
1446 else if (md->type == eModifierType_DynamicPaint) {
1448
1449 if (pmd->canvas) {
1451 pmd->canvas->pmd = pmd;
1452 pmd->canvas->flags &= ~MOD_DPAINT_BAKING; /* just in case */
1453
1454 if (pmd->canvas->surfaces.first) {
1456
1458 surface->canvas = pmd->canvas;
1459 surface->data = nullptr;
1460 BKE_ptcache_blend_read_data(reader, &(surface->ptcaches), &(surface->pointcache), 1);
1461
1462 BLO_read_struct(reader, EffectorWeights, &surface->effector_weights);
1463 if (surface->effector_weights == nullptr) {
1464 surface->effector_weights = BKE_effector_add_weights(nullptr);
1465 }
1466 }
1467 }
1468 }
1469 if (pmd->brush) {
1471 pmd->brush->pmd = pmd;
1472 BLO_read_struct(reader, ParticleSystem, &pmd->brush->psys);
1473 BLO_read_struct(reader, ColorBand, &pmd->brush->paint_ramp);
1474 BLO_read_struct(reader, ColorBand, &pmd->brush->vel_ramp);
1475 }
1476 }
1477
1478 if ((mti != nullptr) && (mti->blend_read != nullptr)) {
1479 mti->blend_read(reader, md);
1480 }
1481 }
1482}
1483
1484namespace blender::bke {
1485
1486using Clock = std::chrono::high_resolution_clock;
1487
1489{
1490 return std::chrono::duration<double, std::chrono::seconds::period>(
1491 Clock::now().time_since_epoch())
1492 .count();
1493}
1494
1499
1501{
1502 const double end_time = get_current_time_in_seconds();
1503 const double duration = end_time - start_time_;
1504 md_.execution_time = duration;
1505}
1506
1507} // namespace blender::bke
void CustomData_MeshMasks_update(CustomData_MeshMasks *mask_dst, const CustomData_MeshMasks *mask_src)
Definition customdata.cc:96
BMEditMesh * BKE_editmesh_from_object(Object *ob)
Return the BMEditMesh for a given object.
Definition editmesh.cc:61
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:58
void BKE_fluid_flow_behavior_set(struct Object *object, struct FluidFlowSettings *settings, int behavior)
Definition fluid.cc:4585
void BKE_fluid_effector_type_set(struct Object *object, struct FluidEffectorSettings *settings, int type)
Definition fluid.cc:4605
void BKE_fluid_domain_type_set(struct Object *object, struct FluidDomainSettings *settings, int type)
Definition fluid.cc:4558
void BKE_fluid_modifier_create_type_data(struct FluidModifierData *fmd)
Definition fluid.cc:4775
void BKE_fluid_flow_type_set(struct Object *object, struct FluidFlowSettings *settings, int type)
Definition fluid.cc:4590
void BKE_fluid_modifier_free(struct FluidModifierData *fmd)
Definition fluid.cc:4764
#define G_MAIN
Key * BKE_key_from_object(Object *ob)
Definition key.cc:1791
void id_us_plus(ID *id)
Definition lib_id.cc:358
@ LIB_ID_CREATE_NO_USER_REFCOUNT
void id_us_min(ID *id)
Definition lib_id.cc:366
LibraryForeachIDCallbackFlag
@ IDWALK_CB_USER
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:892
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
@ ME_WRAPPER_TYPE_MDATA
@ ME_WRAPPER_TYPE_SUBD
@ ME_WRAPPER_TYPE_BMESH
void BKE_mesh_wrapper_ensure_mdata(Mesh *mesh)
Mesh * BKE_mesh_wrapper_ensure_subdivision(Mesh *mesh)
#define MODIFIER_TYPE_PANEL_PREFIX
void(*)(void *user_data, Object *ob, ID **idpoin, LibraryForeachIDCallbackFlag cb_flag) IDWalkFunc
@ eModifierTypeFlag_AcceptsBMesh
@ eModifierTypeFlag_SupportsMapping
@ eModifierTypeFlag_EnableInEditmode
@ eModifierTypeFlag_SupportsEditmode
bool BKE_modifier_supports_mapping(ModifierData *md)
void(*)(void *user_data, Object *ob, ModifierData *md, const PointerRNA *ptr, PropertyRNA *texture_prop) TexWalkFunc
void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *ob)
Definition multires.cc:385
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)
@ RPT_WARNING
Definition BKE_report.hh:38
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
#define BLI_path_join(...)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.cc:41
#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:5703
BlendFileReadReport * BLO_read_data_reports(BlendDataReader *reader)
Definition readfile.cc:5978
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:189
bool DEG_object_geometry_is_evaluated(const Object &object)
T * DEG_get_original(T *id)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
Definition DNA_ID.h:723
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:694
#define ID_BLEND_PATH(_bmain, _id)
Definition DNA_ID.h:685
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:730
#define CD_MASK_ORCO
@ MOD_DPAINT_BAKING
@ FLUID_FLOW_NEEDS_UPDATE
@ FLUID_FLOW_TYPE_LIQUID
@ FLUID_FLOW_TYPE_SMOKE
@ FLUID_DOMAIN_TYPE_GAS
@ FLUID_DOMAIN_TYPE_LIQUID
@ FLUID_EFFECTOR_NEEDS_UPDATE
@ FLUID_DOMAIN_FILE_LOAD
@ FLUID_FLOW_BEHAVIOR_OUTFLOW
@ FLUID_FLOW_BEHAVIOR_INFLOW
@ FLUID_EFFECTOR_TYPE_GUIDE
@ FLUID_EFFECTOR_TYPE_COLLISION
@ 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
@ 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:202
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)
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)
static void modifier_copy_data_id_us_cb(void *, Object *, ID **idpoin, const LibraryForeachIDCallbackFlag cb_flag)
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 void modifier_free_data_id_us_cb(void *, Object *, ID **idpoin, const LibraryForeachIDCallbackFlag cb_flag)
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()
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 VirtualModifierData virtualModifierCommonData
bool BKE_modifier_deform_verts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, blender::MutableSpan< blender::float3 > positions)
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_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)
BPy_StructRNA * depsgraph
unsigned long long int uint64_t
constexpr int64_t size() const
Definition BLI_span.hh:493
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:739
int64_t size() const
Definition BLI_set.hh:587
bool add(const Key &key)
Definition BLI_set.hh:248
bool same_topology_as(const Mesh &mesh) const
#define offsetof(t, d)
#define DATA(_y, _x)
static void modifier_free_data_id_us_cb(void *, Object *, ID **idpoin, const LibraryForeachIDCallbackFlag cb_flag)
#define printf(...)
format
#define LOG(level)
Definition log.h:97
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static double get_current_time_in_seconds()
std::chrono::high_resolution_clock Clock
uint64_t get_default_hash(const T &v, const Args &...args)
Definition BLI_hash.hh:233
#define hash
Definition noise_c.cc:154
const char * name
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
GPUTexture * tex_velocity_z
GPUTexture * tex_velocity_y
struct PointCache * point_cache[2]
GPUTexture * tex_flame_coba
struct ColorBand * coba
GPUTexture * tex_velocity_x
struct EffectorWeights * effector_weights
struct FluidModifierData * fmd
struct FluidModifierData * fmd
struct ParticleSystem * psys
struct FluidDomainSettings * domain
struct FluidEffectorSettings * effector
struct FluidFlowSettings * flow
struct FluidsimSettings * fss
static GeometrySet from_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
void * last
void * first
char filepath[1024]
Definition BKE_main.hh:179
MeshRuntimeHandle * runtime
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(* modify_geometry_set)(ModifierData *md, const ModifierEvalContext *ctx, blender::bke::GeometrySet *geometry_set)
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
i
Definition text_draw.cc:230
static DynamicLibrary lib
uint8_t flag
Definition wm_window.cc:145
#define writestruct(wd, filecode, struct_id, nr, adr)