[Bf-blender-cvs] [318f347] soc-2016-layer_manager: Store array of all layer items in the layer tree

Julian Eisel noreply at git.blender.org
Wed Jun 8 02:39:22 CEST 2016


Commit: 318f347cd4f224185bb2020610c12a561ea40e25
Author: Julian Eisel
Date:   Wed Jun 8 02:08:38 2016 +0200
Branches: soc-2016-layer_manager
https://developer.blender.org/rB318f347cd4f224185bb2020610c12a561ea40e25

Store array of all layer items in the layer tree

Coexists with LayerTree.items and LayerTreeItem.childs listbases which were used for recursive iterations over the layer tree (using BKE_layertree_iterate or BKE_layeritem_iterate_childs). However, it was a bit annoying having to use this everywhere, especially if many args had to be passed as void *. Also, iterative methods with arrays instead of listbases should give us a bit of speedup.
It's possible LayerTree.items will not be needed anymore, but will leave in for now.

Array is only used on BKE level so far.

===================================================================

M	source/blender/blenkernel/BKE_layer.h
M	source/blender/blenkernel/intern/layer.c
M	source/blender/makesdna/DNA_space_types.h

===================================================================

diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index 49f8fb7..e6896cf 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -58,6 +58,11 @@ void BKE_layertree_delete(LayerTree *ltree);
 bool BKE_layertree_iterate(const LayerTree *ltree, LayerTreeIterFunc foreach, void *customdata, const bool inverse);
 int  BKE_layertree_get_totitems(const LayerTree *ltree);
 
+#define BKE_LAYERTREE_ITER_START(ltree, idx_name, litem_name) \
+	for (int idx_name = 0; idx_name < BKE_layertree_get_totitems(ltree); idx_name++) { \
+		LayerTreeItem *litem_name = ltree->items_all[idx_name];
+#define BKE_LAYERTREE_ITER_END } (void)0
+
 /* -------------------------------------------------------------------- */
 /* Layer Tree Item */
 
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 1b92df3..c12ea80 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -44,6 +44,8 @@
 
 #include "MEM_guardedalloc.h"
 
+static void layeritem_free(LayerTreeItem *litem);
+
 
 /* -------------------------------------------------------------------- */
 /** \name Layer Tree
@@ -61,12 +63,16 @@ LayerTree *BKE_layertree_new(const eLayerTree_Type type)
 
 void BKE_layertree_delete(LayerTree *ltree)
 {
-	for (LayerTreeItem *litem = ltree->items.first, *next_litem; litem; litem = next_litem) {
-		next_litem = litem->next;
-		BKE_layeritem_remove(litem, true);
+	BKE_LAYERTREE_ITER_START(ltree, i, litem)
+	{
+		/* layeritem_free does all we need in this case. No un-registering needed */
+		layeritem_free(litem);
 	}
-	BLI_assert(BLI_listbase_is_empty(&ltree->items));
+	BKE_LAYERTREE_ITER_END;
 
+	if (ltree->items_all) {
+		MEM_freeN(ltree->items_all);
+	}
 	MEM_freeN(ltree);
 }
 
@@ -122,6 +128,9 @@ int BKE_layertree_get_totitems(const LayerTree *ltree)
 
 /**
  * Register an already allocated \a litem.
+ *
+ * \note Reallocates memory for item storage array, if you want to add many items at once,
+ * better do differently (e.g. _ex version that allows reserving memory)
  */
 void BKE_layeritem_register(
         LayerTree *tree, LayerTreeItem *litem, LayerTreeItem *parent,
@@ -129,6 +138,7 @@ void BKE_layeritem_register(
         const LayerItemPollFunc poll, LayerItemDrawFunc draw, LayerItemDrawSettingsFunc draw_settings)
 {
 	litem->type = type;
+	litem->index = tree->tot_items;
 	litem->tree = tree;
 	BLI_strncpy(litem->name, name, sizeof(litem->name));
 
@@ -137,7 +147,9 @@ void BKE_layeritem_register(
 	litem->draw = draw;
 	litem->draw_settings = draw_settings;
 
-	tree->tot_items++;
+	/* add to item array */
+	tree->items_all = MEM_reallocN(tree->items_all, sizeof(*tree->items_all) * ++tree->tot_items);
+	tree->items_all[tree->tot_items - 1] = litem;
 
 	if (parent) {
 		BLI_assert(ELEM(parent->type, LAYER_ITEMTYPE_GROUP));
@@ -168,29 +180,52 @@ LayerTreeItem *BKE_layeritem_add(
 	return litem;
 }
 
+static void layeritem_free(LayerTreeItem *litem)
+{
+	if (litem->free) {
+		litem->free(litem);
+	}
+	MEM_freeN(litem);
+}
+
+
 /**
- * Free and unlink \a litem from the list it's stored in.
+ * Recursive function to remove \a litem. Used to avoid multiple realloc's
+ * for LayerTree.items_all, instead caller can simply realloc once (afterwards!).
  *
  * \param remove_children: Free and unlink all children (and their children, etc) of \a litem as well.
- * \note Recursive
  */
-void BKE_layeritem_remove(LayerTreeItem *litem, const bool remove_children)
+static void layeritem_remove_ex(LayerTreeItem *litem, const bool remove_children)
 {
 	BLI_remlink(litem->parent ? &litem->parent->childs : &litem->tree->items, litem);
+
+	for (int i = litem->index + 1; i < litem->tree->tot_items; i++) {
+		litem->tree->items_all[i - 1] = litem->tree->items_all[i];
+		litem->tree->items_all[i - 1]->index--;
+	}
 	litem->tree->tot_items--;
 
 	if (remove_children) {
 		for (LayerTreeItem *child = litem->childs.first, *child_next; child; child = child_next) {
 			child_next = child->next;
-			BKE_layeritem_remove(child, true);
+			layeritem_remove_ex(child, true);
 		}
 		BLI_assert(BLI_listbase_is_empty(&litem->childs));
 	}
+	layeritem_free(litem);
+}
 
-	if (litem->free) {
-		litem->free(litem);
-	}
-	MEM_freeN(litem);
+/**
+ * Free and unlink \a litem from the list and the array it's stored in.
+ *
+ * \param remove_children: Free and unlink all children (and their children, etc) of \a litem as well.
+ * \note Calls recursive #layeritem_remove_ex.
+ */
+void BKE_layeritem_remove(LayerTreeItem *litem, const bool remove_children)
+{
+	LayerTree *ltree = litem->tree; /* store before deleting litem */
+	layeritem_remove_ex(litem, remove_children);
+	ltree->items_all = MEM_reallocN(ltree->items_all, sizeof(*ltree->items_all) * ltree->tot_items);
 }
 
 /**
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index f8e73db..782c3f4 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -1344,6 +1344,8 @@ typedef struct LayerTree {
 	/* LayerTreeItem - Only items of the first level in the hierarchy, these may have children then.
 	 * TODO check if worth using array instead */
 	ListBase items;
+	/* Array of all layer tree items, including all childs. Using array in hope it speeds up iterations. */
+	struct LayerTreeItem **items_all;
 } LayerTree;
 
 /**
@@ -1353,7 +1355,8 @@ typedef struct LayerTree {
 typedef struct LayerTreeItem {
 	struct LayerTreeItem *next, *prev;
 
-	int type, pad; /* eLayerTreeItem_Type */
+	int type;      /* eLayerTreeItem_Type */
+	int index;     /* index of the item - stored to avoid loockups */
 	char name[64]; /* MAX_NAME */
 
 	struct LayerTree *tree; /* pointer back to layer tree - TODO check if needed */




More information about the Bf-blender-cvs mailing list