Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/lib_id.c
| Show First 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | IDTypeInfo IDType_ID_LINK_PLACEHOLDER = { | ||||
| .foreach_cache = NULL, | .foreach_cache = NULL, | ||||
| .blend_write = NULL, | .blend_write = NULL, | ||||
| .blend_read_data = NULL, | .blend_read_data = NULL, | ||||
| .blend_read_lib = NULL, | .blend_read_lib = NULL, | ||||
| .blend_read_expand = NULL, | .blend_read_expand = NULL, | ||||
| .blend_read_undo_preserve = NULL, | .blend_read_undo_preserve = NULL, | ||||
| .lib_override_apply_post = NULL, | |||||
| }; | }; | ||||
| /* GS reads the memory pointed at in a specific ordering. | /* GS reads the memory pointed at in a specific ordering. | ||||
| * only use this definition, makes little and big endian systems | * only use this definition, makes little and big endian systems | ||||
| * work fine, in conjunction with MAKE_ID */ | * work fine, in conjunction with MAKE_ID */ | ||||
| /* ************* general ************************ */ | /* ************* general ************************ */ | ||||
| ▲ Show 20 Lines • Show All 1,665 Lines • ▼ Show 20 Lines | static void library_make_local_copying_check(ID *id, | ||||
| GSet *loop_tags, | GSet *loop_tags, | ||||
| MainIDRelations *id_relations, | MainIDRelations *id_relations, | ||||
| GSet *done_ids) | GSet *done_ids) | ||||
| { | { | ||||
| if (BLI_gset_haskey(done_ids, id)) { | if (BLI_gset_haskey(done_ids, id)) { | ||||
| return; /* Already checked, nothing else to do. */ | return; /* Already checked, nothing else to do. */ | ||||
| } | } | ||||
| MainIDRelationsEntry *entry = BLI_ghash_lookup(id_relations->id_used_to_user, id); | MainIDRelationsEntry *entry = BLI_ghash_lookup(id_relations->relations_from_pointers, id); | ||||
| BLI_gset_insert(loop_tags, id); | BLI_gset_insert(loop_tags, id); | ||||
| for (; entry != NULL; entry = entry->next) { | for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != NULL; | ||||
| from_id_entry = from_id_entry->next) { | |||||
| /* Used_to_user stores ID pointer, not pointer to ID pointer. */ | |||||
| ID *par_id = (ID *)entry->id_pointer; | |||||
| /* Our oh-so-beloved 'from' pointers... Those should always be ignored here, since the actual | /* Our oh-so-beloved 'from' pointers... Those should always be ignored here, since the actual | ||||
| * relation we want to check is in the other way around. */ | * relation we want to check is in the other way around. */ | ||||
| if (entry->usage_flag & IDWALK_CB_LOOPBACK) { | if (from_id_entry->usage_flag & IDWALK_CB_LOOPBACK) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| ID *from_id = from_id_entry->id_pointer.from; | |||||
| /* Shape-keys are considered 'private' to their owner ID here, and never tagged | /* Shape-keys are considered 'private' to their owner ID here, and never tagged | ||||
| * (since they cannot be linked), so we have to switch effective parent to their owner. | * (since they cannot be linked), so we have to switch effective parent to their owner. | ||||
| */ | */ | ||||
| if (GS(par_id->name) == ID_KE) { | if (GS(from_id->name) == ID_KE) { | ||||
| par_id = ((Key *)par_id)->from; | from_id = ((Key *)from_id)->from; | ||||
| } | } | ||||
| if (par_id->lib == NULL) { | if (from_id->lib == NULL) { | ||||
| /* Local user, early out to avoid some gset querying... */ | /* Local user, early out to avoid some gset querying... */ | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (!BLI_gset_haskey(done_ids, par_id)) { | if (!BLI_gset_haskey(done_ids, from_id)) { | ||||
| if (BLI_gset_haskey(loop_tags, par_id)) { | if (BLI_gset_haskey(loop_tags, from_id)) { | ||||
| /* We are in a 'dependency loop' of IDs, this does not say us anything, skip it. | /* We are in a 'dependency loop' of IDs, this does not say us anything, skip it. | ||||
| * Note that this is the situation that can lead to archipelagoes of linked data-blocks | * Note that this is the situation that can lead to archipelagoes of linked data-blocks | ||||
| * (since all of them have non-local users, they would all be duplicated, | * (since all of them have non-local users, they would all be duplicated, | ||||
| * leading to a loop of unused linked data-blocks that cannot be freed since they all use | * leading to a loop of unused linked data-blocks that cannot be freed since they all use | ||||
| * each other...). */ | * each other...). */ | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* Else, recursively check that user ID. */ | /* Else, recursively check that user ID. */ | ||||
| library_make_local_copying_check(par_id, loop_tags, id_relations, done_ids); | library_make_local_copying_check(from_id, loop_tags, id_relations, done_ids); | ||||
| } | } | ||||
| if (par_id->tag & LIB_TAG_DOIT) { | if (from_id->tag & LIB_TAG_DOIT) { | ||||
| /* This user will be fully local in future, so far so good, | /* This user will be fully local in future, so far so good, | ||||
| * nothing to do here but check next user. */ | * nothing to do here but check next user. */ | ||||
| } | } | ||||
| else { | else { | ||||
| /* This user won't be fully local in future, so current ID won't be either. | /* This user won't be fully local in future, so current ID won't be either. | ||||
| * And we are done checking it. */ | * And we are done checking it. */ | ||||
| id->tag &= ~LIB_TAG_DOIT; | id->tag &= ~LIB_TAG_DOIT; | ||||
| break; | break; | ||||
| ▲ Show 20 Lines • Show All 570 Lines • Show Last 20 Lines | |||||