static void rna_ID_user_remap(ID *id, Main *bmain, ID *new_id) { if (GS(id->name) == GS(new_id->name)) { /* For now, do not allow remapping data in linked data from here... */ BKE_libblock_remap(bmain, id, new_id, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_NEVER_NULL_USAGE); } }
void BKE_libblock_delete(Main *bmain, void *idv) { ListBase *lbarray[MAX_LIBARRAY]; int base_count, i; base_count = set_listbasepointers(bmain, lbarray); BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); /* First tag all datablocks directly from target lib. * Note that we go forward here, since we want to check dependencies before users (e.g. meshes before objects). * Avoids to have to loop twice. */ for (i = 0; i < base_count; i++) { ListBase *lb = lbarray[i]; ID *id; for (id = lb->first; id; id = id->next) { /* Note: in case we delete a library, we also delete all its datablocks! */ if ((id == (ID *)idv) || (id->lib == (Library *)idv) || (id->tag & LIB_TAG_DOIT)) { id->tag |= LIB_TAG_DOIT; /* Will tag 'never NULL' users of this ID too. * Note that we cannot use BKE_libblock_unlink() here, since it would ignore indirect (and proxy!) * links, this can lead to nasty crashing here in second, actual deleting loop. * Also, this will also flag users of deleted data that cannot be unlinked * (object using deleted obdata, etc.), so that they also get deleted. */ BKE_libblock_remap(bmain, id, NULL, ID_REMAP_FLAG_NEVER_NULL_USAGE | ID_REMAP_FORCE_NEVER_NULL_USAGE); } } } /* In usual reversed order, such that all usage of a given ID, even 'never NULL' ones, have been already cleared * when we reach it (e.g. Objects being processed before meshes, they'll have already released their 'reference' * over meshes when we come to freeing obdata). */ for (i = base_count; i--; ) { ListBase *lb = lbarray[i]; ID *id, *id_next; for (id = lb->first; id; id = id_next) { id_next = id->next; if (id->tag & LIB_TAG_DOIT) { if (id->us != 0) { #ifdef DEBUG_PRINT printf("%s: deleting %s (%d)\n", __func__, id->name, id->us); #endif BLI_assert(id->us == 0); } BKE_libblock_free(bmain, id); } } } }
void BKE_brush_make_local(Main *bmain, Brush *brush, const bool lib_local) { bool is_local = false, is_lib = false; /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ if (!ID_IS_LINKED_DATABLOCK(brush)) { return; } if (brush->clone.image) { /* Special case: ima always local immediately. Clone image should only have one user anyway. */ id_make_local(bmain, &brush->clone.image->id, false, false); } BKE_library_ID_test_usages(bmain, brush, &is_local, &is_lib); if (lib_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &brush->id); BKE_id_expand_local(&brush->id); /* enable fake user by default */ id_fake_user_set(&brush->id); } else { Brush *brush_new = BKE_brush_copy(bmain, brush); /* Ensures FAKE_USER is set */ brush_new->id.us = 0; /* setting newid is mandatory for complex make_lib_local logic... */ ID_NEW_SET(brush, brush_new); if (!lib_local) { BKE_libblock_remap(bmain, brush, brush_new, ID_REMAP_SKIP_INDIRECT_USAGE); } } } }