Blender V5.0
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_light_linking.h"
21#include "BKE_mesh_types.hh"
22#include "BKE_modifier.hh"
23#include "BKE_object.hh"
24#include "BKE_object_types.hh"
25
26namespace blender::deg {
27
30{
31 /* TODO(sergey): Use something like BKE_object_runtime_reset(). */
32 runtime = {};
33}
34
36{
37 /* Store evaluated mesh and curve_cache, and make sure we don't free it. */
38 runtime = *object->runtime;
39 if (object->light_linking) {
40 light_linking_runtime = object->light_linking->runtime;
41 }
43 /* Keep bounding-box (for now at least). */
44 object->runtime->bounds_eval = runtime.bounds_eval;
45 /* Object update will override actual object->data to an evaluated version.
46 * Need to make sure we don't have data set to evaluated one before free
47 * anything. */
48 object->data = runtime.data_orig;
49 /* Make a backup of base flags. */
50 base_flag = object->base_flag;
51 base_local_view_bits = object->base_local_view_bits;
52 /* Backup runtime data of all modifiers. */
54 /* Backup runtime data of all pose channels. */
56}
57
59{
60 LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) {
61 if (modifier_data->runtime == nullptr) {
62 continue;
63 }
64
65 modifier_runtime_data.add(modifier_data->persistent_uid, ModifierDataBackup(modifier_data));
66 modifier_data->runtime = nullptr;
67 }
68}
69
71{
72 if (object->pose != nullptr) {
73 LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
74 const SessionUID &session_uid = pchan->runtime.session_uid;
76
77 pose_channel_runtime_data.add(session_uid, pchan->runtime);
78 BKE_pose_channel_runtime_reset(&pchan->runtime);
79 }
80 }
81}
82
84{
85 ID *data_orig = object->runtime->data_orig;
86 ID *data_eval = runtime.data_eval;
87 std::optional<Bounds<float3>> bounds = object->runtime->bounds_eval;
88 *object->runtime = runtime;
89 object->runtime->data_orig = data_orig;
90 object->runtime->bounds_eval = bounds;
91 if (ELEM(object->type, OB_MESH, OB_LATTICE, OB_CURVES_LEGACY, OB_FONT) && data_eval != nullptr) {
92 if (object->id.recalc & ID_RECALC_GEOMETRY) {
93 /* If geometry is tagged for update it means, that part of
94 * evaluated mesh are not valid anymore. In this case we can not
95 * have any "persistent" pointers to point to an invalid data.
96 *
97 * We restore object's data datablock to an original copy of
98 * that datablock. */
99 object->data = data_orig;
100
101 /* After that, immediately free the invalidated caches. */
103 }
104 else {
105 /* Do same thing as object update: override actual object data pointer with evaluated
106 * datablock, but only if the evaluated data has the same type as the original data. */
107 if (GS(((ID *)object->data)->name) == GS(data_eval->name)) {
108 object->data = data_eval;
109 }
110
111 /* Evaluated mesh simply copied edit_mesh pointer from
112 * original mesh during update, need to make sure no dead
113 * pointers are left behind. */
114 if (object->type == OB_MESH) {
115 Mesh *mesh_eval = (Mesh *)data_eval;
116 Mesh *mesh_orig = (Mesh *)data_orig;
117 mesh_eval->runtime->edit_mesh = mesh_orig->runtime->edit_mesh;
118 }
119 }
120 }
122 if (object->id.recalc & ID_RECALC_GEOMETRY) {
123 /* Free evaluated caches. */
124 object->data = data_orig;
126 }
127 else {
128 object->data = object->runtime->data_eval;
129 }
130 }
131
133 /* Lazily allocate light linking on the evaluated object for the cases when the object is only
134 * a receiver or a blocker and does not need its own LightLinking on the original object. */
136 object->light_linking->runtime = *light_linking_runtime;
137 }
138
139 object->base_flag = base_flag;
140 object->base_local_view_bits = base_local_view_bits;
141
142 /* Restore modifier's runtime data.
143 * NOTE: Data of unused modifiers will be freed there. */
146}
147
149{
150 LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) {
151 std::optional<ModifierDataBackup> backup = modifier_runtime_data.pop_try(
152 modifier_data->persistent_uid);
153 if (backup.has_value()) {
154 modifier_data->runtime = backup->runtime;
155 }
156 }
157
158 for (ModifierDataBackup &backup : modifier_runtime_data.values()) {
159 const ModifierTypeInfo *modifier_type_info = BKE_modifier_get_info(backup.type);
160 BLI_assert(modifier_type_info != nullptr);
161 modifier_type_info->free_runtime_data(backup.runtime);
162
163 if (backup.type == eModifierType_Subsurf) {
164 if (object->type == OB_MESH) {
165 Mesh *mesh = (Mesh *)object->data;
166 if (mesh->runtime->subsurf_runtime_data == backup.runtime) {
167 mesh->runtime->subsurf_runtime_data = nullptr;
168 }
169 }
170 }
171 }
172}
173
175{
176 if (object->pose != nullptr) {
177 LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
178 const SessionUID &session_uid = pchan->runtime.session_uid;
179 std::optional<bPoseChannel_Runtime> runtime = pose_channel_runtime_data.pop_try(session_uid);
180 if (runtime.has_value()) {
181 pchan->runtime = *runtime;
182 }
183 }
184 }
187 }
188}
189
190} // 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)
void BKE_light_linking_ensure(struct Object *object)
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:1074
@ 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(x)
Definition DNA_ID.h:414
unsigned int recalc
Definition DNA_ID.h:445
ID_RuntimeHandle * runtime
Definition DNA_ID.h:538
char name[258]
Definition DNA_ID.h:432
MeshRuntimeHandle * runtime
void(* free_runtime_data)(void *runtime_data)
struct bPose * pose
ListBase modifiers
LightLinking * light_linking
ListBase chanbase