Blender V4.3
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
10
11#include <cstring>
12
13#include "DNA_mesh_types.h"
14
15#include "BLI_listbase.h"
16
17#include "BKE_action.hh"
18#include "BKE_mesh_types.hh"
19#include "BKE_object.hh"
20#include "BKE_object_types.hh"
21
22namespace blender::deg {
23
25 : base_flag(0), base_local_view_bits(0)
26{
27 /* TODO(sergey): Use something like BKE_object_runtime_reset(). */
28 runtime = {};
29}
30
32{
33 /* Store evaluated mesh and curve_cache, and make sure we don't free it. */
34 runtime = *object->runtime;
35 if (object->light_linking) {
36 light_linking_runtime = object->light_linking->runtime;
37 }
39 /* Keep bounding-box (for now at least). */
40 object->runtime->bounds_eval = runtime.bounds_eval;
41 /* Object update will override actual object->data to an evaluated version.
42 * Need to make sure we don't have data set to evaluated one before free
43 * anything. */
44 object->data = runtime.data_orig;
45 /* Make a backup of base flags. */
46 base_flag = object->base_flag;
47 base_local_view_bits = object->base_local_view_bits;
48 /* Backup runtime data of all modifiers. */
50 /* Backup runtime data of all pose channels. */
52}
53
55{
56 LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) {
57 if (modifier_data->runtime == nullptr) {
58 continue;
59 }
60
61 modifier_runtime_data.add(modifier_data->persistent_uid, ModifierDataBackup(modifier_data));
62 modifier_data->runtime = nullptr;
63 }
64}
65
67{
68 if (object->pose != nullptr) {
69 LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
70 const SessionUID &session_uid = pchan->runtime.session_uid;
72
73 pose_channel_runtime_data.add(session_uid, pchan->runtime);
74 BKE_pose_channel_runtime_reset(&pchan->runtime);
75 }
76 }
77}
78
80{
81 ID *data_orig = object->runtime->data_orig;
82 ID *data_eval = runtime.data_eval;
83 std::optional<Bounds<float3>> bounds = object->runtime->bounds_eval;
84 *object->runtime = runtime;
85 object->runtime->data_orig = data_orig;
86 object->runtime->bounds_eval = bounds;
87 if (ELEM(object->type, OB_MESH, OB_LATTICE, OB_CURVES_LEGACY, OB_FONT) && data_eval != nullptr) {
88 if (object->id.recalc & ID_RECALC_GEOMETRY) {
89 /* If geometry is tagged for update it means, that part of
90 * evaluated mesh are not valid anymore. In this case we can not
91 * have any "persistent" pointers to point to an invalid data.
92 *
93 * We restore object's data datablock to an original copy of
94 * that datablock. */
95 object->data = data_orig;
96
97 /* After that, immediately free the invalidated caches. */
99 }
100 else {
101 /* Do same thing as object update: override actual object data pointer with evaluated
102 * datablock, but only if the evaluated data has the same type as the original data. */
103 if (GS(((ID *)object->data)->name) == GS(data_eval->name)) {
104 object->data = data_eval;
105 }
106
107 /* Evaluated mesh simply copied edit_mesh pointer from
108 * original mesh during update, need to make sure no dead
109 * pointers are left behind. */
110 if (object->type == OB_MESH) {
111 Mesh *mesh_eval = (Mesh *)data_eval;
112 Mesh *mesh_orig = (Mesh *)data_orig;
113 mesh_eval->runtime->edit_mesh = mesh_orig->runtime->edit_mesh;
114 }
115 }
116 }
117 else if (ELEM(object->type, OB_CURVES, OB_POINTCLOUD, OB_VOLUME, OB_GREASE_PENCIL)) {
118 if (object->id.recalc & ID_RECALC_GEOMETRY) {
119 /* Free evaluated caches. */
120 object->data = data_orig;
122 }
123 else {
124 object->data = object->runtime->data_eval;
125 }
126 }
127
129 /* Lazily allocate light linking on the evaluated object for the cases when the object is only
130 * a receiver or a blocker and does not need its own LightLinking on the original object. */
131 if (!object->light_linking) {
132 object->light_linking = MEM_cnew<LightLinking>(__func__);
133 }
134 object->light_linking->runtime = *light_linking_runtime;
135 }
136
137 object->base_flag = base_flag;
138 object->base_local_view_bits = base_local_view_bits;
139
140 /* Restore modifier's runtime data.
141 * NOTE: Data of unused modifiers will be freed there. */
144}
145
147{
148 LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) {
149 optional<ModifierDataBackup> backup = modifier_runtime_data.pop_try(
150 modifier_data->persistent_uid);
151 if (backup.has_value()) {
152 modifier_data->runtime = backup->runtime;
153 }
154 }
155
156 for (ModifierDataBackup &backup : modifier_runtime_data.values()) {
157 const ModifierTypeInfo *modifier_type_info = BKE_modifier_get_info(backup.type);
158 BLI_assert(modifier_type_info != nullptr);
159 modifier_type_info->free_runtime_data(backup.runtime);
160
161 if (backup.type == eModifierType_Subsurf) {
162 if (object->type == OB_MESH) {
163 Mesh *mesh = (Mesh *)object->data;
164 if (mesh->runtime->subsurf_runtime_data == backup.runtime) {
165 mesh->runtime->subsurf_runtime_data = nullptr;
166 }
167 }
168 }
169 }
170}
171
173{
174 if (object->pose != nullptr) {
175 LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
176 const SessionUID &session_uid = pchan->runtime.session_uid;
177 optional<bPoseChannel_Runtime> runtime = pose_channel_runtime_data.pop_try(session_uid);
178 if (runtime.has_value()) {
179 pchan->runtime = *runtime;
180 }
181 }
182 }
185 }
186}
187
188} // 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:50
#define LISTBASE_FOREACH(type, var, list)
bool BLI_session_uid_is_generated(const SessionUID *uid)
Definition session_uid.c:38
#define ELEM(...)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
@ eModifierType_Subsurf
@ OB_LATTICE
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
@ OB_CURVES
std::optional< Value > pop_try(const Key &key)
Definition BLI_map.hh:395
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:271
ValueIterator values() const
Definition BLI_map.hh:846
Map< SessionUID, bPoseChannel_Runtime > pose_channel_runtime_data
optional< LightLinkingRuntime > light_linking_runtime
Map< int, ModifierDataBackup > modifier_runtime_data
#define GS(x)
Definition iris.cc:202
Definition DNA_ID.h:413
char name[66]
Definition DNA_ID.h:425
struct ID_Runtime runtime
Definition DNA_ID.h:492
MeshRuntimeHandle * runtime
void(* free_runtime_data)(void *runtime_data)
std::optional< Bounds< float3 > > bounds_eval