14#define NESTED_ID_NASTY_WORKAROUND
17#define DNA_DEPRECATED_ALLOW
49#ifdef NESTED_ID_NASTY_WORKAROUND
85 if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) \
90#ifdef NESTED_ID_NASTY_WORKAROUND
91union NestedIDHackTempStorage {
104void nested_id_hack_discard_pointers(
ID *id_cow)
106 switch (
GS(id_cow->
name)) {
107# define SPECIAL_CASE(id_type, dna_type, field) \
109 ((dna_type *)id_cow)->field = nullptr; \
137 psys->part =
nullptr;
151const ID *nested_id_hack_get_discarded_pointers(NestedIDHackTempStorage *storage,
const ID *
id)
154# define SPECIAL_CASE(id_type, dna_type, field, variable) \
156 storage->variable = dna::shallow_copy(*(dna_type *)id); \
157 storage->variable.field = nullptr; \
158 return &storage->variable.id; \
172 storage->scene = *(
Scene *)
id;
173 storage->scene.toolsettings =
nullptr;
174 storage->scene.nodetree =
nullptr;
175 return &storage->scene.id;
187void nested_id_hack_restore_pointers(
const ID *old_id,
ID *new_id)
189 if (new_id ==
nullptr) {
192 switch (
GS(old_id->
name)) {
193# define SPECIAL_CASE(id_type, dna_type, field) \
195 ((dna_type *)(new_id))->field = ((dna_type *)(old_id))->field; \
217void ntree_hack_remap_pointers(
const Depsgraph *
depsgraph,
ID *id_cow)
219 switch (
GS(id_cow->
name)) {
220# define SPECIAL_CASE(id_type, dna_type, field, field_type) \
222 dna_type *data = (dna_type *)id_cow; \
223 if (data->field != nullptr) { \
224 ID *ntree_id_cow = depsgraph->get_cow_id(&data->field->id); \
225 if (ntree_id_cow != nullptr) { \
226 DEG_COW_PRINT(" Remapping datablock for %s: id_orig=%p id_cow=%p\n", \
227 data->field->id.name, \
230 data->field = (field_type *)ntree_id_cow; \
260bool id_copy_inplace_no_main(
const ID *
id,
ID *newid)
262 const ID *id_for_copy = id;
266 if (id_type ==
ID_OB) {
267 const Object *
object =
reinterpret_cast<const Object *
>(id_for_copy);
272#ifdef NESTED_ID_NASTY_WORKAROUND
273 NestedIDHackTempStorage id_hack_storage;
274 id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage,
id);
283#ifdef NESTED_ID_NASTY_WORKAROUND
285 nested_id_hack_restore_pointers(
id, newid);
294bool scene_copy_inplace_no_main(
const Scene *scene,
Scene *new_scene)
301#ifdef NESTED_ID_NASTY_WORKAROUND
302 NestedIDHackTempStorage id_hack_storage;
303 const ID *id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, &scene->
id);
305 const ID *id_for_copy = &scene->
id;
313#ifdef NESTED_ID_NASTY_WORKAROUND
315 nested_id_hack_restore_pointers(&scene->
id, &new_scene->
id);
331 Scene *scene_orig =
reinterpret_cast<Scene *
>(id_node->id_orig);
344void scene_minimize_unused_view_layers(
const Depsgraph *
depsgraph,
345 const IDNode *id_node,
348 if (
depsgraph->is_render_pipeline_depsgraph) {
370 view_layer_cow !=
nullptr;
371 view_layer_cow = view_layer_next)
373 view_layer_next = view_layer_cow->next;
374 if (view_layer_input !=
nullptr &&
STREQ(view_layer_input->
name, view_layer_cow->name)) {
375 view_layer_eval = view_layer_cow;
385 if (view_layer_eval !=
nullptr) {
390void scene_remove_all_bases(
Scene *scene_cow)
399void view_layer_remove_disabled_bases(
const Depsgraph *
depsgraph,
403 if (view_layer ==
nullptr) {
406 ListBase enabled_bases = {
nullptr,
nullptr};
421 if (is_object_enabled) {
425 if (base == view_layer->
basact) {
426 view_layer->
basact =
nullptr;
434void view_layer_update_orig_base_pointers(
const ViewLayer *view_layer_orig,
437 if (view_layer_orig ==
nullptr || view_layer_eval ==
nullptr) {
444 base_orig = base_orig->
next;
448void scene_setup_view_layers_before_remap(
const Depsgraph *
depsgraph,
449 const IDNode *id_node,
452 scene_minimize_unused_view_layers(
depsgraph, id_node, scene_cow);
455 if (
depsgraph->is_render_pipeline_depsgraph) {
456 scene_remove_all_bases(scene_cow);
460void scene_setup_view_layers_after_remap(
const Depsgraph *
depsgraph,
461 const IDNode *id_node,
466 view_layer_update_orig_base_pointers(view_layer_orig, view_layer_eval);
467 view_layer_remove_disabled_bases(
depsgraph, scene_cow, view_layer_eval);
474inline bool check_datablock_expanded(
const ID *id_cow)
476 return (id_cow->
name[0] !=
'\0');
482struct RemapCallbackUserData {
490 if (*id_p ==
nullptr) {
494 RemapCallbackUserData *user_data = (RemapCallbackUserData *)cb_data->
user_data;
495 const Depsgraph *
depsgraph = user_data->depsgraph;
501 " Remapping datablock for %s: id_orig=%p id_cow=%p\n", id_orig->
name, id_orig, id_cow);
507void update_armature_edit_mode_pointers(
const Depsgraph * ,
513 armature_cow->
edbo = armature_orig->
edbo;
517void update_curve_edit_mode_pointers(
const Depsgraph * ,
521 const Curve *curve_orig = (
const Curve *)id_orig;
527void update_mball_edit_mode_pointers(
const Depsgraph * ,
536void update_lattice_edit_mode_pointers(
const Depsgraph * ,
545void update_mesh_edit_mode_pointers(
const ID *id_orig,
ID *id_cow)
547 const Mesh *mesh_orig = (
const Mesh *)id_orig;
549 if (mesh_orig->
runtime->edit_mesh ==
nullptr) {
557void update_edit_mode_pointers(
const Depsgraph *
depsgraph,
const ID *id_orig,
ID *id_cow)
562 update_armature_edit_mode_pointers(
depsgraph, id_orig, id_cow);
565 update_mesh_edit_mode_pointers(id_orig, id_cow);
568 update_curve_edit_mode_pointers(
depsgraph, id_orig, id_cow);
571 update_mball_edit_mode_pointers(
depsgraph, id_orig, id_cow);
574 update_lattice_edit_mode_pointers(
depsgraph, id_orig, id_cow);
582void update_list_orig_pointers(
const ListBase *listbase_orig,
586 T *element_orig =
reinterpret_cast<T *
>(listbase_orig->
first);
587 T *element_cow =
reinterpret_cast<T *
>(listbase->
first);
591 while (element_orig !=
nullptr && element_cow !=
nullptr) {
592 element_cow->*orig_field = element_orig;
593 element_cow = element_cow->next;
594 element_orig = element_orig->next;
598 "list of pointers of different sizes, unable to reliably set orig pointer");
601void update_particle_system_orig_pointers(
const Object *object_orig,
Object *object_cow)
603 update_list_orig_pointers(
607void set_particle_system_modifiers_loaded(
Object *object_cow)
618void reset_particle_system_edit_eval(
const Depsgraph *
depsgraph,
Object *object_cow)
627 if (orig_psys->
edit !=
nullptr) {
634void update_particles_after_copy(
const Depsgraph *
depsgraph,
635 const Object *object_orig,
638 update_particle_system_orig_pointers(object_orig, object_cow);
639 set_particle_system_modifiers_loaded(object_cow);
640 reset_particle_system_edit_eval(
depsgraph, object_cow);
643void update_pose_orig_pointers(
const bPose *pose_orig,
bPose *pose_cow)
648void update_nla_strips_orig_pointers(
const ListBase *strips_orig,
ListBase *strips_cow)
652 while (strip_orig !=
nullptr) {
654 update_nla_strips_orig_pointers(&strip_orig->
strips, &strip_cow->
strips);
655 strip_cow = strip_cow->
next;
656 strip_orig = strip_orig->
next;
660void update_nla_tracks_orig_pointers(
const ListBase *tracks_orig,
ListBase *tracks_cow)
664 while (track_orig !=
nullptr) {
665 update_nla_strips_orig_pointers(&track_orig->
strips, &track_cow->
strips);
666 track_cow = track_cow->
next;
667 track_orig = track_orig->
next;
671void update_animation_data_after_copy(
const ID *id_orig,
ID *id_cow)
674 if (anim_data_orig ==
nullptr) {
686void update_id_after_copy(
const Depsgraph *
depsgraph,
687 const IDNode *id_node,
692 update_animation_data_after_copy(id_orig, id_cow);
699 object_cow->
mode = object_orig->
mode;
706 if (armature_orig->
edbo ==
nullptr) {
707 update_pose_orig_pointers(object_orig->
pose, object_cow->
pose);
711 update_particles_after_copy(
depsgraph, object_orig, object_cow);
716 const Scene *scene_orig = (
const Scene *)id_orig;
718 scene_setup_view_layers_after_remap(
depsgraph, id_node,
reinterpret_cast<Scene *
>(id_cow));
724 update_edit_mode_pointers(
depsgraph, id_orig, id_cow);
735 if (*id_p !=
nullptr) {
736 if (!check_datablock_expanded(*id_p)) {
737 data->is_valid =
false;
748ID *deg_expand_eval_copy_datablock(
const Depsgraph *
depsgraph,
const IDNode *id_node)
750 const ID *id_orig = id_node->id_orig;
751 ID *id_cow = id_node->id_cow;
752 const int id_cow_recalc = id_cow->
recalc;
761 "Expanding datablock for %s: id_orig=%p id_cow=%p\n", id_orig->
name, id_orig, id_cow);
764 BLI_assert(check_datablock_expanded(id_cow) ==
false);
784 done = scene_copy_inplace_no_main((
Scene *)id_orig, (
Scene *)id_cow);
788 scene_setup_view_layers_before_remap(
depsgraph, id_node, (
Scene *)id_cow);
801 done = id_copy_inplace_no_main(id_orig, id_cow);
804 BLI_assert_msg(0,
"No idea how to perform evaluated copy on datablock");
808 " Remapping ID links for %s: id_orig=%p id_cow=%p\n", id_orig->
name, id_orig, id_cow);
810#ifdef NESTED_ID_NASTY_WORKAROUND
811 ntree_hack_remap_pointers(
depsgraph, id_cow);
817 RemapCallbackUserData user_data = {
nullptr};
833 update_id_after_copy(
depsgraph, id_node, id_orig, id_cow);
834 id_cow->
recalc = id_cow_recalc;
868 update_edit_mode_pointers(
depsgraph, id_orig, id_cow);
876 deg_expand_eval_copy_datablock(
depsgraph, id_node);
892void discard_armature_edit_mode_pointers(
ID *id_cow)
895 armature_cow->
edbo =
nullptr;
898void discard_curve_edit_mode_pointers(
ID *id_cow)
905void discard_mball_edit_mode_pointers(
ID *id_cow)
911void discard_lattice_edit_mode_pointers(
ID *id_cow)
917void discard_mesh_edit_mode_pointers(
ID *id_cow)
920 mesh_cow->
runtime->edit_mesh =
nullptr;
923void discard_scene_pointers(
ID *id_cow)
931void discard_edit_mode_pointers(
ID *id_cow)
936 discard_armature_edit_mode_pointers(id_cow);
939 discard_mesh_edit_mode_pointers(id_cow);
942 discard_curve_edit_mode_pointers(id_cow);
945 discard_mball_edit_mode_pointers(id_cow);
948 discard_lattice_edit_mode_pointers(id_cow);
953 discard_scene_pointers(id_cow);
970 if (!check_datablock_expanded(id_cow)) {
976#ifdef NESTED_ID_NASTY_WORKAROUND
977 nested_id_hack_discard_pointers(id_cow);
985 ob_cow->
data =
nullptr;
992 discard_edit_mode_pointers(id_cow);
997 id_cow->
name[0] =
'\0';
1014 if (id_cow ==
nullptr) {
1018 data.is_valid =
true;
1020 nullptr, id_cow, foreach_libblock_validate_callback, &
data,
IDWALK_NOP);
1021 return data.is_valid;
1037 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()
@ LIB_ID_CREATE_NO_ALLOCATE
@ LIB_ID_COPY_SET_COPIED_ON_WRITE
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)
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.
@ 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,...)
#define ID_TYPE_USE_COPY_ON_EVAL(_id_type)
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
struct Depsgraph * depsgraph
struct ID_Runtime 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 bNodeTree * nodetree
struct ToolSettings * toolsettings
struct EditBone * act_edbone
struct bPoseChannel * orig_pchan
bool is_cow_explicitly_tagged