[Bf-blender-cvs] [e1d43df] soc-2016-layer_manager: Layer drag & drop reordering

Julian Eisel noreply at git.blender.org
Thu Jun 16 01:56:40 CEST 2016


Commit: e1d43df90bf76c051770e1123d78c53f097acf59
Author: Julian Eisel
Date:   Thu Jun 16 01:44:58 2016 +0200
Branches: soc-2016-layer_manager
https://developer.blender.org/rBe1d43df90bf76c051770e1123d78c53f097acf59

Layer drag & drop reordering

Took some time to get logic to work like user's would expect it, but seems to work now.

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

M	release/datafiles/brushicons/snake_hook.png
M	source/blender/blenkernel/BKE_layer.h
M	source/blender/blenkernel/intern/layer.c
M	source/blender/editors/space_layers/layers_draw.c
M	source/blender/editors/space_layers/layers_intern.h
M	source/blender/editors/space_layers/layers_ops.c
M	source/blender/editors/space_layers/layers_util.c

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

diff --git a/release/datafiles/brushicons/snake_hook.png b/release/datafiles/brushicons/snake_hook.png
index 961c54e..908a7f1 100644
Binary files a/release/datafiles/brushicons/snake_hook.png and b/release/datafiles/brushicons/snake_hook.png differ
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index 81cd051..cc30933 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -90,6 +90,7 @@ void BKE_layeritem_register(
         const LayerItemPollFunc poll, LayerItemDrawFunc draw, LayerItemDrawSettingsFunc draw_settings);
 void BKE_layeritem_remove(LayerTreeItem *litem, const bool remove_children);
 
+void BKE_layeritem_move(LayerTreeItem *litem, const int newidx);
 void BKE_layeritem_group_assign(LayerTreeItem *group, LayerTreeItem *item);
 
 bool BKE_layeritem_iterate_childs(
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 4b346c7..da3c4ef 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -229,6 +229,28 @@ void BKE_layeritem_remove(LayerTreeItem *litem, const bool remove_children)
 }
 
 /**
+ * Move \a litem that's already in the layer tree to slot \a newidx.
+ */
+void BKE_layeritem_move(LayerTreeItem *litem, const int newidx)
+{
+	const bool is_higher = litem->index < newidx;
+
+	for (int i = is_higher ? litem->index + 1 : litem->index - 1;
+	     i < litem->tree->tot_items && i >= 0;
+	     is_higher ? i++ : i--)
+	{
+		const int iter_new_idx = i + (is_higher ? -1 : 1);
+		litem->tree->items_all[iter_new_idx] = litem->tree->items_all[i];
+		litem->tree->items_all[iter_new_idx]->index = iter_new_idx;
+		if (i == newidx) {
+			litem->tree->items_all[i] = litem;
+			litem->index = i;
+			break;
+		}
+	}
+}
+
+/**
  * Assign \a item to \a group.
  */
 void BKE_layeritem_group_assign(LayerTreeItem *group, LayerTreeItem *item)
diff --git a/source/blender/editors/space_layers/layers_draw.c b/source/blender/editors/space_layers/layers_draw.c
index 29498a9..ce805fd 100644
--- a/source/blender/editors/space_layers/layers_draw.c
+++ b/source/blender/editors/space_layers/layers_draw.c
@@ -22,6 +22,7 @@
  *  \ingroup splayers
  */
 
+#include "BIF_gl.h"
 #include "BIF_glutil.h"
 
 #include "BLI_utildefines.h"
@@ -67,24 +68,23 @@ static int layer_tile_indent_level_get(const LayerTreeItem *litem)
 }
 
 /**
- * Draw the tile for \a litem.
  * \return the height of the drawn tile.
  */
 static float layer_tile_draw(
-        LayerTreeItem *litem,
-        const bContext *C, ARegion *ar, SpaceLayers *slayer, uiBlock *block, uiStyle *style,
-        float ofs_y, int idx)
+        LayerTile *tile,
+        const bContext *C, ARegion *ar, uiBlock *block, uiStyle *style,
+        float row_ofs_y, int idx)
 {
-	LayerTile *tile = BLI_ghash_lookup(slayer->tiles, litem);
+	LayerTreeItem *litem = tile->litem;
 	const bool expanded = litem->draw_settings && (tile->flag & LAYERTILE_EXPANDED);
 
 	const float pad_x = 4.0f * UI_DPI_FAC;
 	const float header_y = LAYERTILE_HEADER_HEIGHT;
 
-	const float ofs_x = layer_tile_indent_level_get(litem) * LAYERITEM_INDENT_SIZE;
+	const float ofs_x = layer_tile_indent_level_get(litem) * LAYERITEM_INDENT_SIZE + tile->ofs[0];
+	const float ofs_y = row_ofs_y + tile->ofs[1];
 	const rctf rect = {-ar->v2d.cur.xmin + ofs_x, ar->winx,
 	                   -ar->v2d.cur.ymin - ofs_y - header_y, -ar->v2d.cur.ymin - ofs_y};
-	int size_y = 0;
 	int tile_size_y = 0;
 
 	/* draw item itself */
@@ -120,14 +120,23 @@ static float layer_tile_draw(
 		        rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), 0, 0, style);
 		litem->draw_settings(C, litem, layout);
 
