14#define NESTED_ID_NASTY_WORKAROUND
17#define DNA_DEPRECATED_ALLOW
59#ifdef NESTED_ID_NASTY_WORKAROUND
95 if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) \
100#ifdef NESTED_ID_NASTY_WORKAROUND
101union NestedIDHackTempStorage {
114void nested_id_hack_discard_pointers(
ID *id_cow)
116 switch (
GS(id_cow->
name)) {
117# define SPECIAL_CASE(id_type, dna_type, field) \
119 ((dna_type *)id_cow)->field = nullptr; \
147 psys->part =
nullptr;
161const ID *nested_id_hack_get_discarded_pointers(NestedIDHackTempStorage *storage,
const ID *
id)
163 switch (
GS(id->name)) {
164# define SPECIAL_CASE(id_type, dna_type, field, variable) \
166 storage->variable = dna::shallow_copy(*(dna_type *)id); \
167 storage->variable.field = nullptr; \
168 return &storage->variable.id; \
182 storage->scene = *(
Scene *)
id;
183 storage->scene.toolsettings =
nullptr;
184 storage->scene.nodetree =
nullptr;
185 return &storage->scene.id;
197void nested_id_hack_restore_pointers(
const ID *old_id,
ID *new_id)
199 if (new_id ==
nullptr) {
202 switch (
GS(old_id->
name)) {
203# define SPECIAL_CASE(id_type, dna_type, field) \
205 ((dna_type *)(new_id))->field = ((dna_type *)(old_id))->field; \
227void ntree_hack_remap_pointers(
const Depsgraph *
depsgraph,
ID *id_cow)
229 switch (
GS(id_cow->
name)) {
230# define SPECIAL_CASE(id_type, dna_type, field, field_type) \
232 dna_type *data = (dna_type *)id_cow; \
233 if (data->field != nullptr) { \
234 ID *ntree_id_cow = depsgraph->get_cow_id(&data->field->id); \
235 if (ntree_id_cow != nullptr) { \
236 DEG_COW_PRINT(" Remapping datablock for %s: id_orig=%p id_cow=%p\n", \
237 data->field->id.name, \
240 data->field = (field_type *)ntree_id_cow; \
270bool id_copy_inplace_no_main(
const ID *
id,
ID *newid)
272 const ID *id_for_copy = id;
276 if (id_type ==
ID_OB) {
277 const Object *
object =
reinterpret_cast<const Object *
>(id_for_copy);
282#ifdef NESTED_ID_NASTY_WORKAROUND
283 NestedIDHackTempStorage id_hack_storage;
284 id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage,
id);
293#ifdef NESTED_ID_NASTY_WORKAROUND
295 nested_id_hack_restore_pointers(
id, newid);
304bool scene_copy_inplace_no_main(
const Scene *scene,
Scene *new_scene)
311#ifdef NESTED_ID_NASTY_WORKAROUND
312 NestedIDHackTempStorage id_hack_storage;
313 const ID *id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, &scene->id);
315 const ID *id_for_copy = &scene->id;
323#ifdef NESTED_ID_NASTY_WORKAROUND
325 nested_id_hack_restore_pointers(&scene->id, &new_scene->id);
354void scene_minimize_unused_view_layers(
const Depsgraph *
depsgraph,
380 view_layer_cow !=
nullptr;
381 view_layer_cow = view_layer_next)
383 view_layer_next = view_layer_cow->
next;
384 if (view_layer_input !=
nullptr &&
STREQ(view_layer_input->
name, view_layer_cow->name)) {
385 view_layer_eval = view_layer_cow;
395 if (view_layer_eval !=
nullptr) {
400void scene_remove_all_bases(
Scene *scene_cow)
409void view_layer_remove_disabled_bases(
const Depsgraph *
depsgraph,
413 if (view_layer ==
nullptr) {
416 ListBase enabled_bases = {
nullptr,
nullptr};
431 if (is_object_enabled) {
435 if (base == view_layer->
basact) {
436 view_layer->
basact =
nullptr;
444void view_layer_update_orig_base_pointers(
const ViewLayer *view_layer_orig,
447 if (view_layer_orig ==
nullptr || view_layer_eval ==
nullptr) {
454 base_orig = base_orig->
next;
458void scene_setup_view_layers_before_remap(
const Depsgraph *
depsgraph,
466 scene_remove_all_bases(scene_cow);
470void scene_setup_view_layers_after_remap(
const Depsgraph *
depsgraph,
476 view_layer_update_orig_base_pointers(view_layer_orig, view_layer_eval);
477 view_layer_remove_disabled_bases(
depsgraph, scene_cow, view_layer_eval);
484inline bool check_datablock_expanded(
const ID *id_cow)
486 return (id_cow->
name[0] !=
'\0');
492struct RemapCallbackUserData {
500 if (*id_p ==
nullptr) {
504 RemapCallbackUserData *user_data = (RemapCallbackUserData *)cb_data->
user_data;
505 const Depsgraph *
depsgraph = user_data->depsgraph;
511 " Remapping datablock for %s: id_orig=%p id_cow=%p\n", id_orig->
name, id_orig, id_cow);
517void update_armature_edit_mode_pointers(
const Depsgraph * ,
523 armature_cow->
edbo = armature_orig->
edbo;
527void update_curve_edit_mode_pointers(
const Depsgraph * ,
531 const Curve *curve_orig = (
const Curve *)id_orig;
537void update_mball_edit_mode_pointers(
const Depsgraph * ,
546void update_lattice_edit_mode_pointers(
const Depsgraph * ,
555void update_mesh_edit_mode_pointers(
const ID *id_orig,
ID *id_cow)
557 const Mesh *mesh_orig = (
const Mesh *)id_orig;
559 if (mesh_orig->
runtime->edit_mesh ==
nullptr) {
567void update_edit_mode_pointers(
const Depsgraph *
depsgraph,
const ID *id_orig,
ID *id_cow)
572 update_armature_edit_mode_pointers(
depsgraph, id_orig, id_cow);
575 update_mesh_edit_mode_pointers(id_orig, id_cow);
578 update_curve_edit_mode_pointers(
depsgraph, id_orig, id_cow);
581 update_mball_edit_mode_pointers(
depsgraph, id_orig, id_cow);
584 update_lattice_edit_mode_pointers(
depsgraph, id_orig, id_cow);
592void update_list_orig_pointers(
const ListBase *listbase_orig,
596 T *element_orig =
reinterpret_cast<T *
>(listbase_orig->
first);
597 T *element_cow =
reinterpret_cast<T *
>(listbase->
first);
601 while (element_orig !=
nullptr && element_cow !=
nullptr) {
602 element_cow->*orig_field = element_orig;
603 element_cow = element_cow->next;
604 element_orig = element_orig->next;
608 "list of pointers of different sizes, unable to reliably set orig pointer");
611void update_particle_system_orig_pointers(
const Object *object_orig,
Object *object_cow)
613 update_list_orig_pointers(
617void set_particle_system_modifiers_loaded(
Object *object_cow)
628void reset_particle_system_edit_eval(
const Depsgraph *
depsgraph,
Object *object_cow)
637 if (orig_psys->
edit !=
nullptr) {
644void update_particles_after_copy(
const Depsgraph *
depsgraph,
645 const Object *object_orig,
648 update_particle_system_orig_pointers(object_orig, object_cow);
649 set_particle_system_modifiers_loaded(object_cow);
650 reset_particle_system_edit_eval(
depsgraph, object_cow);
653void update_pose_orig_pointers(
const bPose *pose_orig,
bPose *pose_cow)
658void update_nla_strips_orig_pointers(
const ListBase *strips_orig,
ListBase *strips_cow)
662 while (strip_orig !=
nullptr) {
664 update_nla_strips_orig_pointers(&strip_orig->
strips, &strip_cow->
strips);
665 strip_cow = strip_cow->
next;
666 strip_orig = strip_orig->
next;
670void update_nla_tracks_orig_pointers(
const ListBase *tracks_orig,
ListBase *tracks_cow)
674 while (track_orig !=
nullptr) {
675 update_nla_strips_orig_pointers(&track_orig->
strips, &track_cow->
strips);
676 track_cow = track_cow->
next;
677 track_orig = track_orig->
next;
681void update_animation_data_after_copy(
const ID *id_orig,
ID *id_cow)
684 if (anim_data_orig ==
nullptr) {
696void update_id_after_copy(
const Depsgraph *
depsgraph,
702 update_animation_data_after_copy(id_orig, id_cow);
709 object_cow->
mode = object_orig->
mode;
716 if (armature_orig->edbo ==
nullptr) {
717 update_pose_orig_pointers(object_orig->pose, object_cow->
pose);
721 update_particles_after_copy(
depsgraph, object_orig, object_cow);
726 const Scene *scene_orig = (
const Scene *)id_orig;
744 update_edit_mode_pointers(
depsgraph, id_orig, id_cow);
752 ValidateData *data = (ValidateData *)cb_data->
user_data;
753 ID **id_p = cb_data->id_pointer;
755 if (*id_p !=
nullptr) {
756 if (!check_datablock_expanded(*id_p)) {
757 data->is_valid =
false;
772 const int id_cow_recalc = id_cow->
recalc;
781 "Expanding datablock for %s: id_orig=%p id_cow=%p\n", id_orig->
name, id_orig, id_cow);
784 BLI_assert(check_datablock_expanded(id_cow) ==
false);
804 done = scene_copy_inplace_no_main((
Scene *)id_orig, (
Scene *)id_cow);
821 done = id_copy_inplace_no_main(id_orig, id_cow);
824 BLI_assert_msg(0,
"No idea how to perform evaluated copy on datablock");
828 " Remapping ID links for %s: id_orig=%p id_cow=%p\n", id_orig->
name, id_orig, id_cow);
830#ifdef NESTED_ID_NASTY_WORKAROUND
831 ntree_hack_remap_pointers(
depsgraph, id_cow);
837 RemapCallbackUserData user_data = {
nullptr};
854 id_cow->
recalc = id_cow_recalc;
888 update_edit_mode_pointers(
depsgraph, id_orig, id_cow);
912void discard_armature_edit_mode_pointers(
ID *id_cow)
915 armature_cow->
edbo =
nullptr;
918void discard_curve_edit_mode_pointers(
ID *id_cow)
925void discard_mball_edit_mode_pointers(
ID *id_cow)
931void discard_lattice_edit_mode_pointers(
ID *id_cow)
937void discard_mesh_edit_mode_pointers(
ID *id_cow)
940 mesh_cow->
runtime->edit_mesh =
nullptr;
943void discard_scene_pointers(
ID *id_cow)
951void discard_edit_mode_pointers(
ID *id_cow)
956 discard_armature_edit_mode_pointers(id_cow);
959 discard_mesh_edit_mode_pointers(id_cow);
962 discard_curve_edit_mode_pointers(id_cow);
965 discard_mball_edit_mode_pointers(id_cow);
968 discard_lattice_edit_mode_pointers(id_cow);
973 discard_scene_pointers(id_cow);
990 if (!check_datablock_expanded(id_cow)) {
996#ifdef NESTED_ID_NASTY_WORKAROUND
997 nested_id_hack_discard_pointers(id_cow);
1005 ob_cow->
data =
nullptr;
1006 ob_cow->
sculpt =
nullptr;
1012 discard_edit_mode_pointers(id_cow);
1017 id_cow->
name[0] =
'\0';
1034 if (id_cow ==
nullptr) {
1038 data.is_valid =
true;
1040 nullptr, id_cow, foreach_libblock_validate_callback, &data,
IDWALK_NOP);
1041 return data.is_valid;
1050 id_cow->
tag &= ~ID_TAG_LOCALIZED;
1057 return check_datablock_expanded(id_cow);
Blender kernel action and pose functionality.
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_gpencil_data_update_orig_pointers(const struct bGPdata *gpd_orig, const struct bGPdata *gpd_eval)
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, int 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(struct ListBase *listbase) ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_listbase_swaplinks(struct 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)
Types and defines for representing Rigid Body entities.
Read Guarded memory(de)allocation.
void init_from_id(ID *id)
void restore_to_id(ID *id)
FreestyleLineStyle linestyle
#define SPECIAL_CASE(id_type, dna_type, field)
const Depsgraph * depsgraph
#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 SEQ_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 bGPDlayer * gpl_orig
bGPDlayer_Runtime runtime
struct bPoseChannel * orig_pchan
ID * get_cow_id(const ID *id_orig) const
IDNode * find_id_node(const ID *id) const
bool is_render_pipeline_depsgraph
bool is_cow_explicitly_tagged
eDepsNode_LinkedState_Type linked_state