63 library->runtime = MEM_new<LibraryRuntime>(__func__);
77 std::optional<Library *> owner_library,
83 BLI_assert(!owner_library || *owner_library ==
nullptr);
86 const Library *library_src =
reinterpret_cast<const Library *
>(id_src);
99 library_dst->
runtime = MEM_new<LibraryRuntime>(__func__);
101 library_src->
runtime->filepath_abs,
102 sizeof(library_dst->
runtime->filepath_abs));
105 library_dst->
runtime->versionfile = library_src->
runtime->versionfile;
106 library_dst->
runtime->subversionfile = library_src->
runtime->subversionfile;
107 library_dst->
runtime->colorspace = library_src->
runtime->colorspace;
118 if (
lib->archive_parent_library) {
126 for (
Library *&lib_p :
lib->runtime->archived_libraries) {
138 for (
Library *&lib_p :
lib->runtime->archived_libraries) {
152 if (
lib->packedfile !=
186 lib->runtime = MEM_new<LibraryRuntime>(__func__);
194 lib->archive_parent_library->runtime->archived_libraries.append(
lib);
233 if (
lib->filepath != filepath) {
237 STRNCPY(
lib->runtime->filepath_abs, filepath);
260 Library *best_parent_lib =
nullptr;
261 bool do_break =
false;
272 ID *from_id = item->id_pointer.from;
278 if (from_id_lib ==
lib) {
281 if (directly_used_libs.
contains(from_id_lib)) {
283 BLI_assert(best_parent_lib ==
nullptr || best_parent_lib->
runtime->temp_index > 0);
284 best_parent_lib = from_id_lib;
288 if (!from_id_lib->
runtime->parent) {
291 if (!best_parent_lib ||
292 best_parent_lib->
runtime->temp_index > from_id_lib->
runtime->temp_index)
294 best_parent_lib = from_id_lib;
295 if (best_parent_lib->
runtime->temp_index == 0) {
317 if (best_parent_lib) {
318 lib->runtime->parent = best_parent_lib;
319 lib->runtime->temp_index = best_parent_lib->
runtime->temp_index + 1;
322 lib->runtime->parent =
nullptr;
323 lib->runtime->temp_index = 0;
324 directly_used_libs.
add(
lib);
335 lib_iter->runtime->temp_index = 0;
353 directly_used_libs.
add(id_iter->
lib);
363 if (directly_used_libs.
contains(lib_iter)) {
364 BLI_assert(lib_iter->runtime->temp_index == 0);
370 if (lib_iter->runtime->parent) {
371 if (lib_iter->runtime->temp_index > 0) {
375 for (
Library *parent_lib_iter = lib_iter;
376 parent_lib_iter && parent_lib_iter->
runtime->temp_index == 0;
377 parent_lib_iter = parent_lib_iter->runtime->parent)
379 parent_libraries.
append(parent_lib_iter);
381 int parent_temp_index = parent_libraries.
last()->runtime->temp_index +
382 int(parent_libraries.
size()) - 1;
383 for (
Library *parent_lib_iter : parent_libraries) {
385 parent_lib_iter->runtime->temp_index == parent_temp_index);
386 parent_lib_iter->runtime->temp_index = parent_temp_index--;
400 if (directly_used_libs.
contains(lib_iter)) {
401 BLI_assert(lib_iter->runtime->temp_index == 0);
405 if (lib_iter->runtime->parent) {
406 BLI_assert(lib_iter->runtime->temp_index > 0);
409 BLI_assert(lib_iter->runtime->temp_index == 0);
426 if (filepath_abs == lib_iter->runtime->filepath_abs) {
451 archive_library->
runtime->parent = reference_library.
runtime->parent;
457 archive_library->
runtime->tag = reference_library.
runtime->tag & copy_tag;
463 reference_library.
runtime->archived_libraries.append(archive_library);
465 return archive_library;
474 Library *archive_library =
nullptr;
475 for (
Library *lib_iter : reference_library.
runtime->archived_libraries) {
485 packed_id && packed_id->
deep_hash != id_deep_hash,
486 "An already packed ID with same deep hash as the one to be packed, should have already "
487 "be found and used (deduplication) before reaching this code-path");
492 archive_library = lib_iter;
495 if (!archive_library) {
502 BLI_assert(reference_library.
runtime->archived_libraries.contains(archive_library));
503 return archive_library;
516 ID *packed_id = already_packed_ids.
lookup_default(linked_id_deep_hash,
nullptr);
522 auto existing_id_process = [&deep_hashes, &id_remapper](
ID *linked_id,
ID *packed_id) {
531 id_remapper.
add(linked_id, packed_id);
532 linked_id->newid = packed_id;
537 existing_id_process(linked_id, packed_id);
544 existing_id_process(&linked_key->
id, &packed_key->
id);
555 bmain, *linked_id, *linked_id->
lib, linked_id_deep_hash, is_new);
557 auto copied_id_process =
558 [&archive_lib, &deep_hashes, &ids_to_remap, &id_remapper, &already_packed_ids](
559 ID *linked_id,
ID *packed_id) {
570 packed_id->
deep_hash = deep_hashes.hashes.lookup(linked_id);
571 id_remapper.add(linked_id, packed_id);
572 ids_to_remap.add(packed_id);
573 already_packed_ids.
add(packed_id->
deep_hash, packed_id);
584 copied_id_process(linked_id, packed_id);
591 copied_id_process(&linked_key->
id, &embedded_key->
id);
607 for (
ID *
id : ids_to_pack) {
612 "Trying to pack an already packed ID '%s' (from '%s')",
614 id->lib->runtime->filepath_abs);
618 final_ids_to_pack.
add(
id);
622 bmain, final_ids_to_pack.
as_span());
623 if (
const auto *errors = std::get_if<id_hash::DeepHashErrors>(&hash_result)) {
624 if (!errors->missing_files.is_empty()) {
626 "Trying to pack IDs that depend on missing linked libraries: %s",
627 errors->missing_files[0].c_str());
629 if (!errors->updated_files.is_empty()) {
631 "Trying to pack linked ID that has been modified on disk: %s",
632 errors->updated_files[0].c_str());
636 const auto &deep_hashes = std::get<id_hash::ValidDeepHashes>(hash_result);
643 already_packed_ids.
add(
id->deep_hash,
id);
649 for (
ID *linked_id : final_ids_to_pack) {
650 pack_linked_id(bmain, linked_id, deep_hashes, already_packed_ids, ids_to_remap, id_remapper);
664 ids_to_pack.
add(&root_id);
678 if (!referenced_id) {
682 CLOG_ERROR(&
LOG,
"Linked data-block references non-linked data-block");
691 "Non-packed data-block references packed data-block from the same library, "
692 "which is not allowed");
705 ids_to_pack.
add(referenced_id);
722 int i_insert_curr = 0;
723 for (; i_read_curr <
lib->runtime->archived_libraries.size(); i_read_curr++) {
724 if (!
lib->runtime->archived_libraries[i_read_curr]) {
727 if (i_insert_curr < i_read_curr) {
728 lib->runtime->archived_libraries[i_insert_curr] =
729 lib->runtime->archived_libraries[i_read_curr];
734 if (i_insert_curr < i_read_curr) {
735 lib->runtime->archived_libraries.resize(i_insert_curr);
bool BKE_bpath_foreach_path_fixed_process(BPathForeachPathData *bpath_data, char *path, size_t path_maxncpy)
@ IDTYPE_FLAGS_NO_ANIMDATA
@ IDTYPE_FLAGS_NO_LIBLINKING
@ IDTYPE_FLAGS_NEVER_UNUSED
Key * BKE_key_from_id(ID *id)
struct ID * BKE_id_copy_in_lib(Main *bmain, std::optional< Library * > owner_library, const ID *id, std::optional< const ID * > new_owner_id, ID **new_id_p, int flag)
ID * BKE_libblock_find_name_and_library(Main *bmain, short type, const char *name, const char *lib_name)
void id_us_ensure_real(ID *id)
void * BKE_id_new(Main *bmain, short type, const char *name)
@ LIB_ID_COPY_ASSET_METADATA
@ LIB_ID_COPY_NO_ANIMDATA
const char * BKE_id_name(const ID &id)
void BKE_id_blend_write(BlendWriter *writer, ID *id)
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
@ IDWALK_CB_EMBEDDED_NOT_OWNING
#define BKE_LIB_FOREACHID_PROCESS_ID(data_, id_, cb_flag_)
LibraryForeachIDFlag BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data)
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, LibraryForeachIDFlag flag)
@ IDWALK_DO_INTERNAL_RUNTIME_POINTERS
void BKE_libblock_relink_multiple(Main *bmain, const blender::Span< ID * > ids, eIDRemapType remap_type, blender::bke::id::IDRemapper &id_remapper, int remap_flags)
@ LIBRARY_IS_ASSET_EDIT_FILE
@ LIBRARY_TAG_RESYNC_REQUIRED
#define FOREACH_MAIN_ID_END
#define FOREACH_MAIN_LISTBASE_ID_END
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
#define FOREACH_MAIN_LISTBASE_END
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb)
void BKE_main_relations_create(Main *bmain, short flag)
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
const char * BKE_main_blendfile_path(const Main *bmain) ATTR_NONNULL()
void BKE_main_relations_free(Main *bmain)
void BKE_main_ensure_invariants(Main &bmain, std::optional< blender::Span< ID * > > modified_ids=std::nullopt)
void BKE_main_namemap_destroy(UniqueName_Map **r_name_map) ATTR_NONNULL()
bool BKE_main_namemap_contain_name(Main &bmain, Library *lib, short id_type, blender::StringRef name)
PackedFile * BKE_packedfile_duplicate(const PackedFile *pf_src)
void BKE_packedfile_free(PackedFile *pf)
void BKE_packedfile_blend_write(BlendWriter *writer, const PackedFile *pf)
#define BLI_assert_unreachable()
#define BLI_assert_msg(a, msg)
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
#define LISTBASE_FOREACH(type, var, list)
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
bool BLI_path_is_rel(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
char * STRNCPY(char(&dst)[N], const char *src)
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define UNUSED_VARS_NDEBUG(...)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
bool BLO_write_is_undo(BlendWriter *writer)
#define BLT_I18NCONTEXT_ID_LIBRARY
#define CLOG_ERROR(clg_ref,...)
#define CLOG_DEBUG(clg_ref,...)
ID and Library types, which are fundamental for SDNA.
#define ID_IS_PACKED(_id)
#define ID_IS_LINKED(_id)
@ LIBRARY_FLAG_IS_ARCHIVE
Object groups, one object can be in many groups at once.
BMesh const char void * data
const Value & lookup(const Key &key) const
bool add(const Key &key, const Value &value)
Value lookup_default(const Key &key, const Value &default_value) const
bool contains(const Key &key) const
Span< Key > as_span() const
void append(const T &value)
const T & last(const int64_t n=0) const
void add(ID *old_id, ID *new_id)
void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath)
void BKE_library_main_rebuild_hierarchy(Main *bmain)
static void library_runtime_reset(Library *lib)
static void rebuild_hierarchy_best_parent_find(Main *bmain, blender::Set< Library * > &directly_used_libs, Library *lib)
static void library_blend_read_data(BlendDataReader *, ID *id)
static void pack_linked_ids(Main &bmain, const blender::Set< ID * > &ids_to_pack)
static void library_blend_read_after_liblink(BlendLibReader *, ID *id)
static void library_foreach_path(ID *id, BPathForeachPathData *bpath_data)
static void library_blend_write_data(BlendWriter *writer, ID *id, const void *id_address)
static void library_foreach_id(ID *id, LibraryForeachIDData *data)
static Library * add_archive_library(Main &bmain, Library &reference_library)
static void library_init_data(ID *id)
static void library_copy_data(Main *bmain, std::optional< Library * > owner_library, ID *id_dst, const ID *id_src, int)
static void library_free_data(ID *id)
static void pack_linked_id(Main &bmain, ID *linked_id, const id_hash::ValidDeepHashes &deep_hashes, blender::Map< IDHash, ID * > &already_packed_ids, blender::VectorSet< ID * > &ids_to_remap, blender::bke::id::IDRemapper &id_remapper)
std::variant< ValidDeepHashes, DeepHashErrors > IDHashResult
IDHashResult compute_linked_id_deep_hashes(const Main &bmain, Span< const ID * > root_ids)
Library * ensure_archive_library(Main &bmain, ID &id, Library &reference_library, const IDHash &id_deep_hash, bool &is_new)
void main_cleanup_parent_archives(Main &bmain)
void pack_linked_id_hierarchy(Main &bmain, ID &root_id)
Library * search_filepath_abs(ListBase *libraries, blender::StringRef filepath_abs)
LibraryForeachIDCallbackFlag cb_flag
struct PackedFile * packedfile
LibraryRuntimeHandle * runtime
struct Library * archive_parent_library
MainIDRelationsEntryItem * next
MainIDRelationsEntryItem * from_ids
GHash * relations_from_pointers
MainIDRelations * relations
Map< const ID *, IDHash > hashes
static DynamicLibrary lib