Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_outliner/outliner_select.c
| Context not available. | |||||
| /* **************** Box Select Tool ****************** */ | /* **************** Box Select Tool ****************** */ | ||||
| static void outliner_item_box_select( | static void outliner_item_box_select( | ||||
| SpaceOutliner *soops, Scene *scene, rctf *rectf, TreeElement *te, bool select) | SpaceOutliner *soops, Scene *scene, rctf *rectf, TreeElement *te, bool select, bContext *C, bool *extend, float *initial_y_pos) | ||||
| { | { | ||||
| TreeStoreElem *tselem = TREESTORE(te); | ViewLayer *view_layer = CTX_data_view_layer(C); | ||||
| TreeStoreElem *tselem = TREESTORE(te); | |||||
| if (te->ys <= rectf->ymax && te->ys + UI_UNIT_Y >= rectf->ymin) { | |||||
| if (select) { | if (te->ys <= rectf->ymax && te->ys + UI_UNIT_Y >= rectf->ymin) { | ||||
| tselem->flag |= TSE_SELECTED; | if (select) { | ||||
| } | if (!(tselem->flag & TSE_SELECTED)) { | ||||
| else { | tselem->flag |= TSE_SELECTED; | ||||
| tselem->flag &= ~TSE_SELECTED; | do_outliner_item_activate_tree_element(C, scene, view_layer, soops, te, tselem, extend, true); | ||||
| } | *extend = true; | ||||
| } | } | ||||
| } | |||||
| /* Look at its children. */ | else if (tselem->flag & TSE_SELECTED) { | ||||
| if (TSELEM_OPEN(tselem, soops)) { | do_outliner_item_activate_tree_element(C, scene, view_layer, soops, te, tselem, extend, false); | ||||
| for (te = te->subtree.first; te; te = te->next) { | tselem->flag &= ~TSE_SELECTED; | ||||
| outliner_item_box_select(soops, scene, rectf, te, select); | } | ||||
| } | } | ||||
| } | |||||
| /* Look at its children. */ | |||||
| if (TSELEM_OPEN(tselem, soops)) { | |||||
| if (rectf->ymin < *initial_y_pos) { | |||||
| for (te = te->subtree.first; te; te = te->next) { | |||||
| outliner_item_box_select(soops, scene, rectf, te, select, C, extend, initial_y_pos); | |||||
| } | |||||
| } | |||||
| else { | |||||
| for (te = te->subtree.last; te; te = te->prev) { | |||||
| outliner_item_box_select(soops, scene, rectf, te, select, C, extend, initial_y_pos); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| static int outliner_box_select_exec(bContext *C, wmOperator *op) | static int outliner_box_select_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Scene *scene = CTX_data_scene(C); | ViewLayer *view_layer = CTX_data_view_layer(C); | ||||
| SpaceOutliner *soops = CTX_wm_space_outliner(C); | Scene *scene = CTX_data_scene(C); | ||||
| ARegion *ar = CTX_wm_region(C); | SpaceOutliner *soops = CTX_wm_space_outliner(C); | ||||
| rctf rectf; | ARegion *ar = CTX_wm_region(C); | ||||
| rctf rectf; | |||||
| bool extend = false; | |||||
| const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); | |||||
| const bool select = (sel_op != SEL_OP_SUB); | |||||
| if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | |||||
| outliner_flag_set(&soops->tree, TSE_SELECTED, 0); | |||||
| BKE_view_layer_base_deselect_all(view_layer); | |||||
| if (sel_op == SEL_OP_ADD) { | |||||
| extend = true; | |||||
| } | |||||
| } | |||||
| WM_operator_properties_border_to_rctf(op, &rectf); | |||||
| UI_view2d_region_to_view_rctf(&ar->v2d, &rectf, &rectf); | |||||
| float initial_y_pos = RNA_float_get(op->ptr, "initial_y_pos"); | |||||
| for (TreeElement *te = soops->tree.first; te; te = te->next) { | |||||
| outliner_item_box_select(soops, scene, &rectf, te, select, C, &extend, &initial_y_pos); | |||||
| } | |||||
| DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); | |||||
| WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); | |||||
| ED_region_tag_redraw(ar); | |||||
| return OPERATOR_FINISHED; | |||||
| } | |||||
| const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); | static int is_event_over_item_name_or_icon(TreeElement *te, const float mval[2]) | ||||
| const bool select = (sel_op != SEL_OP_SUB); | { | ||||
| if (SEL_OP_USE_PRE_DESELECT(sel_op)) { | if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) { | ||||
| outliner_flag_set(&soops->tree, TSE_SELECTED, 0); | |||||
| } | /* click and drage on icon or name of an item */ | ||||
| if (mval[0] > te->xs + UI_UNIT_X * 1 && mval[0] < te->xend) { | |||||
| return 1; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| for (te = te->subtree.first; te; te = te->next) { | |||||
| if (is_event_over_item_name_or_icon(te, mval)) { | |||||
| return 1; | |||||
| } | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| WM_operator_properties_border_to_rctf(op, &rectf); | static int outliner_box_invoke(bContext *C, wmOperator *op, const wmEvent *event) | ||||
| UI_view2d_region_to_view_rctf(&ar->v2d, &rectf, &rectf); | { | ||||
| ARegion *ar = CTX_wm_region(C); | |||||
| SpaceOutliner *soops = CTX_wm_space_outliner(C); | |||||
| TreeElement *te; | |||||
| float fmval[2]; | |||||
| for (TreeElement *te = soops->tree.first; te; te = te->next) { | UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); | ||||
| outliner_item_box_select(soops, scene, &rectf, te, select); | RNA_float_set(op->ptr, "initial_y_pos", fmval[1]); | ||||
| } | |||||
| DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); | const bool wait_for_input = !ISTWEAK(event->type) && RNA_boolean_get(op->ptr, "wait_for_input"); // for checking B / Mouse Drag | ||||
| WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); | const bool tweak = RNA_boolean_get(op->ptr, "tweak"); | ||||
| ED_region_tag_redraw(ar); | |||||
| return OPERATOR_FINISHED; | for (te = soops->tree.first; te; te = te->next) { | ||||
| if (!wait_for_input && tweak && is_event_over_item_name_or_icon(te, fmval)) { | |||||
| return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; | |||||
| } | |||||
| } | |||||
| return WM_gesture_box_invoke(C, op, event); | |||||
| } | } | ||||
| void OUTLINER_OT_select_box(wmOperatorType *ot) | void OUTLINER_OT_select_box(wmOperatorType *ot) | ||||
| { | { | ||||
| /* identifiers */ | /* identifiers */ | ||||
| ot->name = "Box Select"; | ot->name = "Box Select"; | ||||
| ot->idname = "OUTLINER_OT_select_box"; | ot->idname = "OUTLINER_OT_select_box"; | ||||
| ot->description = "Use box selection to select tree elements"; | ot->description = "Use box selection to select tree elements"; | ||||
| /* api callbacks */ | /* api callbacks */ | ||||
| ot->invoke = WM_gesture_box_invoke; | ot->invoke = outliner_box_invoke; | ||||
| ot->exec = outliner_box_select_exec; | ot->exec = outliner_box_select_exec; | ||||
| ot->modal = WM_gesture_box_modal; | ot->modal = WM_gesture_box_modal; | ||||
| ot->cancel = WM_gesture_box_cancel; | ot->cancel = WM_gesture_box_cancel; | ||||
| ot->poll = ED_operator_outliner_active; | ot->poll = ED_operator_outliner_active; | ||||
| /* flags */ | |||||
| ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | |||||
| /* properties */ | |||||
| PropertyRNA *prop; | |||||
| prop = RNA_def_float(ot->srna, "initial_y_pos" , 0, MINAFRAME, MAXFRAME, "Initial Y Position", "", MINAFRAME, MAXFRAME); | |||||
| RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); | |||||
| /* flags */ | prop = RNA_def_boolean(ot->srna, "tweak", 0, "Tweak", "Only activate when mouse is not over an item's icon or name - useful for tweak gesture"); | ||||
| ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | RNA_def_property_flag(prop, PROP_SKIP_SAVE); | ||||
| /* properties */ | WM_operator_properties_gesture_box(ot); | ||||
| WM_operator_properties_gesture_box(ot); | WM_operator_properties_select_operation_simple(ot); | ||||
| WM_operator_properties_select_operation_simple(ot); | |||||
| } | } | ||||
| /* ****************************************************** */ | /* ****************************************************** */ | ||||
| Context not available. | |||||