13 #define NESTED_ID_NASTY_WORKAROUND
16 #define DNA_DEPRECATED_ALLOW
57 #ifdef NESTED_ID_NASTY_WORKAROUND
93 if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) \
98 #ifdef NESTED_ID_NASTY_WORKAROUND
99 union NestedIDHackTempStorage {
113 void nested_id_hack_discard_pointers(
ID *id_cow)
115 switch (
GS(id_cow->
name)) {
116 # define SPECIAL_CASE(id_type, dna_type, field) \
118 ((dna_type *)id_cow)->field = nullptr; \
147 psys->part =
nullptr;
161 const ID *nested_id_hack_get_discarded_pointers(NestedIDHackTempStorage *storage,
const ID *
id)
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; \
183 storage->scene = *(
Scene *)
id;
184 storage->scene.toolsettings =
nullptr;
185 storage->scene.nodetree =
nullptr;
186 return &storage->scene.id;
198 void nested_id_hack_restore_pointers(
const ID *old_id,
ID *new_id)
200 if (new_id ==
nullptr) {
203 switch (
GS(old_id->
name)) {
204 # define SPECIAL_CASE(id_type, dna_type, field) \
206 ((dna_type *)(new_id))->field = ((dna_type *)(old_id))->field; \
231 switch (
GS(id_cow->
name)) {
232 # define SPECIAL_CASE(id_type, dna_type, field, field_type) \
234 dna_type *data = (dna_type *)id_cow; \
235 if (data->field != nullptr) { \
236 ID *ntree_id_cow = depsgraph->get_cow_id(&data->field->id); \
237 if (ntree_id_cow != nullptr) { \
238 DEG_COW_PRINT(" Remapping datablock for %s: id_orig=%p id_cow=%p\n", \
239 data->field->id.name, \
242 data->field = (field_type *)ntree_id_cow; \
267 struct ValidateData {
273 bool id_copy_inplace_no_main(
const ID *
id,
ID *newid)
275 const ID *id_for_copy =
id;
279 if (id_type ==
ID_OB) {
280 const Object *
object =
reinterpret_cast<const Object *
>(id_for_copy);
285 #ifdef NESTED_ID_NASTY_WORKAROUND
286 NestedIDHackTempStorage id_hack_storage;
287 id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage,
id);
296 #ifdef NESTED_ID_NASTY_WORKAROUND
298 nested_id_hack_restore_pointers(
id, newid);
314 #ifdef NESTED_ID_NASTY_WORKAROUND
315 NestedIDHackTempStorage id_hack_storage;
316 const ID *id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, &
scene->
id);
326 #ifdef NESTED_ID_NASTY_WORKAROUND
328 nested_id_hack_restore_pointers(&
scene->
id, &new_scene->id);
373 view_layer->basact =
nullptr;
380 view_layer_input =
nullptr;
390 view_layer_cow !=
nullptr;
391 view_layer_cow = view_layer_next) {
392 view_layer_next = view_layer_cow->
next;
393 if (view_layer_input !=
nullptr &&
STREQ(view_layer_input->
name, view_layer_cow->name)) {
394 view_layer_eval = view_layer_cow;
401 if (view_layer_eval !=
nullptr) {
402 view_layer_eval->
prev = view_layer_eval->
next =
nullptr;
408 void scene_remove_all_bases(
Scene *scene_cow)
419 if (view_layer ==
nullptr) {
422 ListBase enabled_bases = {
nullptr,
nullptr};
436 if (is_object_enabled) {
440 if (base == view_layer->
basact) {
441 view_layer->
basact =
nullptr;
449 void view_layer_update_orig_base_pointers(
const ViewLayer *view_layer_orig,
452 if (view_layer_orig ==
nullptr || view_layer_eval ==
nullptr) {
458 base_eval->base_orig = base_orig;
459 base_orig = base_orig->
next;
471 scene_remove_all_bases(scene_cow);
481 view_layer_update_orig_base_pointers(view_layer_orig, view_layer_eval);
482 view_layer_remove_disabled_bases(
depsgraph, view_layer_eval);
489 inline bool check_datablock_expanded(
const ID *id_cow)
491 return (id_cow->
name[0] !=
'\0');
497 struct RemapCallbackUserData {
505 if (*id_p ==
nullptr) {
516 " Remapping datablock for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
522 void update_armature_edit_mode_pointers(
const Depsgraph * ,
528 armature_cow->
edbo = armature_orig->
edbo;
532 void update_curve_edit_mode_pointers(
const Depsgraph * ,
536 const Curve *curve_orig = (
const Curve *)id_orig;
542 void update_mball_edit_mode_pointers(
const Depsgraph * ,
551 void update_lattice_edit_mode_pointers(
const Depsgraph * ,
560 void update_mesh_edit_mode_pointers(
const ID *id_orig,
ID *id_cow)
562 const Mesh *mesh_orig = (
const Mesh *)id_orig;
577 update_armature_edit_mode_pointers(
depsgraph, id_orig, id_cow);
580 update_mesh_edit_mode_pointers(id_orig, id_cow);
583 update_curve_edit_mode_pointers(
depsgraph, id_orig, id_cow);
586 update_mball_edit_mode_pointers(
depsgraph, id_orig, id_cow);
589 update_lattice_edit_mode_pointers(
depsgraph, id_orig, id_cow);
597 void update_list_orig_pointers(
const ListBase *listbase_orig,
601 T *element_orig =
reinterpret_cast<T *
>(listbase_orig->
first);
602 T *element_cow =
reinterpret_cast<T *
>(listbase->
first);
606 while (element_orig !=
nullptr && element_cow !=
nullptr) {
607 element_cow->*orig_field = element_orig;
608 element_cow = element_cow->next;
609 element_orig = element_orig->next;
612 BLI_assert((element_orig ==
nullptr && element_cow ==
nullptr) ||
613 !
"list of pointers of different sizes, unable to reliably set orig pointer");
616 void update_particle_system_orig_pointers(
const Object *object_orig,
Object *object_cow)
618 update_list_orig_pointers(
622 void set_particle_system_modifiers_loaded(
Object *object_cow)
642 if (orig_psys->
edit !=
nullptr) {
650 const Object *object_orig,
653 update_particle_system_orig_pointers(object_orig, object_cow);
654 set_particle_system_modifiers_loaded(object_cow);
655 reset_particle_system_edit_eval(
depsgraph, object_cow);
658 void update_pose_orig_pointers(
const bPose *pose_orig,
bPose *pose_cow)
663 void update_nla_strips_orig_pointers(
const ListBase *strips_orig,
ListBase *strips_cow)
667 while (strip_orig !=
nullptr) {
669 update_nla_strips_orig_pointers(&strip_orig->
strips, &strip_cow->
strips);
670 strip_cow = strip_cow->
next;
671 strip_orig = strip_orig->
next;
675 void update_nla_tracks_orig_pointers(
const ListBase *tracks_orig,
ListBase *tracks_cow)
679 while (track_orig !=
nullptr) {
680 update_nla_strips_orig_pointers(&track_orig->
strips, &track_cow->
strips);
681 track_cow = track_cow->
next;
682 track_orig = track_orig->
next;
686 void update_animation_data_after_copy(
const ID *id_orig,
ID *id_cow)
689 if (anim_data_orig ==
nullptr) {
707 update_animation_data_after_copy(id_orig, id_cow);
714 object_cow->
mode = object_orig->
mode;
721 if (armature_orig->
edbo ==
nullptr) {
722 update_pose_orig_pointers(object_orig->
pose, object_cow->
pose);
726 update_particles_after_copy(
depsgraph, object_orig, object_cow);
731 const Scene *scene_orig = (
const Scene *)id_orig;
750 update_edit_mode_pointers(
depsgraph, id_orig, id_cow);
761 if (*id_p !=
nullptr) {
762 if (!check_datablock_expanded(*id_p)) {
763 data->is_valid =
false;
778 const int id_cow_recalc = id_cow->
recalc;
787 "Expanding datablock for %s: id_orig=%p id_cow=%p\n", id_orig->
name, id_orig, id_cow);
790 BLI_assert(check_datablock_expanded(id_cow) ==
false);
810 done = scene_copy_inplace_no_main((
Scene *)id_orig, (
Scene *)id_cow);
827 done = id_copy_inplace_no_main(id_orig, id_cow);
834 " Remapping ID links for %s: id_orig=%p id_cow=%p\n", id_orig->
name, id_orig, id_cow);
836 #ifdef NESTED_ID_NASTY_WORKAROUND
837 ntree_hack_remap_pointers(
depsgraph, id_cow);
843 RemapCallbackUserData
user_data = {
nullptr};
853 id_cow->
recalc = id_cow_recalc;
887 update_edit_mode_pointers(
depsgraph, id_orig, id_cow);
919 void discard_armature_edit_mode_pointers(
ID *id_cow)
922 armature_cow->
edbo =
nullptr;
925 void discard_curve_edit_mode_pointers(
ID *id_cow)
932 void discard_mball_edit_mode_pointers(
ID *id_cow)
938 void discard_lattice_edit_mode_pointers(
ID *id_cow)
944 void discard_mesh_edit_mode_pointers(
ID *id_cow)
950 void discard_scene_pointers(
ID *id_cow)
959 void discard_edit_mode_pointers(
ID *id_cow)
964 discard_armature_edit_mode_pointers(id_cow);
967 discard_mesh_edit_mode_pointers(id_cow);
970 discard_curve_edit_mode_pointers(id_cow);
973 discard_mball_edit_mode_pointers(id_cow);
976 discard_lattice_edit_mode_pointers(id_cow);
981 discard_scene_pointers(id_cow);
998 if (!check_datablock_expanded(id_cow)) {
1004 #ifdef NESTED_ID_NASTY_WORKAROUND
1005 nested_id_hack_discard_pointers(id_cow);
1013 ob_cow->
data =
nullptr;
1014 ob_cow->
sculpt =
nullptr;
1020 discard_edit_mode_pointers(id_cow);
1025 id_cow->
name[0] =
'\0';
1042 if (id_cow ==
nullptr) {
1046 data.is_valid =
true;
1048 nullptr, id_cow, foreach_libblock_validate_callback, &
data,
IDWALK_NOP);
1049 return data.is_valid;
1064 return check_datablock_expanded(id_cow);
Blender kernel action and pose functionality.
struct AnimData * BKE_animdata_from_id(const struct ID *id)
void BKE_animsys_update_driver_array(struct ID *id)
void BKE_pose_remap_bone_pointers(struct bArmature *armature, struct bPose *pose)
void BKE_pose_pchan_index_rebuild(struct bPose *pose)
bool BKE_gpencil_can_avoid_full_copy_on_write(const struct Depsgraph *depsgraph, struct bGPdata *gpd)
void BKE_gpencil_data_update_orig_pointers(const struct bGPdata *gpd_orig, const struct bGPdata *gpd_eval)
void BKE_gpencil_update_on_write(struct bGPdata *gpd_orig, struct bGPdata *gpd_eval)
void BKE_view_layer_free_ex(struct ViewLayer *view_layer, bool do_id_user)
struct ViewLayer * BKE_view_layer_default_render(const struct Scene *scene)
@ LIB_ID_CREATE_NO_ALLOCATE
@ LIB_ID_COPY_SET_COPIED_ON_WRITE
void BKE_libblock_free_data(struct ID *id, bool do_id_user) ATTR_NONNULL()
struct ID * BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, int flag)
void BKE_libblock_free_data_py(struct ID *id)
void BKE_libblock_free_datablock(struct ID *id, int flag) ATTR_NONNULL()
void BKE_library_foreach_ID_link(struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
@ IDWALK_IGNORE_EMBEDDED_ID
General operations, lookup, etc. for blender objects.
void BKE_object_check_uuids_unique_and_report(const struct Object *object)
bool BKE_object_data_is_in_editmode(const struct Object *ob, const struct 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)
struct Depsgraph Depsgraph
bool DEG_is_active(const struct Depsgraph *depsgraph)
void DEG_debug_print_eval(struct 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_IS_COW(_id_type)
@ LIB_TAG_COPIED_ON_WRITE
@ 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.
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
void restore_to_id(ID *id)
void init_from_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)
bool deg_check_base_in_depsgraph(const Depsgraph *graph, Base *base)
ID * deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode *id_node)
bool deg_copy_on_write_is_needed(const ID *id_orig)
void deg_tag_copy_on_write_id(ID *id_cow, const ID *id_orig)
bool deg_validate_copy_on_write_datablock(ID *id_cow)
@ DEG_ID_LINKED_INDIRECTLY
bool deg_copy_on_write_is_expanded(const ID *id_cow)
void deg_evaluate_copy_on_write(struct ::Depsgraph *graph, const IDNode *id_node)
void deg_free_copy_on_write_datablock(ID *id_cow)
void SEQ_relations_check_uuids_unique_and_report(const Scene *scene)
struct EditFont * editfont
struct EditLatt * editlatt
struct BMEditMesh * edit_mesh
struct NlaStrip * orig_strip
struct SculptSession * sculpt
struct ParticleSystemModifierData * psmd_eval
struct ParticleSystem * psys_eval
struct PTCacheEdit * edit
struct ParticleSystem * orig_psys
struct LightCache * light_cache_data
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