Commit: 79dabc537e3e345c3e536a6369b1d130942155c3 Author: Campbell Barton Date: Fri Jul 6 14:41:14 2018 +0200 Branches: blender2.8 https://developer.blender.org/rB79dabc537e3e345c3e536a6369b1d130942155c3
Merge branch 'master' into blender2.8 =================================================================== =================================================================== diff --cc source/blender/editors/space_outliner/outliner_edit.c index 1c78931b449,3708b653ec4..d8a5ba533c4 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@@ -150,45 -147,8 +150,45 @@@ TreeElement *outliner_dropzone_find(con return NULL; } + /* ************************************************************** */ -/* Click Activated */ + +/* Highlight --------------------------------------------------- */ + +static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + SpaceOops *soops = CTX_wm_space_outliner(C); + const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]); + + TreeElement *hovered_te = outliner_find_item_at_y(soops, &soops->tree, my); + bool changed = false; + + if (!hovered_te || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED)) { - changed = outliner_set_flag(&soops->tree, TSE_HIGHLIGHTED, false); ++ changed = outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED, false); + if (hovered_te) { + hovered_te->store_elem->flag |= TSE_HIGHLIGHTED; + changed = true; + } + } + + if (changed) { + ED_region_tag_redraw_no_rebuild(ar); + } + + return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH); +} + +void OUTLINER_OT_highlight_update(wmOperatorType *ot) +{ + ot->name = "Update Highlight"; + ot->idname = "OUTLINER_OT_highlight_update"; + ot->description = "Update the item highlight based on the current mouse position"; + + ot->invoke = outliner_highlight_update; + + ot->poll = ED_operator_outliner_active; +} /* Toggle Open/Closed ------------------------------------------- */ @@@ -850,11 -743,7 +850,11 @@@ int outliner_flag_is_any_test(ListBase return 0; } -void outliner_flag_set(ListBase *lb, short flag, short set) +/** + * Set or unset \a flag for all outliner elements in \a lb and sub-trees. + * \return if any flag was modified. + */ - bool outliner_set_flag(ListBase *lb, short flag, short set) ++bool outliner_flag_set(ListBase *lb, short flag, short set) { TreeElement *te; TreeStoreElem *tselem; @@@ -863,21 -750,10 +863,21 @@@ for (te = lb->first; te; te = te->next) { tselem = TREESTORE(te); - if (set == 0) tselem->flag &= ~flag; - else tselem->flag |= flag; - outliner_flag_set(&te->subtree, flag, set); + has_flag = (tselem->flag & flag); + if (set == 0) { + if (has_flag) { + tselem->flag &= ~flag; + changed = true; + } + } + else if (!has_flag) { + tselem->flag |= flag; + changed = true; + } - changed |= outliner_set_flag(&te->subtree, flag, set); ++ changed |= outliner_flag_set(&te->subtree, flag, set); } + + return changed; } /* Restriction Columns ------------------------------- */ @@@ -946,14 -997,15 +946,14 @@@ static int outliner_toggle_selected_exe ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); - if (outliner_has_one_flag(&soops->tree, TSE_SELECTED, 1)) - outliner_set_flag(&soops->tree, TSE_SELECTED, 0); + if (outliner_flag_is_any_test(&soops->tree, TSE_SELECTED, 1)) + outliner_flag_set(&soops->tree, TSE_SELECTED, 0); else - outliner_set_flag(&soops->tree, TSE_SELECTED, 1); + outliner_flag_set(&soops->tree, TSE_SELECTED, 1); - soops->storeflag |= SO_TREESTORE_REDRAW; - + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - ED_region_tag_redraw(ar); + ED_region_tag_redraw_no_rebuild(ar); return OPERATOR_FINISHED; } diff --cc source/blender/editors/space_outliner/outliner_intern.h index 0ab22208841,49647a0d838..0763933b102 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@@ -245,8 -172,8 +245,8 @@@ void outliner_do_object_operation int common_restrict_check(struct bContext *C, struct Object *ob); - int outliner_has_one_flag(ListBase *lb, short flag, const int curlevel); - bool outliner_set_flag(ListBase *lb, short flag, short set); + int outliner_flag_is_any_test(ListBase *lb, short flag, const int curlevel); -void outliner_flag_set(ListBase *lb, short flag, short set); ++bool outliner_flag_set(ListBase *lb, short flag, short set); void object_toggle_visibility_cb( struct bContext *C, struct ReportList *reports, struct Scene *scene, diff --cc source/blender/editors/space_outliner/outliner_ops.c index b061e8537c2,9574e82505f..760e2853038 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@@ -51,356 -36,8 +51,356 @@@ #include "WM_api.h" #include "WM_types.h" +#include "ED_screen.h" + #include "outliner_intern.h" +typedef struct OutlinerDragDropTooltip { + TreeElement *te; + void *handle; +} OutlinerDragDropTooltip; + +enum { + OUTLINER_ITEM_DRAG_CANCEL, + OUTLINER_ITEM_DRAG_CONFIRM, +}; + +static bool outliner_item_drag_drop_poll(bContext *C) +{ + SpaceOops *soops = CTX_wm_space_outliner(C); + return ED_operator_outliner_active(C) && + /* Only collection display modes supported for now. Others need more design work */ + ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_LIBRARIES); +} + +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 void outliner_item_drag_end(wmWindow *win, OutlinerDragDropTooltip *data) +{ + MEM_SAFE_FREE(data->te->drag_data); + + if (data->handle) { + WM_draw_cb_exit(win, data->handle); + } + + MEM_SAFE_FREE(data); +} + +static void outliner_item_drag_get_insert_data( + const SpaceOops *soops, ARegion *ar, const wmEvent *event, TreeElement *te_dragged, + TreeElement **r_te_insert_handle, TreeElementInsertType *r_insert_type) +{ + TreeElement *te_hovered; + float view_mval[2]; + + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]); + te_hovered = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]); + + if (te_hovered) { + /* mouse hovers an element (ignoring x-axis), now find out how to insert the dragged item exactly */ + + if (te_hovered == te_dragged) { + *r_te_insert_handle = te_dragged; + } + else if (te_hovered != te_dragged) { + const float margin = UI_UNIT_Y * (1.0f / 4); + + *r_te_insert_handle = te_hovered; + if (view_mval[1] < (te_hovered->ys + margin)) { + if (TSELEM_OPEN(TREESTORE(te_hovered), soops)) { + /* inserting after a open item means we insert into it, but as first child */ + if (BLI_listbase_is_empty(&te_hovered->subtree)) { + *r_insert_type = TE_INSERT_INTO; + } + else { + *r_insert_type = TE_INSERT_BEFORE; + *r_te_insert_handle = te_hovered->subtree.first; + } + } + else { + *r_insert_type = TE_INSERT_AFTER; + } + } + else if (view_mval[1] > (te_hovered->ys + (3 * margin))) { + *r_insert_type = TE_INSERT_BEFORE; + } + else { + *r_insert_type = TE_INSERT_INTO; + } + } + } + else { + /* mouse doesn't hover any item (ignoring x-axis), so it's either above list bounds or below. */ + + TreeElement *first = soops->tree.first; + TreeElement *last = soops->tree.last; + + if (view_mval[1] < last->ys) { + *r_te_insert_handle = last; + *r_insert_type = TE_INSERT_AFTER; + } + else if (view_mval[1] > (first->ys + UI_UNIT_Y)) { + *r_te_insert_handle = first; + *r_insert_type = TE_INSERT_BEFORE; + } + else { + BLI_assert(0); + } + } +} + +static void outliner_item_drag_handle( + SpaceOops *soops, ARegion *ar, const wmEvent *event, TreeElement *te_dragged) +{ + TreeElement *te_insert_handle; + TreeElementInsertType insert_type; + + outliner_item_drag_get_insert_data(soops, ar, event, te_dragged, &te_insert_handle, &insert_type); + + if (!te_dragged->reinsert_poll && + /* there is no reinsert_poll, so we do some generic checks (same types and reinsert callback is available) */ + (TREESTORE(te_dragged)->type == TREESTORE(te_insert_handle)->type) && + te_dragged->reinsert) + { + /* pass */ + } + else if (te_dragged == te_insert_handle) { + /* nothing will happen anyway, no need to do poll check */ + } + else if (!te_dragged->reinsert_poll || + !te_dragged->reinsert_poll(te_dragged, &te_insert_handle, &insert_type)) + { + te_insert_handle = NULL; + } + te_dragged->drag_data->insert_type = insert_type; + te_dragged->drag_data->insert_handle = te_insert_handle; +} + +/** + * Returns true if it is a collection and empty. + */ +static bool is_empty_collection(TreeElement *te) +{ + Collection *collection = outliner_collection_from_tree_element(te); + + if (!collection) { + return false; + } + + return BLI_listbase_is_empty(&collection->gobject) && + BLI_listbase_is_empty(&collection->children); +} + +static bool outliner_item_drag_drop_apply( + Main *bmain, + Scene *scene, + SpaceOops *soops, + OutlinerDragDropTooltip *data, + const wmEvent *event) +{ + TreeElement *dragged_te = data->te; + TreeElement *insert_handle = dragged_te->drag_data->insert_handle; + TreeElementInsertType insert_type = dragged_te->drag_data->insert_type; + + if ((insert_handle == dragged_te) || !insert_handle) { + /* No need to do anything */ + } + else if (dragged_te->reinsert) { + BLI_assert(!dragged_te->reinsert_poll || dragged_te->reinsert_poll(dragged_te, &insert_handle, + &insert_type)); + /* call of assert above should not have changed insert_handle and insert_type at this point */ + BLI_assert(dragged_te->drag_data->insert_handle == insert_handle && + dragged_te->drag_data->insert_type == insert_type); + + /* If the collection was @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs