@@ -92,6 +92,90 @@ PackedStringArray SceneTreeEditor::_get_node_accessibility_configuration_warning
9292 return warnings;
9393}
9494
95+ void SceneTreeEditor::_gui_input (const Ref<InputEvent> &p_event) {
96+ if (connect_to_script_mode) {
97+ return ; // Don't do anything in this mode.
98+ }
99+
100+ Ref<InputEventMouseButton> mb = p_event;
101+ if (mb.is_valid ()) {
102+ if (mb->get_button_index () == MouseButton::LEFT) {
103+ if (mb->is_pressed ()) {
104+ Vector2 tree_mouse_pos = tree->get_transform ().xform_inv (mb->get_position ());
105+ int tree_button_id = tree->get_button_id_at_position (tree_mouse_pos);
106+ if (tree_button_id == BUTTON_VISIBILITY) {
107+ TreeItem *tree_item = tree->get_item_at_position (tree_mouse_pos);
108+ ERR_FAIL_NULL (tree_item);
109+ NodePath node_path = tree_item->get_metadata (0 );
110+ Node *node = get_node_or_null (node_path);
111+ if (node != nullptr ) {
112+ visibility_drag_value = !node->call (" is_visible" );
113+ visibility_drag_start_pos = tree_mouse_pos;
114+ visibility_drag_start_node = node->get_instance_id ();
115+ }
116+ }
117+ } else if (mb->is_released () && visibility_drag_start_node.is_valid ()) {
118+ if (!visibility_drag_nodes.is_empty ()) {
119+ EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton ();
120+ undo_redo->create_action (vformat (TTR (" Toggle Visibility of %d Nodes" ), visibility_drag_nodes.size ()));
121+
122+ for (ObjectID id : visibility_drag_nodes) {
123+ Node *node = ObjectDB::get_instance<Node>(id);
124+ if (node != nullptr ) {
125+ undo_redo->add_do_method (node, " set_visible" , visibility_drag_value);
126+ undo_redo->add_undo_method (node, " set_visible" , !visibility_drag_value);
127+ }
128+ }
129+
130+ undo_redo->commit_action (false );
131+ }
132+
133+ // Defer this so that `_cell_button_pressed` can still react to the dragging.
134+ callable_mp (this , &SceneTreeEditor::_reset_visibility_drag).call_deferred ();
135+ }
136+ } else if (mb->get_button_index () == MouseButton::RIGHT && visibility_drag_start_node.is_valid ()) {
137+ _reset_visibility_drag ();
138+ accept_event ();
139+ }
140+
141+ return ;
142+ }
143+
144+ Ref<InputEventMouseMotion> mm = p_event;
145+ if (mm.is_valid ()) {
146+ if (visibility_drag_start_node.is_valid ()) {
147+ Vector2 tree_mouse_pos = tree->get_transform ().xform_inv (mm->get_position ());
148+ int tree_button_id = tree->get_button_id_at_position (tree_mouse_pos);
149+ bool crossed_drag_threshold = visibility_drag_start_pos.distance_to (tree_mouse_pos) > get_viewport ()->get_drag_threshold ();
150+ if (tree_button_id == BUTTON_VISIBILITY && (crossed_drag_threshold || !visibility_drag_nodes.is_empty ())) {
151+ Node *start_node = ObjectDB::get_instance<Node>(visibility_drag_start_node);
152+ if (start_node != nullptr && (bool )start_node->call (" is_visible" ) != visibility_drag_value) {
153+ start_node->call (" set_visible" , visibility_drag_value);
154+ visibility_drag_nodes.push_back (visibility_drag_start_node);
155+ }
156+
157+ TreeItem *tree_item = tree->get_item_at_position (tree_mouse_pos);
158+ ERR_FAIL_NULL (tree_item);
159+ NodePath node_path = tree_item->get_metadata (0 );
160+ Node *node = get_node_or_null (node_path);
161+ if (node != nullptr && (bool )node->call (" is_visible" ) != visibility_drag_value) {
162+ node->call (" set_visible" , visibility_drag_value);
163+ visibility_drag_nodes.push_back (node->get_instance_id ());
164+ }
165+ }
166+ }
167+
168+ return ;
169+ }
170+
171+ if (p_event->is_action_type ()) {
172+ if (p_event->is_action_pressed (SNAME (" ui_cancel" )) && visibility_drag_start_node.is_valid ()) {
173+ _reset_visibility_drag ();
174+ accept_event ();
175+ }
176+ }
177+ }
178+
95179void SceneTreeEditor::_cell_button_pressed (Object *p_item, int p_column, int p_id, MouseButton p_button) {
96180 if (p_button != MouseButton::LEFT) {
97181 return ;
@@ -125,6 +209,10 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i
125209 }
126210
127211 } else if (p_id == BUTTON_VISIBILITY) {
212+ if (!visibility_drag_nodes.is_empty ()) {
213+ return ;
214+ }
215+
128216 undo_redo->create_action (TTR (" Toggle Visible" ));
129217 _toggle_visible (n);
130218 List<Node *> selection = editor_selection->get_top_selected_node_list ();
@@ -1367,6 +1455,13 @@ void SceneTreeEditor::_tree_scroll_to_item(ObjectID p_item_id) {
13671455 }
13681456}
13691457
1458+ void SceneTreeEditor::_reset_visibility_drag () {
1459+ visibility_drag_value = false ;
1460+ visibility_drag_start_pos = Vector2 ();
1461+ visibility_drag_start_node = ObjectID ();
1462+ visibility_drag_nodes.clear ();
1463+ }
1464+
13701465void SceneTreeEditor::_notification (int p_what) {
13711466 switch (p_what) {
13721467 case NOTIFICATION_ENTER_TREE: {
@@ -1430,6 +1525,11 @@ void SceneTreeEditor::_notification(int p_what) {
14301525 }
14311526 }
14321527 } break ;
1528+
1529+ case NOTIFICATION_APPLICATION_FOCUS_OUT:
1530+ case NOTIFICATION_WM_WINDOW_FOCUS_OUT: {
1531+ _reset_visibility_drag ();
1532+ } break ;
14331533 }
14341534}
14351535
@@ -2194,6 +2294,7 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
21942294 tree->connect (" multi_selected" , callable_mp (this , &SceneTreeEditor::_cell_multi_selected));
21952295 tree->connect (" button_clicked" , callable_mp (this , &SceneTreeEditor::_cell_button_pressed));
21962296 tree->connect (" nothing_selected" , callable_mp (this , &SceneTreeEditor::_deselect_items));
2297+ tree->connect (SceneStringName (gui_input), callable_mp (this , &SceneTreeEditor::_gui_input));
21972298
21982299 error = memnew (AcceptDialog);
21992300 add_child (error);
0 commit comments