+		int size_y = 0;
 		UI_block_layout_resolve(block, NULL, &size_y);
 		tile_size_y = -(ofs_y + size_y + ar->v2d.cur.ymin);
 	}
 
-	/* draw background */
-	if (idx % 2) {
-		UI_ThemeColorShade(TH_BACK, 10);
+	/* draw background, this is done after defining buttons so we can get real layout height */
+	if ((idx % 2) || (tile->flag & LAYERTILE_FLOATING)) {
+		if (tile->flag & LAYERTILE_FLOATING) {
+			UI_ThemeColorShadeAlpha(TH_BACK, idx % 2 ? 10 : 0, -100);
+		}
+		else {
+			UI_ThemeColorShade(TH_BACK, 10);
+		}
+
+		glEnable(GL_BLEND);
 		fdrawbox_filled(0, rect.ymax - tile_size_y, rect.xmax, rect.ymax);
+		glDisable(GL_BLEND);
 	}
 	/* draw selection */
 	if (tile->flag & LAYERTILE_SELECTED) {
@@ -137,31 +146,88 @@ static float layer_tile_draw(
 	}
 
 	idx++;
+	BLI_rcti_rctf_copy(&tile->rect, &rect);
 	/* set tile height */
 	tile->tot_height = tile_size_y;
 
 	return tile_size_y;
 }
 
-void layers_tiles_draw(const bContext *C, ARegion *ar)
+struct FloatingTileDrawInfo {
+	LayerTile *tile;
+	int idx;
+	float pos_y;
+};
+
+static void layers_tiles_draw_floating(const bContext *C, struct FloatingTileDrawInfo *floating)
 {
-	SpaceLayers *slayer = CTX_wm_space_layers(C);
+	ARegion *ar = CTX_wm_region(C);
+	uiStyle *style = UI_style_get_dpi();
+
+	BLI_assert(floating->tile->flag & LAYERTILE_FLOATING);
 
+	/* Own block for both draw steps because otherwise buttons from
+	 * fixed tiles are drawn over background of floating ones. */
 	uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+
+	if (floating->tile->litem->draw) {
+		layer_tile_draw(floating->tile, C, ar, block, style, floating->pos_y, floating->idx);
+	}
+
+	UI_block_end(C, block);
+	UI_block_draw(C, block);
+}
+
+static void layers_tiles_draw_fixed(
+        const bContext *C,
+        float *r_ofs_y, int *r_idx,
+        struct FloatingTileDrawInfo *r_floating)
+{
+	SpaceLayers *slayer = CTX_wm_space_layers(C);
+	ARegion *ar = CTX_wm_region(C);
 	uiStyle *style = UI_style_get_dpi();
 
-	/* draw tiles */
-	int idx = 0;
-	float ofs_y = 0.0f;
+	/* Own block for both draw steps because otherwise buttons from
+	 * fixed tiles are drawn over background of floating ones. */
+	uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+
 	BKE_LAYERTREE_ITER_START(slayer->act_tree, 0, i, litem)
 	{
+		LayerTile *tile = BLI_ghash_lookup(slayer->tiles, litem);
+		BLI_assert(tile->litem == litem);
+
+		/* skip floating buts but return some info for drawing them later */
+		if (tile->flag & LAYERTILE_FLOATING) {
+			BLI_assert(r_floating->tile == NULL); /* only one floating tile allowed */
+			r_floating->tile = tile;
+			r_floating->idx = *r_idx;
+			r_floating->pos_y = *r_ofs_y;
+			/* use tot_height from last draw, we can assume it hasn't changed */
+			*r_ofs_y += tile->tot_height;
+			(*r_idx)++;
+			continue;
+		}
+
 		if (litem->draw) {
-			ofs_y += layer_tile_draw(litem, C, ar, slayer, block, style, ofs_y, idx);
-			idx++;
+			*r_ofs_y += layer_tile_draw(tile, C, ar, block, style, *r_ofs_y, *r_idx);
+			(*r_idx)++;
 		}
 	}
 	BKE_LAYERTREE_ITER_END;
 
+	UI_block_end(C, block);
+	UI_block_draw(C, block);
+}
+
+void layers_tiles_draw(const bContext *C, ARegion *ar)
+{
+	struct FloatingTileDrawInfo floating = {NULL};
+	float ofs_y = 0.0f;
+	int idx = 0;
+
+	/* draw fixed (not floating) tiles first */
+	layers_tiles_draw_fixed(C, &ofs_y, &idx, &floating);
+
 	/* fill remaining space with empty boxes */
 	const float tot_fill_tiles = (-ar->v2d.cur.ymin - ofs_y) / LAYERTILE_HEADER_HEIGHT + 1;
 	for (int i = 0; i < tot_fill_tiles; i++) {
@@ -172,8 +238,10 @@ void layers_tiles_draw(const bContext *C, ARegion *ar)
 		}
 	}
 
-	UI_block_end(C, block);
-	UI_block_draw(C, block);
+	/* draw floating tile last */
+	if (floating.tile) {
+		layers_tiles_draw_floating(C, &floating);
+	}
 
 	/* update size of tot-rect (extents of data/viewable area) */
 	UI_view2d_totRect_set(&ar->v2d, ar->winx - BLI_rcti_size_x(&ar->v2d.vert), ofs_y);
diff --git a/source/blender/editors/space_layers/layers_intern.h b/source/blender/editors/space_layers/layers_intern.h
index dc5d029..d4e8f1f 100644
--- a/source/blender/editors/space_layers/layers_intern.h
+++ b/source/blender/editors/space_layers/layers_intern.h
@@ -35,6 +35,9 @@ typedef enum eLayerTileFlag {
 	LAYERTILE_SELECTED = (1 << 0),
 	LAYERTILE_RENAME   = (1 << 1),
 	LAYERTILE_EXPANDED = (1 << 2),
+	/* Draw the tile as if it was floating above others (for drag and drop).
+	 * Note: Currently only one floating tile at a time allowed. */
+	LAYERTILE_FLOATING = (1 << 3),
 } eLayerTileFlag;
 
 /**
@@ -48,6 +51,10 @@ typedef struct LayerTile {
 	/* The height of this item. Set right after drawing,
 	 * so should always reflect what's on the screen */
 	int tot_height;
+	struct rcti rect;
+
+	/* Offset applied for drawing, used for drag and drop preview */
+	int ofs[2];
 } LayerTile;
 
 /* layers_draw.c */
