[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