[Bf-blender-cvs] [84d25cb] id-remap: Merge branch 'master' into id-remap.
Bastien Montagne
noreply at git.blender.org
Thu Dec 3 16:36:50 CET 2015
Commit: 84d25cb87adc2e9457c29b8586e8c3591ef18800
Author: Bastien Montagne
Date: Tue Dec 1 17:45:22 2015 +0100
Branches: id-remap
https://developer.blender.org/rB84d25cb87adc2e9457c29b8586e8c3591ef18800
Merge branch 'master' into id-remap.
Also, changing how library delete works (not functional currently).
Conflicts:
source/blender/editors/space_outliner/outliner_edit.c
source/blender/editors/space_outliner/outliner_ops.c
source/blender/editors/space_outliner/outliner_tools.c
===================================================================
===================================================================
diff --cc source/blender/blenkernel/BKE_library.h
index 6384143,9a961ba..8381394
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@@ -91,7 -82,7 +91,7 @@@ struct ListBase *which_libbase(struct M
int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]);
void BKE_libblock_free(struct Main *bmain, void *idv);
--void BKE_libblock_free_ex(struct Main *bmain, void *idv, bool do_id_user);
++void BKE_libblock_free_ex(struct Main *bmain, void *idv, const bool do_id_user, const bool use_recursive_delete);
void BKE_libblock_free_us(struct Main *bmain, void *idv);
void BKE_libblock_free_data(struct Main *bmain, struct ID *id);
diff --cc source/blender/blenkernel/intern/blender.c
index fc76c29,fc76c29..3288496
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@@ -565,9 -565,9 +565,9 @@@ bool BKE_read_file_from_memfile
if (bfd) {
/* remove the unused screens and wm */
while (bfd->main->wm.first)
-- BKE_libblock_free_ex(bfd->main, bfd->main->wm.first, true);
++ BKE_libblock_free_ex(bfd->main, bfd->main->wm.first, true, false);
while (bfd->main->screen.first)
-- BKE_libblock_free_ex(bfd->main, bfd->main->screen.first, true);
++ BKE_libblock_free_ex(bfd->main, bfd->main->screen.first, true, false);
setup_app_data(C, bfd, "<memory1>");
}
diff --cc source/blender/blenkernel/intern/library.c
index 4347d80,f1e0bc6..614e351
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@@ -1401,11 -1077,8 +1401,36 @@@ void BKE_libblock_free_data(Main *bmain
BKE_animdata_main_cb(bmain, animdata_dtar_clear_cb, (void *)id);
}
-/* used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c */
-void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user)
++typedef struct IDRecursiveDelete {
++ ID *id_used;
++ ID *id_user;
++ bool changed;
++} IDRecursiveDelete;
++
++static bool foreach_libblock_recursive_delete_callback(void *user_data, ID **id_p, int cb_flag)
++{
++ IDRecursiveDelete *id_recursive_delete = user_data;
++ ID *id_used = id_recursive_delete->id_used;
++ ID *id_user = id_recursive_delete->id_user;
++
++ if ((*id_p == id_used) && (cb_flag & IDWALK_NEVER_NULL)) {
++ id_user->flag |= LIB_DOIT;
++ id_recursive_delete->changed = true;
++ return false; /* No need to keep going on! */
++ }
++
++ return true;
++}
++
+/**
+ * used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c
+ *
- * \param do_id_user if \a true, try to release other ID's 'references' hold by \a idv. */
- void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user)
++ * \param do_id_user if \a true, try to release other ID's 'references' hold by \a idv.
++ * \param use_recursive_delete if \a true and \a do_id_user is true, also delete users of this ID when mandatory
++ * (this applies e.g. in case you delete a Mesh, you also have to
++ * delete all objects using it).
++ */
++void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const bool use_recursive_delete)
{
ID *id = idv;
short type = GS(id->name);
@@@ -1417,11 -1090,7 +1442,56 @@@
BPY_id_release(id);
#endif
- switch (type) { /* GetShort from util.h */
+ if (do_id_user) {
++ if (use_recursive_delete) {
++ /* We check all IDs using current one in a 'never NULL' fashion, and also delete them...
++ * Note that we do not do real recusive calls here, would be dangerous, we just loop until all additional
++ * data to delete has been found (should be two loops at most). */
++ IDRecursiveDelete id_recursive_delete;
++ ListBase *lbarray[MAX_LIBARRAY];
++ int base_count, a;
++
++ BKE_main_id_tag_all(bmain, false);
++
++ base_count = set_listbasepointers(bmain, lbarray);
++
++ id_recursive_delete.id_used = id;
++ id_recursive_delete.changed = true;
++
++ while (id_recursive_delete.changed) {
++ id_recursive_delete.changed = false;
++
++ for (a = base_count; a--; ) {
++ ListBase *lb_rec = lbarray[a];
++ ID *id_user;
++
++ for (id_user = lb_rec->first; id_user; id_user = id_user->next) {
++ id_recursive_delete.id_user = id_user;
++ BKE_library_foreach_ID_link(id_user, foreach_libblock_recursive_delete_callback,
++ &id_recursive_delete, IDWALK_NOP);
++ }
++ }
++ }
++
++ /* And we delete tagged users of id. */
++ for (a = base_count; a--; ) {
++ ListBase *lb_rec = lbarray[a];
++ ID *id_user, *id_user_next;
++
++ for (id_user = lb_rec->first; id_user; id_user = id_user_next) {
++ id_user_next = id_user->next;
++ if (id_user->flag & LIB_DOIT) {
++ BKE_libblock_free_ex(bmain, id_user, true, true);
++ }
++ }
++ }
++ }
+ BKE_libblock_relink_ex(id, NULL, NULL, true);
+ }
+
++ BLI_assert(id->us == 0);
++
+ switch (type) {
case ID_SCE:
BKE_scene_free((Scene *)id);
break;
@@@ -1545,7 -1214,7 +1615,7 @@@
void BKE_libblock_free(Main *bmain, void *idv)
{
-- BKE_libblock_free_ex(bmain, idv, true);
++ BKE_libblock_free_ex(bmain, idv, true, false);
}
void BKE_libblock_free_us(Main *bmain, void *idv) /* test users */
@@@ -1585,7 -1258,7 +1655,7 @@@ void BKE_main_free(Main *mainvar
while ( (id = lb->first) ) {
#if 1
-- BKE_libblock_free_ex(mainvar, id, false);
++ BKE_libblock_free_ex(mainvar, id, false, false);
#else
/* errors freeing ID's can be hard to track down,
* enable this so valgrind will give the line number in its error log */
diff --cc source/blender/editors/space_outliner/outliner_edit.c
index 35341f2,094407b..2690dc1
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@@ -299,162 -290,103 +299,257 @@@ void OUTLINER_OT_item_rename(wmOperator
ot->poll = ED_operator_outliner_active;
}
+ /* Library delete --------------------------------------------------- */
+
-static void lib_delete(bContext *C, TreeElement *te, TreeStoreElem *tselem, ReportList *reports)
++static void lib_delete(bContext *C, TreeElement *te, TreeStoreElem *tselem)
+ {
++ Main *bmain = CTX_data_main(C);
+ Library *lib = (Library *)tselem->id;
+ ListBase *lbarray[MAX_LIBARRAY];
+ int a;
+
- BLI_assert(te->idcode == ID_LI && lib != NULL);
++ BLI_assert(te->idcode == ID_LI && lib != NULL && lib->parent == NULL);
+ UNUSED_VARS_NDEBUG(te);
+
- /* We simply set all ID from given lib (including lib itself) to zero user count.
- * It is not possible to do a proper cleanup without a save/reload in current master. */
- a = set_listbasepointers(CTX_data_main(C), lbarray);
++ a = set_listbasepointers(bmain, lbarray);
++
++ /* First tag all datablocks directly from target lib. */
+ while (a--) {
+ ListBase *lb = lbarray[a];
- ID *id;
++ ID *id, *id_next;
+
- for (id = lb->first; id; id = id->next) {
- if (id->lib == lib) {
- id_fake_user_clear(id);
- id->us = 0;
++ for (id = lb->first; id; id = id_next) {
++ id_next = id->next;
++ if (ELEM(lib, id->lib, (Library *)id)) {
++ BKE_libblock_free_ex(bmain, id, true, true);
+ }
+ }
+ }
-
- BKE_reportf(reports, RPT_WARNING,
- "Please save and reload .blend file to complete deletion of '%s' library",
- ((Library *)tselem->id)->filepath);
+ }
+
+ void lib_delete_cb(
- bContext *C, Scene *UNUSED(scene), TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem)
++ bContext *C, Scene *UNUSED(scene), TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem,
++ void *UNUSED(user_data))
+ {
- lib_delete(C, te, tselem, CTX_wm_reports(C));
++ lib_delete(C, te, tselem);
+ }
+
+ static int outliner_lib_delete_invoke_do(bContext *C, ReportList *reports, TreeElement *te, const float mval[2])
+ {
+ if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (te->idcode == ID_LI && tselem->id) {
+ if (((Library *)tselem->id)->parent) {
+ BKE_reportf(reports, RPT_ERROR_INVALID_INPUT,
+ "Cannot delete indirectly linked library '%s'", ((Library *)tselem->id)->filepath);
+ return OPERATOR_CANCELLED;
+ }
+
- lib_delete(C, te, tselem, reports);
++ lib_delete(C, te, tselem);
+ return OPERATOR_FINISHED;
+ }
+ }
+ else {
+ for (te = te->subtree.first; te; te = te->next) {
+ int ret;
+ if ((ret = outliner_lib_delete_invoke_do(C, reports, te, mval))) {
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ static int outliner_lib_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+ {
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ TreeElement *te;
+ float fmval[2];
+
+ BLI_assert(ar && soops);
+
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+
+ for (te = soops->tree.first; te; te = te->next) {
+ int ret;
+
+ if ((ret = outliner_lib_delete_invoke_do(C, op->reports, te, fmval))) {
+ return ret;
+ }
+ }
+
+ return OPERATOR_CANCELLED;
+ }
+
+ void OUTLINER_OT_lib_delete(wmOperatorType *ot)
+ {
+ ot->name = "Delete Library";
+ ot->idname = "OUTLINER_OT_lib_delete";
+ ot->description = "Delete the library under cursorn (needs a save/reload)";
+
+ ot->invoke = outliner_lib_delete_invoke;
+ ot->poll = ED_operator_outliner_active;
+ }
+
+/* Library relocate/reload --------------------------------------------------- */
+
+static int item_lib_relocate(
- bContext *C, TreeElement *te, TreeStoreElem *tselem, wmOperatorType *ot, const bool reload)
++ bContext *C, TreeElement *te, TreeStoreElem *tselem, wmOperatorType *ot, const bool reload)
+{
+ PointerRNA op_props;
+ int ret = 0;
+
+ BLI_assert(te->idcode == ID_LI && tselem->id != NULL);
+ UNUSED_VARS_NDEBUG(te);
+
+ WM_operator_properties_create_ptr(&op_props, ot);
+
+ RNA_string_set(&op_props, "library", tselem->id->name + 2);
+
+ if (reload) {
+ Library *lib = (Library *)tselem->id;
+ char dir[FILE_MAXDIR], filename[FILE_MAX];
+
+ BLI_split_dirfile(lib->filepat
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list