From 0322700d875a1d518a730512531a881f1278124b Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Thu, 2 Mar 2017 17:11:09 +0100 Subject: Get UI ready for using drag & drop to nest a collection into another one Nothing happen yet when it's supposed to insert the collection into another one, that part will be handled by @dfelinto. See gif for demo of how it works UI wise: {F500337} Also fixed off-by-one error in utility function. --- source/blender/blenkernel/BKE_layer.h | 1 + source/blender/blenkernel/intern/layer.c | 11 +++++++ .../blender/editors/space_outliner/outliner_draw.c | 30 +++++++++++++---- .../editors/space_outliner/outliner_intern.h | 11 +++++-- .../blender/editors/space_outliner/outliner_ops.c | 38 +++++++++++++++------- .../blender/editors/space_outliner/outliner_tree.c | 12 +++++-- .../editors/space_outliner/outliner_utils.c | 2 +- 7 files changed, 81 insertions(+), 24 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index 863f33dea8d..aa1d537a28e 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -86,6 +86,7 @@ int BKE_layer_collection_count(struct SceneLayer *sl); int BKE_layer_collection_findindex(struct SceneLayer *sl, struct LayerCollection *lc); void BKE_layer_collection_reinsert_after(const struct Scene *scene, struct SceneLayer *sl, struct LayerCollection *lc_reinsert, struct LayerCollection *lc_after); +void BKE_layer_collection_reinsert_into(struct LayerCollection *lc_reinsert, struct LayerCollection *lc_into); struct LayerCollection *BKE_collection_link(struct SceneLayer *sl, struct SceneCollection *sc); diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index 605705c483a..77501c4acce 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -536,6 +536,10 @@ static ListBase *scene_collection_listbase_find(ListBase *lb, SceneCollection *s void BKE_layer_collection_reinsert_after( const Scene *scene, SceneLayer *sl, LayerCollection *lc_reinsert, LayerCollection *lc_after) { + /* TODO this function probably needs to be rewritten completely to support all cases + * (reinserting master collection, reinsert into different hierarchy levels, etc) */ + TODO_LAYER_OPERATORS; + SceneCollection *sc_master = BKE_collection_master(scene); SceneCollection *sc_reinsert = lc_reinsert->scene_collection; ListBase *lc_reinsert_lb = layer_collection_listbase_find(&sl->layer_collections, lc_reinsert); @@ -564,6 +568,13 @@ void BKE_layer_collection_reinsert_after( BKE_scene_layer_engine_settings_collection_recalculate(sl, lc_reinsert); } +void BKE_layer_collection_reinsert_into(LayerCollection *lc_reinsert, LayerCollection *lc_into) +{ + /* TODO this is missing */ + TODO_LAYER_OPERATORS; + UNUSED_VARS(lc_reinsert, lc_into); +} + /** * Link a collection to a renderlayer * The collection needs to be created separately diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 990ad296bb9..816740b8769 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1540,7 +1540,7 @@ static int outliner_count_visible_childs(const SpaceOops *soops, const TreeEleme static void outliner_draw_tree_element_floating(const SpaceOops *soops, const ARegion *ar, const TreeElement *te_floating) { - const TreeElement *te_insert = te_floating->drag_data->insert_te; + 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; @@ -1560,14 +1560,30 @@ static void outliner_draw_tree_element_floating(const SpaceOops *soops, const AR UI_GetThemeColorShade4ubv(TH_BACK, -40, col); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformColor4ubv(col); - glLineWidth(line_width); + glEnable(GL_BLEND); + + if (!te_insert || (te_floating->drag_data->insert_type == TE_INSERT_AFTER)) { + immUniformColor4ubv(col); + glLineWidth(line_width); - immBegin(PRIM_LINE_STRIP, 2); - immVertex2f(pos, 0, coord_y); - immVertex2f(pos, ar->v2d.cur.xmax, coord_y); - immEnd(); + immBegin(PRIM_LINE_STRIP, 2); + immVertex2f(pos, 0, coord_y); + immVertex2f(pos, ar->v2d.cur.xmax, coord_y); + immEnd(); + } + else { + BLI_assert(te_floating->drag_data->insert_type == TE_INSERT_INTO); + immUniformColor4ub(UNPACK3(col), col[3] * 0.5f); + + immBegin(PRIM_QUADS, 4); + immVertex2f(pos, 0, coord_y); + immVertex2f(pos, 0, coord_y + UI_UNIT_Y); + immVertex2f(pos, ar->v2d.cur.xmax, coord_y + UI_UNIT_Y); + immVertex2f(pos, ar->v2d.cur.xmax, coord_y); + immEnd(); + } + glDisable(GL_BLEND); immUnbindProgram(); } diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 731b5041bd9..4cee0e44fca 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -49,6 +49,12 @@ struct EditBone; struct wmKeyConfig; +typedef enum TreeElementInsertType { + /* no INSERT_BEFORE needed for now */ + TE_INSERT_AFTER, + TE_INSERT_INTO, +} TreeElementInsertType; + typedef enum TreeTraversalAction { /* Continue traversal regularly, don't skip children. */ TRAVERSE_CONTINUE = 0, @@ -63,7 +69,7 @@ typedef enum TreeTraversalAction { * Passing scene right now, may be better to allow some custom data. */ typedef void (*TreeElementReinsertFunc)(const struct Scene *scene, struct TreeElement *insert_element, - struct TreeElement *insert_after); + struct TreeElement *insert_handle, TreeElementInsertType action); typedef TreeTraversalAction (*TreeTraversalFunc)(struct TreeElement *te, void *customdata); @@ -84,8 +90,9 @@ typedef struct TreeElement { TreeElementReinsertFunc reinsert; struct { + TreeElementInsertType insert_type; /* the element after which we may insert the dragged one (NULL to insert at top) */ - struct TreeElement *insert_te; + 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 5187cc66f58..3db0b6ffa08 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -87,24 +87,40 @@ static void outliner_item_drag_end(OutlinerItemDrag *op_drag_data) MEM_freeN(op_drag_data); } -static void outliner_item_drag_handle(OutlinerItemDrag *op_drag_data, ARegion *ar, const wmEvent *event) +static void outliner_item_drag_handle(ARegion *ar, const wmEvent *event, OutlinerItemDrag *op_drag_data) { 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_te = dragged_te; + dragged_te->drag_data->insert_handle = dragged_te; if (delta_mouse_y > 0) { - for (TreeElement *te = dragged_te->prev; te && (cmp_coord >= (te->ys + (UI_UNIT_Y * 0.5f))); te = te->prev) { - /* will be NULL if we want to insert as first element */ - dragged_te->drag_data->insert_te = te->prev; + 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; + } + else { + dragged_te->drag_data->insert_type = TE_INSERT_INTO; + dragged_te->drag_data->insert_handle = te; + } } } else { - for (TreeElement *te = dragged_te->next; te && (cmp_coord <= (te->ys + (UI_UNIT_Y * 0.5f))); te = te->next) { - dragged_te->drag_data->insert_te = te; + 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; + } } } } @@ -112,7 +128,7 @@ static void outliner_item_drag_handle(OutlinerItemDrag *op_drag_data, ARegion *a static bool outliner_item_drag_drop_apply(const Scene *scene, OutlinerItemDrag *op_drag_data) { TreeElement *dragged_te = op_drag_data->dragged_te; - TreeElement *insert_after = dragged_te->drag_data->insert_te; + TreeElement *insert_after = dragged_te->drag_data->insert_handle; if (insert_after == dragged_te) { /* No need to do anything */ @@ -123,7 +139,7 @@ static bool outliner_item_drag_drop_apply(const Scene *scene, OutlinerItemDrag * /* 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->reinsert(scene, dragged_te, insert_after, dragged_te->drag_data->insert_type); } } @@ -157,7 +173,7 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv redraw = true; break; case MOUSEMOVE: - outliner_item_drag_handle(op_drag_data, ar, event); + outliner_item_drag_handle(ar, event, op_drag_data); redraw = true; break; } @@ -186,7 +202,7 @@ static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *op, const wmE op->customdata = outliner_item_drag_data_create(te, &event->x); te->drag_data = MEM_callocN(sizeof(*te->drag_data), __func__); /* by default we don't change the item position */ - te->drag_data->insert_te = te; + te->drag_data->insert_handle = te; /* unset highlighted tree element, dragged one will be highlighted instead */ outliner_set_flag(&soops->tree, TSE_HIGHLIGHTED, false); diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 8a024e0cc82..0cf76a671a4 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -1287,13 +1287,19 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops) } } -static void outliner_collections_reorder(const Scene *scene, TreeElement *insert_element, TreeElement *insert_after) +static void outliner_collections_reorder(const Scene *scene, TreeElement *insert_element, TreeElement *insert_handle, + TreeElementInsertType action) { SceneLayer *sl = BKE_scene_layer_render_active(scene); LayerCollection *insert_coll = insert_element->directdata; - LayerCollection *insert_after_coll = insert_after ? insert_after->directdata : NULL; + LayerCollection *insert_handle_coll = insert_handle ? insert_handle->directdata : NULL; - BKE_layer_collection_reinsert_after(scene, sl, insert_coll, insert_after_coll); + if (action == TE_INSERT_AFTER) { + BKE_layer_collection_reinsert_after(scene, sl, insert_coll, insert_handle_coll); + } + else if (action == TE_INSERT_INTO) { + BKE_layer_collection_reinsert_into(insert_coll, insert_handle_coll); + } } static void outliner_add_layer_collections_recursive(SpaceOops *soops, ListBase *tree, Scene *scene, diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c index 0e3a4e89fdf..f123b240efc 100644 --- a/source/blender/editors/space_outliner/outliner_utils.c +++ b/source/blender/editors/space_outliner/outliner_utils.c @@ -49,7 +49,7 @@ TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tre { for (TreeElement *te_iter = tree->first; te_iter; te_iter = te_iter->next) { if (view_co_y < (te_iter->ys + UI_UNIT_Y)) { - if (view_co_y > te_iter->ys) { + if (view_co_y >= te_iter->ys) { /* co_y is inside this element */ return te_iter; } -- cgit v1.2.3