Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/main.c
| Show All 29 Lines | |||||
| #include "BLI_blenlib.h" | #include "BLI_blenlib.h" | ||||
| #include "BLI_ghash.h" | #include "BLI_ghash.h" | ||||
| #include "BLI_mempool.h" | #include "BLI_mempool.h" | ||||
| #include "BLI_threads.h" | #include "BLI_threads.h" | ||||
| #include "DNA_ID.h" | #include "DNA_ID.h" | ||||
| #include "BKE_global.h" | #include "BKE_global.h" | ||||
| #include "BKE_idtype.h" | |||||
| #include "BKE_lib_id.h" | #include "BKE_lib_id.h" | ||||
| #include "BKE_lib_query.h" | #include "BKE_lib_query.h" | ||||
| #include "BKE_main.h" | #include "BKE_main.h" | ||||
| #include "BKE_main_idmap.h" | #include "BKE_main_idmap.h" | ||||
| #include "IMB_imbuf.h" | #include "IMB_imbuf.h" | ||||
| #include "IMB_imbuf_types.h" | #include "IMB_imbuf_types.h" | ||||
| ▲ Show 20 Lines • Show All 307 Lines • ▼ Show 20 Lines | GSet *BKE_main_gset_create(Main *bmain, GSet *gset) | ||||
| ID *id; | ID *id; | ||||
| FOREACH_MAIN_ID_BEGIN (bmain, id) { | FOREACH_MAIN_ID_BEGIN (bmain, id) { | ||||
| BLI_gset_add(gset, id); | BLI_gset_add(gset, id); | ||||
| } | } | ||||
| FOREACH_MAIN_ID_END; | FOREACH_MAIN_ID_END; | ||||
| return gset; | return gset; | ||||
| } | } | ||||
| /* Utils for ID's library weak reference API. */ | |||||
| typedef struct LibWeakRefKey { | |||||
| char filepath[FILE_MAX]; | |||||
| char id_name[MAX_ID_NAME]; | |||||
| } LibWeakRefKey; | |||||
| static LibWeakRefKey *lib_weak_key_create(LibWeakRefKey *key, | |||||
| const char *lib_path, | |||||
| const char *id_name) | |||||
| { | |||||
| if (key == NULL) { | |||||
| key = MEM_mallocN(sizeof(*key), __func__); | |||||
| } | |||||
| BLI_strncpy(key->filepath, lib_path, sizeof(key->filepath)); | |||||
| BLI_strncpy(key->id_name, id_name, sizeof(key->id_name)); | |||||
| return key; | |||||
| } | |||||
| static uint lib_weak_key_hash(const void *ptr) | |||||
| { | |||||
| const LibWeakRefKey *string_pair = ptr; | |||||
| uint hash = BLI_ghashutil_strhash_p_murmur(string_pair->filepath); | |||||
| return hash ^ BLI_ghashutil_strhash_p_murmur(string_pair->id_name); | |||||
| } | |||||
| static bool lib_weak_key_cmp(const void *a, const void *b) | |||||
| { | |||||
| const LibWeakRefKey *string_pair_a = a; | |||||
| const LibWeakRefKey *string_pair_b = b; | |||||
| return !(STREQ(string_pair_a->filepath, string_pair_b->filepath) && | |||||
campbellbarton: Since this is `main.c` prefer common prefix on utility functions. | |||||
| STREQ(string_pair_a->id_name, string_pair_b->id_name)); | |||||
| } | |||||
| /** | |||||
| * Generate a mapping between 'library path' of an ID (as a pair (relative blend file path, id | |||||
| * name)), and a current local ID, if any. | |||||
| * | |||||
| * This uses the information stored in `ID.library_weak_reference`. | |||||
| */ | |||||
| GHash *BKE_main_library_weak_reference_create(Main *bmain) | |||||
| { | |||||
| GHash *library_weak_reference_mapping = BLI_ghash_new( | |||||
| lib_weak_key_hash, lib_weak_key_cmp, __func__); | |||||
| ListBase *lb; | |||||
| FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) { | |||||
| ID *id_iter = lb->first; | |||||
| if (id_iter == NULL) { | |||||
| continue; | |||||
Done Inline Actions*picky* the NULL check could be before the function call. campbellbarton: *picky* the NULL check could be before the function call. | |||||
| } | |||||
| if (!BKE_idtype_idcode_append_is_reusable(GS(id_iter->name))) { | |||||
| continue; | |||||
| } | |||||
| BLI_assert(BKE_idtype_idcode_is_linkable(GS(id_iter->name))); | |||||
| FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id_iter) { | |||||
Done Inline ActionsIt'd be more efficient to loop over list-base types, skipping all lists that fail the BKE_idtype_idcode_append_is_reusable test. campbellbarton: It'd be more efficient to loop over list-base types, skipping all lists that fail the… | |||||
| if (id_iter->library_weak_reference == NULL) { | |||||
| continue; | |||||
| } | |||||
| LibWeakRefKey *key = lib_weak_key_create(NULL, | |||||
| id_iter->library_weak_reference->library_filepath, | |||||
| id_iter->library_weak_reference->library_id_name); | |||||
| BLI_ghash_insert(library_weak_reference_mapping, key, id_iter); | |||||
| } | |||||
| FOREACH_MAIN_LISTBASE_ID_END; | |||||
| } | |||||
| FOREACH_MAIN_LISTBASE_END; | |||||
| return library_weak_reference_mapping; | |||||
| } | |||||
| /** | |||||
| * Destroy the data generated by #BKE_main_library_weak_reference_create. | |||||
| */ | |||||
| void BKE_main_library_weak_reference_destroy(GHash *library_weak_reference_mapping) | |||||
| { | |||||
| BLI_ghash_free(library_weak_reference_mapping, MEM_freeN, NULL); | |||||
| } | |||||
| /** | |||||
| * Search for a local ID matching the given linked ID reference. | |||||
| * | |||||
| * \param library_weak_reference_mapping the mapping data generated by | |||||
campbellbartonUnsubmitted Done Inline Actions*picky* use colon after argument name. campbellbarton: *picky* use colon after argument name. | |||||
| * #BKE_main_library_weak_reference_create. | |||||
| * \param library_relative_path the path of a blend file library (relative to current working one). | |||||
| * \param library_id_name the full ID name, including the leading two chars encoding the ID type. | |||||
| */ | |||||
| ID *BKE_main_library_weak_reference_search_item(GHash *library_weak_reference_mapping, | |||||
| const char *library_filepath, | |||||
| const char *library_id_name) | |||||
| { | |||||
| LibWeakRefKey key; | |||||
| lib_weak_key_create(&key, library_filepath, library_id_name); | |||||
| return (ID *)BLI_ghash_lookup(library_weak_reference_mapping, &key); | |||||
| } | |||||
| /** | |||||
| * Add the given ID weak library reference to given local ID and the runtime mapping. | |||||
| * | |||||
| * \param library_weak_reference_mapping the mapping data generated by | |||||
| * #BKE_main_library_weak_reference_create. | |||||
| * \param library_relative_path the path of a blend file library (relative to current working one). | |||||
| * \param library_id_name the full ID name, including the leading two chars encoding the ID type. | |||||
| * \param new_id New local ID matching given weak reference. | |||||
| */ | |||||
| void BKE_main_library_weak_reference_add_item(GHash *library_weak_reference_mapping, | |||||
| const char *library_filepath, | |||||
| const char *library_id_name, | |||||
| ID *new_id) | |||||
| { | |||||
| BLI_assert(GS(library_id_name) == GS(new_id->name)); | |||||
| BLI_assert(new_id->library_weak_reference == NULL); | |||||
| BLI_assert(BKE_idtype_idcode_append_is_reusable(GS(new_id->name))); | |||||
| new_id->library_weak_reference = MEM_mallocN(sizeof(*(new_id->library_weak_reference)), | |||||
| __func__); | |||||
| LibWeakRefKey *key = lib_weak_key_create(NULL, library_filepath, library_id_name); | |||||
| void **id_p; | |||||
| const bool already_exist_in_mapping = BLI_ghash_ensure_p( | |||||
| library_weak_reference_mapping, key, &id_p); | |||||
| BLI_assert(!already_exist_in_mapping); | |||||
| BLI_strncpy(new_id->library_weak_reference->library_filepath, | |||||
| library_filepath, | |||||
| sizeof(new_id->library_weak_reference->library_filepath)); | |||||
| BLI_strncpy(new_id->library_weak_reference->library_id_name, | |||||
| library_id_name, | |||||
| sizeof(new_id->library_weak_reference->library_id_name)); | |||||
| *id_p = new_id; | |||||
| } | |||||
| /** | |||||
| * Update the status of the given ID weak library reference in current local IDs and the runtime | |||||
| * mapping. | |||||
| * | |||||
| * This effectively transfers the 'ownership' of the given weak reference from `old_id` to | |||||
| * `new_id`. | |||||
| * | |||||
| * \param library_weak_reference_mapping the mapping data generated by | |||||
| * #BKE_main_library_weak_reference_create. | |||||
| * \param library_relative_path the path of a blend file library (relative to current working one). | |||||
| * \param library_id_name the full ID name, including the leading two chars encoding the ID type. | |||||
| * \param old_id Existing local ID matching given weak reference. | |||||
| * \param new_id New local ID matching given weak reference. | |||||
| */ | |||||
| void BKE_main_library_weak_reference_update_item(GHash *library_weak_reference_mapping, | |||||
| const char *library_filepath, | |||||
| const char *library_id_name, | |||||
| ID *old_id, | |||||
| ID *new_id) | |||||
| { | |||||
| BLI_assert(GS(library_id_name) == GS(old_id->name)); | |||||
| BLI_assert(GS(library_id_name) == GS(new_id->name)); | |||||
| BLI_assert(old_id->library_weak_reference != NULL); | |||||
| BLI_assert(new_id->library_weak_reference == NULL); | |||||
| BLI_assert(STREQ(old_id->library_weak_reference->library_filepath, library_filepath)); | |||||
| BLI_assert(STREQ(old_id->library_weak_reference->library_id_name, library_id_name)); | |||||
| LibWeakRefKey key; | |||||
| lib_weak_key_create(&key, library_filepath, library_id_name); | |||||
| void **id_p = BLI_ghash_lookup_p(library_weak_reference_mapping, &key); | |||||
| BLI_assert(id_p != NULL && *id_p == old_id); | |||||
| new_id->library_weak_reference = old_id->library_weak_reference; | |||||
| old_id->library_weak_reference = NULL; | |||||
| *id_p = new_id; | |||||
| } | |||||
| /** | |||||
| * Remove the given ID weak library reference from the given local ID and the runtime mapping. | |||||
| * | |||||
| * \param library_weak_reference_mapping the mapping data generated by | |||||
| * #BKE_main_library_weak_reference_create. | |||||
| * \param library_relative_path the path of a blend file library (relative to current working one). | |||||
| * \param library_id_name the full ID name, including the leading two chars encoding the ID type. | |||||
| * \param old_id Existing local ID matching given weak reference. | |||||
| */ | |||||
| void BKE_main_library_weak_reference_remove_item(GHash *library_weak_reference_mapping, | |||||
| const char *library_filepath, | |||||
| const char *library_id_name, | |||||
| ID *old_id) | |||||
| { | |||||
| BLI_assert(GS(library_id_name) == GS(old_id->name)); | |||||
| BLI_assert(old_id->library_weak_reference != NULL); | |||||
| LibWeakRefKey key; | |||||
| lib_weak_key_create(&key, library_filepath, library_id_name); | |||||
| BLI_assert(BLI_ghash_lookup(library_weak_reference_mapping, &key) == old_id); | |||||
| BLI_ghash_remove(library_weak_reference_mapping, &key, MEM_freeN, NULL); | |||||
| MEM_SAFE_FREE(old_id->library_weak_reference); | |||||
| } | |||||
| /** | /** | ||||
| * Generates a raw .blend file thumbnail data from given image. | * Generates a raw .blend file thumbnail data from given image. | ||||
| * | * | ||||
| * \param bmain: If not NULL, also store generated data in this Main. | * \param bmain: If not NULL, also store generated data in this Main. | ||||
| * \param img: ImBuf image to generate thumbnail data from. | * \param img: ImBuf image to generate thumbnail data from. | ||||
| * \return The generated .blend file raw thumbnail data. | * \return The generated .blend file raw thumbnail data. | ||||
| */ | */ | ||||
| BlendThumbnail *BKE_main_thumbnail_from_imbuf(Main *bmain, ImBuf *img) | BlendThumbnail *BKE_main_thumbnail_from_imbuf(Main *bmain, ImBuf *img) | ||||
| ▲ Show 20 Lines • Show All 245 Lines • Show Last 20 Lines | |||||
Since this is main.c prefer common prefix on utility functions.