@@ -3557,6 +3557,47 @@ void Tree::_go_up() {
35573557 accept_event ();
35583558}
35593559
3560+ void Tree::_shift_select_range (TreeItem *new_item) {
3561+ if (!new_item) {
3562+ new_item = selected_item;
3563+ }
3564+ int s_col = selected_col;
3565+ bool in_range = false ;
3566+ TreeItem *item = root;
3567+
3568+ if (!shift_anchor) {
3569+ shift_anchor = selected_item;
3570+ }
3571+
3572+ while (item) {
3573+ bool at_range_edge = item == shift_anchor || item == new_item;
3574+ if (at_range_edge) {
3575+ in_range = !in_range;
3576+ }
3577+ if (new_item == shift_anchor) {
3578+ in_range = false ;
3579+ }
3580+ if (item->is_visible_in_tree ()) {
3581+ if (in_range || at_range_edge) {
3582+ if (!item->is_selected (selected_col) && item->is_selectable (selected_col)) {
3583+ item->select (selected_col);
3584+ emit_signal (SNAME (" multi_selected" ), item, selected_col, true );
3585+ }
3586+ } else if (item->is_selected (selected_col)) {
3587+ item->deselect (selected_col);
3588+ emit_signal (SNAME (" multi_selected" ), item, selected_col, false );
3589+ }
3590+ }
3591+ item = item->get_next_in_tree (false );
3592+ }
3593+
3594+ selected_item = new_item;
3595+ selected_col = s_col;
3596+ ensure_cursor_is_visible ();
3597+ queue_redraw ();
3598+ accept_event ();
3599+ }
3600+
35603601void Tree::_go_down () {
35613602 TreeItem *next = nullptr ;
35623603 if (!selected_item) {
@@ -3646,6 +3687,10 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
36463687
36473688 Ref<InputEventKey> k = p_event;
36483689
3690+ if (k.is_valid () && k->get_keycode () == Key::SHIFT && !k->is_pressed ()) {
3691+ shift_anchor = nullptr ;
3692+ }
3693+
36493694 bool is_command = k.is_valid () && k->is_command_or_control_pressed ();
36503695 if (p_event->is_action (cache.rtl ? " ui_left" : " ui_right" ) && p_event->is_pressed ()) {
36513696 if (!cursor_can_exit_tree) {
@@ -3687,15 +3732,25 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
36873732 if (!cursor_can_exit_tree) {
36883733 accept_event ();
36893734 }
3690-
3691- _go_up ();
3735+ // Shift Up Selection.
3736+ if (k.is_valid () && k->is_shift_pressed () && selected_item && select_mode == SELECT_MULTI) {
3737+ TreeItem *new_item = selected_item->get_prev_visible (false );
3738+ _shift_select_range (new_item);
3739+ } else {
3740+ _go_up ();
3741+ }
36923742
36933743 } else if (p_event->is_action (" ui_down" ) && p_event->is_pressed () && !is_command) {
36943744 if (!cursor_can_exit_tree) {
36953745 accept_event ();
36963746 }
3697-
3698- _go_down ();
3747+ // Shift Down Selection.
3748+ if (k.is_valid () && k->is_shift_pressed () && selected_item && select_mode == SELECT_MULTI) {
3749+ TreeItem *new_item = selected_item->get_next_visible (false );
3750+ _shift_select_range (new_item);
3751+ } else {
3752+ _go_down ();
3753+ }
36993754 } else if (p_event->is_action (" ui_menu" ) && p_event->is_pressed ()) {
37003755 if (allow_rmb_select && selected_item) {
37013756 emit_signal (SNAME (" item_mouse_selected" ), get_item_rect (selected_item).position , MouseButton::RIGHT);
0 commit comments