14#define NESTED_ID_NASTY_WORKAROUND
17#define DNA_DEPRECATED_ALLOW
48#ifdef NESTED_ID_NASTY_WORKAROUND
84 if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) \
89#ifdef NESTED_ID_NASTY_WORKAROUND
90union NestedIDHackTempStorage {
103void nested_id_hack_discard_pointers(
ID *id_cow)
105 switch (
GS(id_cow->
name)) {
106# define SPECIAL_CASE(id_type, dna_type, field) \
108 ((dna_type *)id_cow)->field = nullptr; \
133 psys->part =
nullptr;
147const ID *nested_id_hack_get_discarded_pointers(NestedIDHackTempStorage *storage,
const ID *
id)
150# define SPECIAL_CASE(id_type, dna_type, field, variable) \
152 storage->variable = dna::shallow_copy(*(dna_type *)id); \
153 storage->variable.field = nullptr; \
154 return &storage->variable.id; \
168 storage->scene = *(
Scene *)
id;
169 storage->scene.toolsettings =
nullptr;
170 return &storage->scene.id;
182void nested_id_hack_restore_pointers(
const ID *old_id,
ID *new_id)
184 if (new_id ==
nullptr) {
187 switch (
GS(old_id->
name)) {
188# define SPECIAL_CASE(id_type, dna_type, field) \
190 ((dna_type *)(new_id))->field = ((dna_type *)(old_id))->field; \
211void ntree_hack_remap_pointers(
const Depsgraph *
depsgraph,
ID *id_cow)
213 switch (
GS(id_cow->
name)) {
214# define SPECIAL_CASE(id_type, dna_type, field, field_type) \
216 dna_type *data = (dna_type *)id_cow; \
217 if (data->field != nullptr) { \
218 ID *ntree_id_cow = depsgraph->get_cow_id(&data->field->id); \
219 if (ntree_id_cow != nullptr) { \
220 DEG_COW_PRINT(" Remapping datablock for %s: id_orig=%p id_cow=%p\n", \
221 data->field->id.name, \
224 data->field = (field_type *)ntree_id_cow; \
253bool id_copy_inplace_no_main(
const ID *
id,
ID *newid)
255 const ID *id_for_copy = id;
259 if (id_type ==
ID_OB) {
260 const Object *
object =
reinterpret_cast<const Object *
>(id_for_copy);
265#ifdef NESTED_ID_NASTY_WORKAROUND
266 NestedIDHackTempStorage id_hack_storage;
267 id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage,
id);
276#ifdef NESTED_ID_NASTY_WORKAROUND
278 nested_id_hack_restore_pointers(
id, newid);
287bool scene_copy_inplace_no_main(
const Scene *scene,
Scene *new_scene)
294#ifdef NESTED_ID_NASTY_WORKAROUND
295 NestedIDHackTempStorage id_hack_storage;
296 const ID *id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, &scene->
id);
298 const ID *id_for_copy = &scene->
id;
306#ifdef NESTED_ID_NASTY_WORKAROUND
308 nested_id_hack_restore_pointers(&scene->
id, &new_scene->
id);
324 Scene *scene_orig =
reinterpret_cast<Scene *
>(id_node->id_orig);
337void scene_minimize_unused_view_layers(
const Depsgraph *
depsgraph,
338 const IDNode *id_node,
341 if (
depsgraph->is_render_pipeline_depsgraph) {
363 view_layer_cow !=
nullptr;
364 view_layer_cow = view_layer_next)
366 view_layer_next = view_layer_cow->next;
367 if (view_layer_input !=
nullptr &&
STREQ(view_layer_input->
name, view_layer_cow->name)) {
368 view_layer_eval = view_layer_cow;
378 if (view_layer_eval !=
nullptr) {
383void scene_remove_all_bases(
Scene *scene_cow)
392void view_layer_remove_disabled_bases(
const Depsgraph *
depsgraph,
396 if (view_layer ==
nullptr) {
399 ListBase enabled_bases = {
nullptr,
nullptr};
414 if (is_object_enabled) {
418 if (base == view_layer->
basact) {
419 view_layer->
basact =
nullptr;
427void view_layer_update_orig_base_pointers(
const ViewLayer *view_layer_orig,
430 if (view_layer_orig ==
nullptr || view_layer_eval ==
nullptr) {
437 base_orig = base_orig->
next;
441void scene_setup_view_layers_before_remap(
const Depsgraph *
depsgraph,
442 const IDNode *id_node,
445 scene_minimize_unused_view_layers(
depsgraph, id_node, scene_cow);
448 if (
depsgraph->is_render_pipeline_depsgraph) {
449 scene_remove_all_bases(scene_cow);
453void scene_setup_view_layers_after_remap(
const Depsgraph *
depsgraph,
454 const IDNode *id_node,
459 view_layer_update_orig_base_pointers(view_layer_orig, view_layer_eval);
460 view_layer_remove_disabled_bases(
depsgraph, scene_cow, view_layer_eval);
467inline bool check_datablock_expanded(
const ID *id_cow)
469 return (id_cow->
name[0] !=
'\0');
475struct RemapCallbackUserData {
483 if (*id_p ==
nullptr) {
487 RemapCallbackUserData *user_data = (RemapCallbackUserData *)cb_data->
user_data;
488 const Depsgraph *
depsgraph = user_data->depsgraph;
494 " Remapping data-block for %s: id_orig=%p id_cow=%p\n", id_orig->
name, id_orig, id_cow);
500void update_armature_edit_mode_pointers(
const Depsgraph * ,
506 armature_cow->
edbo = armature_orig->
edbo;
510void update_curve_edit_mode_pointers(
const Depsgraph * ,
514 const Curve *curve_orig = (
const Curve *)id_orig;
520void update_mball_edit_mode_pointers(
const Depsgraph * ,
529void update_lattice_edit_mode_pointers(
const Depsgraph * ,
538void update_mesh_edit_mode_pointers(
const ID *id_orig,
ID *id_cow)
540 const Mesh *mesh_orig = (
const Mesh *)id_orig;
542 if (mesh_orig->
runtime->edit_mesh ==
nullptr) {
550void update_edit_mode_pointers(
const Depsgraph *
depsgraph,
const ID *id_orig,
ID *id_cow)
555 update_armature_edit_mode_pointers(
depsgraph, id_orig, id_cow);
558 update_mesh_edit_mode_pointers(id_orig, id_cow);
561 update_curve_edit_mode_pointers(
depsgraph, id_orig, id_cow);
564 update_mball_edit_mode_pointers(
depsgraph, id_orig, id_cow);
567 update_lattice_edit_mode_pointers(
depsgraph, id_orig, id_cow);
575void update_list_orig_pointers(
const ListBase *listbase_orig,
579 T *element_orig =
reinterpret_cast<T *
>(listbase_orig->
first);
580 T *element_cow =
reinterpret_cast<T *
>(listbase->
first);
584 while (element_orig !=
nullptr && element_cow !=
nullptr) {
585 element_cow->*orig_field = element_orig;
586 element_cow = element_cow->next;
587 element_orig = element_orig->next;
591 "list of pointers of different sizes, unable to reliably set orig pointer");
594void update_particle_system_orig_pointers(
const Object *object_orig,
Object *object_cow)
596 update_list_orig_pointers(
600void set_particle_system_modifiers_loaded(
Object *object_cow)
611void reset_particle_system_edit_eval(
const Depsgraph *
depsgraph,
Object *object_cow)
620 if (orig_psys->
edit !=
nullptr) {
627void update_particles_after_copy(
const Depsgraph *
depsgraph,
628 const Object *object_orig,
631 update_particle_system_orig_pointers(object_orig, object_cow);
632 set_particle_system_modifiers_loaded(object_cow);
633 reset_particle_system_edit_eval(
depsgraph, object_cow);
636void update_pose_orig_pointers(
const bPose *pose_orig,
bPose *pose_cow)
641void update_nla_strips_orig_pointers(
const ListBase *strips_orig,
ListBase *strips_cow)
645 while (strip_orig !=
nullptr) {
647 update_nla_strips_orig_pointers(&strip_orig->
strips, &strip_cow->
strips);
648 strip_cow = strip_cow->
next;
649 strip_orig = strip_orig->
next;
653void update_nla_tracks_orig_pointers(
const ListBase *tracks_orig,
ListBase *tracks_cow)
657 while (track_orig !=
nullptr) {
658 update_nla_strips_orig_pointers(&track_orig->
strips, &track_cow->
strips);
659 track_cow = track_cow->
next;
660 track_orig = track_orig->
next;
664void update_animation_data_after_copy(
const ID *id_orig,
ID *id_cow)
667 if (anim_data_orig ==
nullptr) {
679void update_id_after_copy(
const Depsgraph *
depsgraph,
680 const IDNode *id_node,
685 update_animation_data_after_copy(id_orig, id_cow);
692 object_cow->
mode = object_orig->
mode;
699 if (armature_orig->
edbo ==
nullptr) {
700 update_pose_orig_pointers(object_orig->
pose, object_cow->
pose);
704 update_particles_after_copy(
depsgraph, object_orig, object_cow);
709 const Scene *scene_orig = (
const Scene *)id_orig;
711 scene_setup_view_layers_after_remap(
depsgraph, id_node,
reinterpret_cast<Scene *
>(id_cow));
717 update_edit_mode_pointers(
depsgraph, id_orig, id_cow);
728 if (*id_p !=
nullptr) {
729 if (!check_datablock_expanded(*id_p)) {
730 data->is_valid =
false;
741ID *deg_expand_eval_copy_datablock(
const Depsgraph *
depsgraph,
const IDNode *id_node)
743 const ID *id_orig = id_node->id_orig;
744 ID *id_cow = id_node->id_cow;
745 const int id_cow_recalc = id_cow->
recalc;
754 "Expanding datablock for %s: id_orig=%p id_cow=%p\n", id_orig->
name, id_orig, id_cow);
762 BLI_assert(check_datablock_expanded(id_cow) ==
false);
783 done = scene_copy_inplace_no_main((
Scene *)id_orig, (
Scene *)id_cow);
787 scene_setup_view_layers_before_remap(
depsgraph, id_node, (
Scene *)id_cow);
800 done = id_copy_inplace_no_main(id_orig, id_cow);
803 BLI_assert_msg(0,
"No idea how to perform evaluated copy on datablock");
807 " Remapping ID links for %s: id_orig=%p id_cow=%p\n", id_orig->
name, id_orig, id_cow);
809#ifdef NESTED_ID_NASTY_WORKAROUND
810 ntree_hack_remap_pointers(
depsgraph, id_cow);
816 RemapCallbackUserData user_data = {
nullptr};
832 update_id_after_copy(
depsgraph, id_node, id_orig, id_cow);
833 id_cow->
recalc = id_cow_recalc;
867 update_edit_mode_pointers(
depsgraph, id_orig, id_cow);
875 deg_expand_eval_copy_datablock(
depsgraph, id_node);
891void discard_armature_edit_mode_pointers(
ID *id_cow)
894 armature_cow->
edbo =
nullptr;
897void discard_curve_edit_mode_pointers(
ID *id_cow)
904void discard_mball_edit_mode_pointers(
ID *id_cow)
910void discard_lattice_edit_mode_pointers(
ID *id_cow)
916void discard_mesh_edit_mode_pointers(
ID *id_cow)
919 mesh_cow->
runtime->edit_mesh =
nullptr;
922void discard_scene_pointers(
ID *id_cow)
930void discard_edit_mode_pointers(
ID *id_cow)
935 discard_armature_edit_mode_pointers(id_cow);
938 discard_mesh_edit_mode_pointers(id_cow);
941 discard_curve_edit_mode_pointers(id_cow);
944 discard_mball_edit_mode_pointers(id_cow);
947 discard_lattice_edit_mode_pointers(id_cow);
952 discard_scene_pointers(id_cow);
969 if (!check_datablock_expanded(id_cow)) {
975#ifdef NESTED_ID_NASTY_WORKAROUND
976 nested_id_hack_discard_pointers(id_cow);
984 ob_cow->
data =
nullptr;
991 discard_edit_mode_pointers(id_cow);
996 id_cow->
name[0] =
'\0';
1013 if (id_cow ==
nullptr) {
1017 data.is_valid =
true;
1019 nullptr, id_cow, foreach_libblock_validate_callback, &
data,
IDWALK_NOP);
1020 return data.is_valid;
1036 return check_datablock_expanded(id_cow);
AnimData * BKE_animdata_from_id(const ID *id)
void BKE_animsys_update_driver_array(struct ID *id)
void BKE_pose_pchan_index_rebuild(bPose *pose)
void BKE_pose_remap_bone_pointers(bArmature *armature, bPose *pose)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
void BKE_view_layer_free_object_content(ViewLayer *view_layer)
ViewLayer * BKE_view_layer_default_render(const Scene *scene)
ListBase * BKE_view_layer_object_bases_get(ViewLayer *view_layer)
void BKE_libblock_free_data_py(ID *id)
void BKE_libblock_free_datablock(ID *id, int flag) ATTR_NONNULL()
void BKE_libblock_free_data(ID *id, bool do_id_user) ATTR_NONNULL()
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
@ LIB_ID_CREATE_NO_ALLOCATE
@ LIB_ID_COPY_SET_COPIED_ON_WRITE
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, LibraryForeachIDFlag flag)
@ IDWALK_IGNORE_MISSING_OWNER_ID
@ IDWALK_IGNORE_EMBEDDED_ID
General operations, lookup, etc. for blender objects.
void BKE_object_check_uids_unique_and_report(const Object *object)
bool BKE_object_data_is_in_editmode(const Object *ob, const ID *id)
#define BLI_assert_msg(a, msg)
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_listbase_swaplinks(ListBase *listbase, void *vlinka, void *vlinkb) ATTR_NONNULL(1
bool DEG_is_active(const Depsgraph *depsgraph)
void DEG_debug_print_eval(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address)
ID and Library types, which are fundamental for SDNA.
#define ID_TYPE_USE_COPY_ON_EVAL(_id_type)
@ eParticleSystemFlag_file_loaded
@ eModifierType_ParticleSystem
Object is a sort of wrapper for general info.
#define OB_DATA_SUPPORT_EDITMODE(_type)
Read Guarded memory(de)allocation.
BMesh const char void * data
BPy_StructRNA * depsgraph
void init_from_id(ID *id)
void restore_to_id(ID *id)
#define SPECIAL_CASE(id_type, dna_type, field)
#define DEG_COW_PRINT(format,...)
static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
void MEM_freeN(void *vmemh)
void deg_tag_eval_copy_id(deg::Depsgraph &depsgraph, ID *id_cow, const ID *id_orig)
void deg_create_eval_copy(::Depsgraph *graph, const IDNode *id_node)
bool deg_check_base_in_depsgraph(const Depsgraph *graph, Base *base)
bool deg_eval_copy_is_expanded(const ID *id_cow)
void deg_free_eval_copy_datablock(ID *id_cow)
bool deg_eval_copy_is_needed(const ID *id_orig)
ID * deg_update_eval_copy_datablock(const Depsgraph *depsgraph, const IDNode *id_node)
bool deg_validate_eval_copy_datablock(ID *id_cow)
void relations_check_uids_unique_and_report(const Scene *scene)
struct EditFont * editfont
ID_RuntimeHandle * runtime
struct EditLatt * editlatt
MeshRuntimeHandle * runtime
struct NlaStrip * orig_strip
ObjectRuntimeHandle * runtime
struct SculptSession * sculpt
struct ParticleSystemModifierData * psmd_eval
struct ParticleSystem * psys_eval
struct PTCacheEdit * edit
struct ParticleSystem * orig_psys
struct ToolSettings * toolsettings
struct EditBone * act_edbone
struct bPoseChannel * orig_pchan
bool is_cow_explicitly_tagged