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