[Bf-blender-cvs] [a905436] id-remap: Merge branch 'master' into id-remap
Bastien Montagne
noreply at git.blender.org
Mon Feb 15 19:46:42 CET 2016
Commit: a9054360c6ecac0e51d35ec717c6a90ca655639d
Author: Bastien Montagne
Date: Mon Feb 15 19:43:37 2016 +0100
Branches: id-remap
https://developer.blender.org/rBa9054360c6ecac0e51d35ec717c6a90ca655639d
Merge branch 'master' into id-remap
===================================================================
===================================================================
diff --cc source/blender/blenkernel/intern/library.c
index ea126bf,811fbf5..661b9a5
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@@ -1605,55 -1309,6 +1649,55 @@@ void BKE_libblock_free_us(Main *bmain,
}
}
+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, false);
++ 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 objetcs).
+ * 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) {
+ printf("%s: deleting %s (%d)\n", __func__, id->name, id->us);
+ BLI_assert(id->us == 0);
+ }
+ BKE_libblock_free(bmain, id);
+ }
+ }
+ }
+}
+
Main *BKE_main_new(void)
{
Main *bmain = MEM_callocN(sizeof(Main), "new main");
diff --cc source/blender/windowmanager/intern/wm_operators.c
index 2fb2e69,8a9b069..deb011b
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@@ -2787,399 -2784,6 +2787,399 @@@ static void WM_OT_append(wmOperatorTyp
RNA_def_boolean(ot->srna, "set_fake", false, "Fake User", "Set Fake User for appended items (except Objects and Groups)");
}
+
+static int wm_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ Library *lib;
+ char lib_name[MAX_NAME];
+
+ RNA_string_get(op->ptr, "library", lib_name);
+ lib = (Library *)BKE_libblock_find_name_ex(CTX_data_main(C), ID_LI, lib_name);
+
+ if (lib) {
+ if (lib->parent) {
+ BKE_reportf(op->reports, RPT_ERROR_INVALID_INPUT,
+ "Cannot relocate indirectly linked library '%s'", lib->filepath);
+ return OPERATOR_CANCELLED;
+ }
+ RNA_string_set(op->ptr, "filepath", lib->filepath);
+
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, const bool reload)
+{
+ Library *lib;
+ char lib_name[MAX_NAME];
+
+ RNA_string_get(op->ptr, "library", lib_name);
+ lib = (Library *)BKE_libblock_find_name_ex(CTX_data_main(C), ID_LI, lib_name);
+
+ if (lib) {
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ PropertyRNA *prop;
+ WMLinkAppendData *lapp_data;
+
+ ListBase *lbarray[MAX_LIBARRAY];
+ int lba_idx;
+
+ LinkNode *itemlink;
+ int item_idx;
+
+ int num_ids;
+ char path[FILE_MAX], root[FILE_MAXDIR], libname[FILE_MAX], relname[FILE_MAX];
+ short flag = 0;
+
+ if (RNA_boolean_get(op->ptr, "relative_path")) {
+ flag |= FILE_RELPATH;
+ }
+
+ if (lib->parent && !reload) {
+ BKE_reportf(op->reports, RPT_ERROR_INVALID_INPUT,
+ "Cannot relocate indirectly linked library '%s'", lib->filepath);
+ return OPERATOR_CANCELLED;
+ }
+
+ RNA_string_get(op->ptr, "directory", root);
+ RNA_string_get(op->ptr, "filename", libname);
+
+ if (!BLO_has_bfile_extension(libname)) {
+ BKE_report(op->reports, RPT_ERROR, "Not a library");
+ return OPERATOR_CANCELLED;
+ }
+
+ BLI_join_dirfile(path, sizeof(path), root, libname);
+
+ if (BLI_path_cmp(lib->filepath, path) == 0) {
+ printf("We are supposed to reload '%s' lib (%d)...\n", lib->filepath, lib->id.us);
+
+ lapp_data = wm_link_append_data_new(flag);
+ wm_link_append_data_library_add(lapp_data, path);
+
+ BKE_main_lock(bmain);
+
+ lba_idx = set_listbasepointers(bmain, lbarray);
+ while (lba_idx--) {
+ ID *id = lbarray[lba_idx]->first;
+ const short idcode = id ? GS(id->name) : 0;
+
+ if (!id || !BKE_idcode_is_linkable(idcode)) {
+ /* No need to reload non-linkable datatypes, those will get relinked with their 'users ID'. */
+ continue;
+ }
+
+ for (; id; id = id->next) {
+ if (id->lib == lib) {
+ WMLinkAppendDataItem *item;
+
+ /* We remove it from current Main, and add it to items to link... */
+ /* Note that non-linkable IDs (like e.g. shapekeys) are also explicitely linked here... */
+ BLI_remlink(lbarray[lba_idx], id);
+ item = wm_link_append_data_item_add(lapp_data, id->name + 2, idcode, id);
+ BLI_BITMAP_SET_ALL(item->libraries, true, lapp_data->num_libraries);
+
+ printf("\tdatablock to seek for: %s\n", id->name);
+ }
+ }
+ }
+
- BKE_main_id_flag_all(bmain, LIB_TAG_PRE_EXISTING, true);
++ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
+
+ /* XXX For now, locking is not reentrant so it's not safe to call core linking code with locked Main. */
+ BKE_main_unlock(bmain);
+
+ /* We do not want any instanciation here! */
+ wm_link_do(lapp_data, op->reports, bmain, NULL, NULL, true, true);
+
+ BKE_main_lock(bmain);
+
+ /* We add back old id to bmain.
+ * We need to do this in a first, separated loop, otherwise some of those may not be handled by
+ * ID remapping, which means they would still reference old data to be deleted... */
+ for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; item_idx++, itemlink = itemlink->next) {
+ WMLinkAppendDataItem *item = itemlink->link;
+ ID *old_id = item->customdata;
+
+ BLI_assert(old_id);
+ BLI_addtail(which_libbase(bmain, GS(old_id->name)), old_id);
+ }
+
+ for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; item_idx++, itemlink = itemlink->next) {
+ WMLinkAppendDataItem *item = itemlink->link;
+ ID *old_id = item->customdata;
+ ID *new_id = item->new_id;
+
+ /* Since we asked for placeholders in case of missing IDs, we expect to always get a valid one. */
+ BLI_assert(new_id);
+ if (new_id) {
+// printf("before remap, old_id users: %d (%p), new_id users: %d (%p)\n", old_id->us, old_id, new_id->us, new_id);
+ /* Note that here, we also want to replace indirect usages. */
+ BKE_libblock_remap_locked(bmain, old_id, new_id, ID_REMAP_SKIP_NEVER_NULL_USAGE);
+
+// printf("after remap, old_id users: %d, new_id users: %d\n", old_id->us, new_id->us);
+
+ /* In some cases, new_id might become direct link, remove parent of library in this case. */
+ if (new_id->lib->parent && (new_id->tag & LIB_TAG_INDIRECT) == 0) {
+ BLI_assert(0); /* Should not happen in reload case... */
+ new_id->lib->parent = NULL;
+ }
+ }
+
+ if (old_id->us > 0 && new_id) {
+ size_t len = strlen(old_id->name);
+
+ /* XXX TODO This is utterly weak!!! */
+ if (len > MAX_ID_NAME - 3 && old_id->name[len - 4] == '.') {
+ old_id->name[len - 6] = '.';
+ old_id->name[len - 5] = 'P';
+ }
+ else {
+ len = MIN2(len, MAX_ID_NAME - 3);
+ old_id->name[len] = '.';
+ old_id->name[len + 1] = 'P';
+ old_id->name[len + 2] = '\0';
+ }
+
+ id_sort_by_name(which_libbase(bmain, GS(old_id->name)), old_id);
+
+ BKE_reportf(op->reports, RPT_WARNING,
+ "Lib Reload: Replacing all references to old datablock '%s' by reloaded one failed, "
+ "old one (%d remaining users) had to be kept and was renamed to '%s'",
+ new_id->name, old_id->us, old_id->name);
+ }
+ }
+
+ BKE_main_unlock(bmain);
+
+ for (item_idx = 0, itemlink = lapp_data->items.list; itemlink; item_idx++, itemlink = itemlink->next) {
+ WMLinkAppendDataItem *item = itemlink->link;
+ ID *old_id = item->customdata;
+
+// printf("%p\n", old_id);
+
+ if (old_id->us == 0) {
+ BKE_libblock_free(bmain, old_id);
+ num_ids--;
+ }
+ }
+
+ wm_link_append_data_free(lapp_data);
+ }
+ else {
+ int totfiles = 0;
+
+ printf("We are supposed to relocate '%s' lib to new '%s' one...\n", lib->filepath, libname);
+
+ /* Check if something is indicated for relocate. */
+ prop = RNA_struct_find_property(op->ptr, "files");
+ if (prop) {
+ totfiles = RNA_property_collection_length(op->ptr, prop);
+ if (totfiles == 0) {
+ if (!libname[0]) {
+ BKE_report(op->reports, RPT_ERROR, "Nothing indicated");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ }
+
+ lapp_data = wm_link_append_data_new(flag);
+
+ if (totfiles) {
+ RNA_BEGIN (op->ptr, itemptr, "files")
+ {
+ RNA_string_get(&itemptr, "name", relname);
+
+ BLI_join_dirfile(path, sizeof(path), root, relname);
+
+ if (BLI_path_cmp(path, lib->filepath) == 0 || !BLO_has_bfile_extension(relname)) {
+ continue;
+ }
+
+ printf("\t candidate new lib to reload datablocks from: %s\n", path);
+ wm_link_append_data_library_add(lapp_data, path);
+ }
+ RNA_END;
+ }
+ e
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list