diff --git a/source/blender/editors/space_layers/layers_ops.c b/source/blender/editors/space_layers/layers_ops.c
index d5ba3d6..8bbbd09 100644
--- a/source/blender/editors/space_layers/layers_ops.c
+++ b/source/blender/editors/space_layers/layers_ops.c
@@ -34,12 +34,15 @@
 #include "BLI_utildefines.h"
 #include "BLI_ghash.h"
 #include "BLI_listbase.h"
+#include "BLI_rect.h"
 
 #include "DNA_windowmanager_types.h"
 
 #include "ED_object.h"
 #include "ED_screen.h"
 
+#include "MEM_guardedalloc.h"
+
 #include "RNA_access.h"
 #include "RNA_define.h"
 
@@ -49,6 +52,36 @@
 #include "layers_intern.h" /* own include */
 
 
+/**
+ * LayerTile wrapper for additional information needed for
+ * offsetting and animating tiles during drag & drop reordering.
+ */
+typedef struct {
+	LayerTile *tile;
+	/* With this we can substract the added offset when done. If we simply
+	 * set it to 0 LayerTile.ofs can't be reliably used elsewhere. */
+	int ofs_added;
+} LayerDragTile;
+
+/**
+ * Data for layer tile drag and drop reordering.
+ */
+typedef struct {
+	LayerDragTile dragged; /* info for the tile that's being dragged */
+	/* LayerDragTile hash table for all items that need special info while dragging */
+	GHash *tiledrags;
+	int insert_idx;
+	int init_mval_y;
+} LayerDragData;
+
+enum {
+	LAYERDRAG_CANCEL = 1,
+	LAYERDRAG_CONFIRM,
+};
+
+/* -------------------------------------------------------------------- */
+
+
 static int layer_add_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
 {
 	SpaceLayers *slayer = CTX_wm_space_layers(C);
@@ -227,6 +260,160 @@ static void LAYERS_OT_group_add(wmOperatorType *ot)
 	

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list