Blender V4.5
deg_eval_runtime_backup_object.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2019 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BLI_session_uid.h"
10
12
13#include <cstring>
14
15#include "DNA_mesh_types.h"
16
17#include "BLI_listbase.h"
18
19#include "BKE_action.hh"
20#include "BKE_mesh_types.hh"
21#include "BKE_modifier.hh"
22#include "BKE_object.hh"
23#include "BKE_object_types.hh"
24
25namespace blender::deg {
26
29{
30 /* TODO(sergey): Use something like BKE_object_runtime_reset(). */
31 runtime = {};
32}
33
35{
36 /* Store evaluated mesh and curve_cache, and make sure we don't free it. */
37 runtime = *object->runtime;
38 if (object->light_linking) {
39 light_linking_runtime = object->light_linking->runtime;
40 }
42 /* Keep bounding-box (for now at least). */
43 object->runtime->bounds_eval = runtime.bounds_eval;
44 /* Object update will override actual object->data to an evaluated version.
45 * Need to make sure we don't have data set to evaluated one before free
46 * anything. */
47 object->data = runtime.data_orig;
48 /* Make a backup of base flags. */
49 base_flag = object->base_flag;
50 base_local_view_bits = object->base_local_view_bits;
51 /* Backup runtime data of all modifiers. */
53 /* Backup runtime data of all pose channels. */
55}
56
58{
59 LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) {
60 if (modifier_data->runtime == nullptr) {
61 continue;
62 }
63
64 modifier_runtime_data.add(modifier_data->persistent_uid, ModifierDataBackup(modifier_data));
65 modifier_data->runtime = nullptr;
66 }
67}
68
70{
71 if (object->pose != nullptr) {
72 LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
73 const SessionUID &session_uid = pchan->runtime.session_uid;
75
76 pose_channel_runtime_data.add(session_uid, pchan->runtime);
77 BKE_pose_channel_runtime_reset(&pchan->runtime);
78 }
79 }
80}
81
83{
84 ID *data_orig = object->runtime->data_orig;
85 ID *data_eval = runtime.data_eval;
86 std::optional<Bounds<float3>> bounds = object->runtime->bounds_eval;
87 *object->runtime = runtime;
88 object->runtime->data_orig = data_orig;
89 object->runtime->bounds_eval = bounds;
90 if (ELEM(object->type, OB_MESH, OB_LATTICE, OB_CURVES_LEGACY, OB_FONT) && data_eval != nullptr) {
91 if (object->id.recalc & ID_RECALC_GEOMETRY) {
92 /* If geometry is tagged for update it means, that part of
93 * evaluated mesh are not valid anymore. In this case we can not
94 * have any "persistent" pointers to point to an invalid data.
95 *
96 * We restore object's data datablock to an original copy of
97 * that datablock. */
98 object->data = data_orig;
99
100 /* After that, immediately free the invalidated caches. */
102 }
103 else {
104 /* Do same thing as object update: override actual object data pointer with evaluated
105 * datablock, but only if the evaluated data has the same type as the original data. */
106 if (GS(((ID *)object->data)->name) == GS(data_eval->name)) {
107 object->data = data_eval;
108 }
109
110 /* Evaluated mesh simply copied edit_mesh pointer from
111 * original mesh during update, need to make sure no dead
112 * pointers are left behind. */
113 if (object->type == OB_MESH) {
114 Mesh *mesh_eval = (Mesh *)data_eval;
115 Mesh *mesh_orig = (Mesh *)data_orig;
116 mesh_eval->runtime->edit_mesh = mesh_orig->runtime->edit_mesh;
117 }
118 }
119 }
121 if (object->id.recalc & ID_RECALC_GEOMETRY) {
122 /* Free evaluated caches. */
123 object->data = data_orig;
125 }
126 else {
127 object->data = object->runtime->data_eval;
128 }
129 }
130
132 /* Lazily allocate light linking on the evaluated object for the cases when the object is only
133 * a receiver or a blocker and does not need its own LightLinking on the original object. */
134 if (!object->light_linking) {
135 object->light_linking = MEM_callocN<LightLinking>(__func__);
136 }
137 object->light_linking->runtime = *light_linking_runtime;
138 }
139
140 object->base_flag = base_flag;
141 object->base_local_view_bits = base_local_view_bits;
142
143 /* Restore modifier's runtime data.
144 * NOTE: Data of unused modifiers will be freed there. */
147}
148
150{
151 LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) {
152 std::optional<ModifierDataBackup> backup = modifier_runtime_data.pop_try(
153 modifier_data->persistent_uid);
154 if (backup.has_value()) {
155 modifier_data->runtime = backup->runtime;
156 }
157 }
158
159 for (ModifierDataBackup &backup : modifier_runtime_data.values()) {
160 const ModifierTypeInfo *modifier_type_info = BKE_modifier_get_info(backup.type);
161 BLI_assert(modifier_type_info != nullptr);
162 modifier_type_info->free_runtime_data(backup.runtime);
163
164 if (backup.type == eModifierType_Subsurf) {
165 if (object->type == OB_MESH) {
166 Mesh *mesh = (Mesh *)object->data;
167 if (mesh->runtime->subsurf_runtime_data == backup.runtime) {
168 mesh->runtime->subsurf_runtime_data = nullptr;
169 }
170 }
171 }
172 }
173}
174
176{
177 if (object->pose != nullptr) {
178 LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
179 const SessionUID &session_uid = pchan->runtime.session_uid;
180 std::optional<bPoseChannel_Runtime> runtime = pose_channel_runtime_data.pop_try(session_uid);
181 if (runtime.has_value()) {
182 pchan->runtime = *runtime;
183 }
184 }
185 }
188 }
189}
190
191} // namespace blender::deg
Blender kernel action and pose functionality.
void BKE_pose_channel_runtime_free(bPoseChannel_Runtime *runtime) ATTR_NONNULL(1)
void BKE_pose_channel_runtime_reset(bPoseChannel_Runtime *runtime) ATTR_NONNULL(1)
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
General operations, lookup, etc. for blender objects.
void BKE_object_runtime_reset(Object *object)
void BKE_object_free_derived_caches(Object *ob)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
bool BLI_session_uid_is_generated(const SessionUID *uid)
#define ELEM(...)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:982
@ eModifierType_Subsurf
@ OB_LATTICE
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
@ OB_CURVES
Map< SessionUID, bPoseChannel_Runtime > pose_channel_runtime_data
Map< int, ModifierDataBackup > modifier_runtime_data
std::optional< LightLinkingRuntime > light_linking_runtime
#define GS(a)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
Definition DNA_ID.h:404
unsigned int recalc
Definition DNA_ID.h:427
char name[66]
Definition DNA_ID.h:415
struct ID_Runtime runtime
Definition DNA_ID.h:493
MeshRuntimeHandle * runtime
void(* free_runtime_data)(void *runtime_data)
struct bPose * pose
ListBase modifiers
LightLinking * light_linking
ListBase chanbase