[Bf-blender-cvs] [8e303aae255] blender2.8: Support drag & drop of collections across multiple hierarchy levels
Julian Eisel
noreply at git.blender.org
Fri Mar 10 15:24:59 CET 2017
Commit: 8e303aae255be2ef45d5818af046de7c22312aa4
Author: Julian Eisel
Date: Fri Mar 10 15:03:06 2017 +0100
Branches: blender2.8
https://developer.blender.org/rB8e303aae255be2ef45d5818af046de7c22312aa4
Support drag & drop of collections across multiple hierarchy levels
Two issues are remaining, they'll be fixed separately:
* Graphical feedback when dragging within the master collection is wrong
* There's some bug where collections swap places instead, Dalai will investigate
===================================================================
M source/blender/editors/space_outliner/outliner_draw.c
M source/blender/editors/space_outliner/outliner_intern.h
M source/blender/editors/space_outliner/outliner_ops.c
M source/blender/editors/space_outliner/outliner_tree.c
===================================================================
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 0ba60b21aa7..0b119b5d247 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1520,34 +1520,14 @@ static void outliner_draw_tree_element(
}
}
-/**
- * Count how many visible childs (and open grandchilds, great-grandchilds, ...) \a te has.
- */
-static int outliner_count_visible_childs(const SpaceOops *soops, const TreeElement *te)
-{
- TreeStoreElem *tselem = TREESTORE(te);
- int current_count = 0;
-
- if (TSELEM_OPEN(tselem, soops)) {
- for (TreeElement *te_child = te->subtree.first; te_child; te_child = te_child->next) {
- current_count += outliner_count_visible_childs(soops, te_child);
- current_count++;
- }
- }
-
- return current_count;
-}
-
-static void outliner_draw_tree_element_floating(const SpaceOops *soops, const ARegion *ar,
- const TreeElement *te_floating)
+static void outliner_draw_tree_element_floating(
+ const ARegion *ar, const TreeElement *te_floating)
{
const TreeElement *te_insert = te_floating->drag_data->insert_handle;
- const ListBase *lb_parent = te_floating->parent ? &te_floating->parent->subtree : &soops->tree;
- const TreeElement *te_insert_fallback = te_insert ? te_insert : lb_parent->first;
const int line_width = 2;
unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
- int coord_y = (te_insert ? te_insert->ys : (te_insert_fallback->ys + UI_UNIT_Y)) - (int)(line_width * 0.5f);
+ int coord_y = te_insert->ys;
unsigned char col[4];
if (te_insert == te_floating) {
@@ -1555,15 +1535,14 @@ static void outliner_draw_tree_element_floating(const SpaceOops *soops, const AR
return;
}
- if (te_insert) {
- coord_y -= UI_UNIT_Y * outliner_count_visible_childs(soops, te_insert);
- }
-
UI_GetThemeColorShade4ubv(TH_BACK, -40, col);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
glEnable(GL_BLEND);
- if (!te_insert || (te_floating->drag_data->insert_type == TE_INSERT_AFTER)) {
+ if (ELEM(te_floating->drag_data->insert_type, TE_INSERT_BEFORE, TE_INSERT_AFTER)) {
+ if (te_floating->drag_data->insert_type == TE_INSERT_BEFORE) {
+ coord_y += UI_UNIT_Y;
+ }
immUniformColor4ubv(col);
glLineWidth(line_width);
@@ -1793,7 +1772,7 @@ static void outliner_draw_tree(
startx, &starty, te_edit, &te_floating);
}
if (te_floating) {
- outliner_draw_tree_element_floating(soops, ar, te_floating);
+ outliner_draw_tree_element_floating(ar, te_floating);
}
if (has_restrict_icons) {
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 4cee0e44fca..cad34c96db4 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -50,7 +50,7 @@ struct wmKeyConfig;
typedef enum TreeElementInsertType {
- /* no INSERT_BEFORE needed for now */
+ TE_INSERT_BEFORE,
TE_INSERT_AFTER,
TE_INSERT_INTO,
} TreeElementInsertType;
@@ -91,7 +91,7 @@ typedef struct TreeElement {
struct {
TreeElementInsertType insert_type;
- /* the element after which we may insert the dragged one (NULL to insert at top) */
+ /* the element before/after/into which we may insert the dragged one (NULL to insert at top) */
struct TreeElement *insert_handle;
} *drag_data;
} TreeElement;
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 3db0b6ffa08..6fc088e0f48 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -52,11 +52,6 @@ enum {
OUTLINER_ITEM_DRAG_CONFIRM,
};
-typedef struct OutlinerItemDrag {
- TreeElement *dragged_te;
- int init_mouse_xy[2];
-} OutlinerItemDrag;
-
static int outliner_item_drag_drop_poll(bContext *C)
{
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -67,70 +62,69 @@ static int outliner_item_drag_drop_poll(bContext *C)
static TreeElement *outliner_item_drag_element_find(SpaceOops *soops, ARegion *ar, const wmEvent *event)
{
+ /* note: using EVT_TWEAK_ events to trigger dragging is fine,
+ * it sends coordinates from where dragging was started */
const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]);
return outliner_find_item_at_y(soops, &soops->tree, my);
}
-static OutlinerItemDrag *outliner_item_drag_data_create(TreeElement *dragged_te, const int mouse_xy[2])
-{
- OutlinerItemDrag *drag_data = MEM_mallocN(sizeof(*drag_data), __func__);
-
- drag_data->dragged_te = dragged_te;
- copy_v2_v2_int(drag_data->init_mouse_xy, mouse_xy);
-
- return drag_data;
-}
-
-static void outliner_item_drag_end(OutlinerItemDrag *op_drag_data)
+static void outliner_item_drag_end(TreeElement *dragged_te)
{
- MEM_SAFE_FREE(op_drag_data->dragged_te->drag_data);
- MEM_freeN(op_drag_data);
+ MEM_SAFE_FREE(dragged_te->drag_data);
}
-static void outliner_item_drag_handle(ARegion *ar, const wmEvent *event, OutlinerItemDrag *op_drag_data)
+static void outliner_item_drag_handle(
+ SpaceOops *soops, ARegion *ar, const wmEvent *event, TreeElement *te_dragged)
{
- TreeElement *dragged_te = op_drag_data->dragged_te;
- const int delta_mouse_y = event->y - op_drag_data->init_mouse_xy[1];
- const int cmp_coord = (int)UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]);
- const float margin = UI_UNIT_Y * (1.0f / 3);
-
- /* by default we don't change the item position */
- dragged_te->drag_data->insert_handle = dragged_te;
-
- if (delta_mouse_y > 0) {
- for (TreeElement *te = dragged_te->prev; te && (cmp_coord >= (te->ys + margin)); te = te->prev) {
- if (cmp_coord > (te->ys + (2 * margin))) {
- dragged_te->drag_data->insert_type = TE_INSERT_AFTER;
- /* will be NULL if we want to insert as first element */
- dragged_te->drag_data->insert_handle = te->prev;
+ TreeStoreElem *tselem_dragged = TREESTORE(te_dragged);
+ TreeElement *insert_handle;
+ float view_mval[2];
+
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+ insert_handle = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
+
+ te_dragged->drag_data->insert_handle = NULL;
+ if (insert_handle) {
+ TreeStoreElem *tselem_handle = TREESTORE(insert_handle);
+ if (tselem_handle->type == tselem_dragged->type) {
+ const float margin = UI_UNIT_Y * (1.0f / 4);
+
+ te_dragged->drag_data->insert_handle = insert_handle;
+ if (view_mval[1] < (insert_handle->ys + margin)) {
+ te_dragged->drag_data->insert_type = TE_INSERT_AFTER;
+ }
+ else if (view_mval[1] > (insert_handle->ys + (2 * margin))) {
+ te_dragged->drag_data->insert_type = TE_INSERT_BEFORE;
}
else {
- dragged_te->drag_data->insert_type = TE_INSERT_INTO;
- dragged_te->drag_data->insert_handle = te;
+ te_dragged->drag_data->insert_type = TE_INSERT_INTO;
}
}
}
else {
- for (TreeElement *te = dragged_te->next; te && (cmp_coord <= (te->ys + UI_UNIT_Y - margin)); te = te->next) {
- if (cmp_coord < (te->ys + margin)) {
- dragged_te->drag_data->insert_type = TE_INSERT_AFTER;
- dragged_te->drag_data->insert_handle = te;
- BLI_assert(te->prev != NULL);
- }
- else {
- dragged_te->drag_data->insert_type = TE_INSERT_INTO;
- dragged_te->drag_data->insert_handle = te;
- }
+ TreeElement *first = soops->tree.first;
+ TreeElement *last = soops->tree.last;
+
+ /* mouse doesn't hover any item (ignoring x axis), so it's either above list bounds or below. */
+ if (view_mval[1] < last->ys) {
+ te_dragged->drag_data->insert_handle = last;
+ te_dragged->drag_data->insert_type = TE_INSERT_AFTER;
+ }
+ else if (view_mval[1] > (first->ys + UI_UNIT_Y)) {
+ te_dragged->drag_data->insert_handle = first;
+ te_dragged->drag_data->insert_type = TE_INSERT_BEFORE;
+ }
+ else {
+ BLI_assert(0);
}
}
}
-static bool outliner_item_drag_drop_apply(const Scene *scene, OutlinerItemDrag *op_drag_data)
+static bool outliner_item_drag_drop_apply(const Scene *scene, TreeElement *dragged_te)
{
- TreeElement *dragged_te = op_drag_data->dragged_te;
- TreeElement *insert_after = dragged_te->drag_data->insert_handle;
+ TreeElement *insert_handle = dragged_te->drag_data->insert_handle;
- if (insert_after == dragged_te) {
+ if (insert_handle == dragged_te) {
/* No need to do anything */
return false;
}
@@ -138,8 +132,8 @@ static bool outliner_item_drag_drop_apply(const Scene *scene, OutlinerItemDrag *
if (dragged_te->reinsert) {
/* Not sure yet what the best way to handle reordering elements of different types
* (and stored in different lists). For collection display mode this is enough. */
- if (!insert_after || (insert_after->reinsert == dragged_te->reinsert)) {
- dragged_te->reinsert(scene, dragged_te, insert_after, dragged_te->drag_data->insert_type);
+ if (!insert_handle || (insert_handle->reinsert == dragged_te->reinsert)) {
+ dragged_te->reinsert(scene, dragged_te, insert_handle, dragged_te->drag_data->insert_type);
}
}
@@ -150,7 +144,7 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
{
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
- OutlinerItemDrag *op_drag_data = op->customdata;
+ TreeElement *te_dragged = op->customdata;
int retval = OPERATOR_RUNNING_MODAL;
bool redraw = false;
bool skip_rebuild = true;
@@ -158,7 +152,7 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
switch (event->type) {
case EVT_MODAL_MAP:
if (event->val == OUTLINER_ITEM_DRAG_CONFIRM) {
- outliner_item_drag_drop_apply(CTX_data_scene(C), op_drag_data);
+ outliner_item_drag_drop_apply(CTX_data_scene(C), te_dragged);
skip_rebuild = false;
retval = OPERATOR_FINISHED;
}
@@ -169,11 +163,11 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
BLI_assert(0);
}
WM_event_add_mousemove(C); /* update highlight */
- outliner_item_drag_end(op_drag_data);
+ outliner_it
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list