@@ -93,6 +93,41 @@ void GroupsEditor::_set_group_checked(const String &p_name, bool p_checked) {
9393 ti->set_checked (0 , p_checked);
9494}
9595
96+ void GroupsEditor::_add_to_group (const StringName &p_name, bool p_persist, const Array &p_nodes) {
97+ for (const Variant &v : p_nodes) {
98+ Node *node = Object::cast_to<Node>(v.get_validated_object ());
99+ if (node) {
100+ node->add_to_group (p_name, p_persist);
101+ }
102+ }
103+ }
104+
105+ void GroupsEditor::_remove_from_group (const StringName &p_name, const Array &p_nodes) {
106+ for (const Variant &v : p_nodes) {
107+ Node *node = Object::cast_to<Node>(v.get_validated_object ());
108+ if (node) {
109+ node->remove_from_group (p_name);
110+ }
111+ }
112+ }
113+
114+ void GroupsEditor::_get_group_mask (const StringName &p_name, Array &r_nodes, bool p_invert) {
115+ for (Node *p_node : selection) {
116+ if (p_invert != p_node->is_in_group (p_name)) {
117+ r_nodes.push_back (p_node);
118+ }
119+ }
120+ }
121+
122+ bool GroupsEditor::_can_edit (const StringName &p_group) {
123+ for (Node *p_node : selection) {
124+ if (!can_edit (p_node, p_group)) {
125+ return false ;
126+ }
127+ }
128+ return true ;
129+ }
130+
96131bool GroupsEditor::_has_group (const String &p_name) {
97132 return global_groups.has (p_name) || scene_groups.has (p_name);
98133}
@@ -102,7 +137,7 @@ void GroupsEditor::_modify_group(Object *p_item, int p_column, int p_id, MouseBu
102137 return ;
103138 }
104139
105- if (!node ) {
140+ if (selection. is_empty () ) {
106141 return ;
107142 }
108143
@@ -177,7 +212,7 @@ void GroupsEditor::_update_tree() {
177212 return ;
178213 }
179214
180- if (!node ) {
215+ if (selection. is_empty () ) {
181216 return ;
182217 }
183218
@@ -190,7 +225,9 @@ void GroupsEditor::_update_tree() {
190225 tree->clear ();
191226
192227 List<Node::GroupInfo> groups;
193- node->get_groups (&groups);
228+ for (Node *p_node : selection) {
229+ p_node->get_groups (&groups);
230+ }
194231 groups.sort_custom <_GroupInfoComparator>();
195232
196233 List<StringName> current_groups;
@@ -220,7 +257,7 @@ void GroupsEditor::_update_tree() {
220257
221258 TreeItem *item = tree->create_item (local_root);
222259 item->set_cell_mode (0 , TreeItem::CELL_MODE_CHECK);
223- item->set_editable (0 , can_edit (node, E));
260+ item->set_editable (0 , _can_edit ( E));
224261 item->set_checked (0 , current_groups.find (E) != nullptr );
225262 item->set_text (0 , E);
226263 item->set_meta (" __local" , true );
@@ -252,7 +289,7 @@ void GroupsEditor::_update_tree() {
252289
253290 TreeItem *item = tree->create_item (global_root);
254291 item->set_cell_mode (0 , TreeItem::CELL_MODE_CHECK);
255- item->set_editable (0 , can_edit (node, E));
292+ item->set_editable (0 , _can_edit ( E));
256293 item->set_checked (0 , current_groups.find (E) != nullptr );
257294 item->set_text (0 , E);
258295 item->set_meta (" __local" , false );
@@ -307,15 +344,18 @@ void GroupsEditor::_cache_scene_groups(const ObjectID &p_id) {
307344 }
308345}
309346
310- void GroupsEditor::set_current (Node *p_node) {
311- if (node == p_node) {
347+ void GroupsEditor::set_selection (const Vector<Node *> &p_nodes) {
348+ if (p_nodes.is_empty ()) {
349+ holder->hide ();
350+ select_a_node->show ();
351+ selection.clear ();
312352 return ;
313353 }
314- node = p_node;
315354
316- if (!node) {
317- return ;
318- }
355+ selection = p_nodes;
356+
357+ holder->show ();
358+ select_a_node->hide ();
319359
320360 if (scene_tree->get_edited_scene_root () != scene_root_node) {
321361 scene_root_node = scene_tree->get_edited_scene_root ();
@@ -338,8 +378,10 @@ void GroupsEditor::_item_edited() {
338378 if (ti->is_checked (0 )) {
339379 undo_redo->create_action (TTR (" Add to Group" ));
340380
341- undo_redo->add_do_method (node, " add_to_group" , name, true );
342- undo_redo->add_undo_method (node, " remove_from_group" , name);
381+ Array nodes;
382+ _get_group_mask (name, nodes, true );
383+ undo_redo->add_do_method (this , " _add_to_group" , name, true , nodes);
384+ undo_redo->add_undo_method (this , " _remove_from_group" , name, nodes);
343385
344386 undo_redo->add_do_method (this , " _set_group_checked" , name, true );
345387 undo_redo->add_undo_method (this , " _set_group_checked" , name, false );
@@ -353,8 +395,10 @@ void GroupsEditor::_item_edited() {
353395 } else {
354396 undo_redo->create_action (TTR (" Remove from Group" ));
355397
356- undo_redo->add_do_method (node, " remove_from_group" , name);
357- undo_redo->add_undo_method (node, " add_to_group" , name, true );
398+ Array nodes;
399+ _get_group_mask (name, nodes, false );
400+ undo_redo->add_do_method (this , " _remove_from_group" , name, nodes);
401+ undo_redo->add_undo_method (this , " _add_to_group" , name, true , nodes);
358402
359403 undo_redo->add_do_method (this , " _set_group_checked" , name, false );
360404 undo_redo->add_undo_method (this , " _set_group_checked" , name, true );
@@ -489,8 +533,10 @@ void GroupsEditor::_confirm_add() {
489533 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton ();
490534 undo_redo->create_action (TTR (" Add to Group" ));
491535
492- undo_redo->add_do_method (node, " add_to_group" , name, true );
493- undo_redo->add_undo_method (node, " remove_from_group" , name);
536+ Array nodes;
537+ _get_group_mask (name, nodes, true );
538+ undo_redo->add_do_method (this , " _add_to_group" , name, true , nodes);
539+ undo_redo->add_undo_method (this , " _remove_from_group" , name, nodes);
494540
495541 bool is_local = !global_group_button->is_pressed ();
496542 if (is_local) {
@@ -819,6 +865,9 @@ void GroupsEditor::_bind_methods() {
819865 ClassDB::bind_method (" _rename_scene_group" , &GroupsEditor::_rename_scene_group);
820866 ClassDB::bind_method (" _remove_scene_group" , &GroupsEditor::_remove_scene_group);
821867 ClassDB::bind_method (" _set_group_checked" , &GroupsEditor::_set_group_checked);
868+
869+ ClassDB::bind_method (" _add_to_group" , &GroupsEditor::_add_to_group);
870+ ClassDB::bind_method (" _remove_from_group" , &GroupsEditor::_remove_from_group);
822871}
823872
824873void GroupsEditor::_node_removed (Node *p_node) {
@@ -834,15 +883,19 @@ void GroupsEditor::_node_removed(Node *p_node) {
834883}
835884
836885GroupsEditor::GroupsEditor () {
837- node = nullptr ;
838886 scene_tree = SceneTree::get_singleton ();
839887
840888 ED_SHORTCUT (" groups_editor/delete" , TTRC (" Delete" ), Key::KEY_DELETE);
841889 ED_SHORTCUT (" groups_editor/rename" , TTRC (" Rename" ), Key::F2);
842890 ED_SHORTCUT_OVERRIDE (" groups_editor/rename" , " macos" , Key::ENTER);
843891
892+ holder = memnew (VBoxContainer);
893+ holder->set_v_size_flags (SIZE_EXPAND_FILL);
894+ holder->hide ();
895+ add_child (holder);
896+
844897 HBoxContainer *hbc = memnew (HBoxContainer);
845- add_child (hbc);
898+ holder-> add_child (hbc);
846899
847900 add = memnew (Button);
848901 add->set_theme_type_variation (" FlatMenuButton" );
@@ -867,11 +920,21 @@ GroupsEditor::GroupsEditor() {
867920 tree->connect (" button_clicked" , callable_mp (this , &GroupsEditor::_modify_group));
868921 tree->connect (" item_mouse_selected" , callable_mp (this , &GroupsEditor::_item_mouse_selected));
869922 tree->connect (SceneStringName (gui_input), callable_mp (this , &GroupsEditor::_groups_gui_input));
870- add_child (tree);
923+ holder-> add_child (tree);
871924
872925 menu = memnew (PopupMenu);
873926 menu->connect (SceneStringName (id_pressed), callable_mp (this , &GroupsEditor::_menu_id_pressed));
874927 tree->add_child (menu);
875928
929+ select_a_node = memnew (Label);
930+ select_a_node->set_focus_mode (FOCUS_ACCESSIBILITY);
931+ select_a_node->set_text (TTRC (" Select one or more nodes to edit their groups." ));
932+ select_a_node->set_custom_minimum_size (Size2 (100 * EDSCALE, 0 ));
933+ select_a_node->set_v_size_flags (SIZE_EXPAND_FILL);
934+ select_a_node->set_vertical_alignment (VERTICAL_ALIGNMENT_CENTER);
935+ select_a_node->set_horizontal_alignment (HORIZONTAL_ALIGNMENT_CENTER);
936+ select_a_node->set_autowrap_mode (TextServer::AUTOWRAP_WORD_SMART);
937+ add_child (select_a_node);
938+
876939 ProjectSettingsEditor::get_singleton ()->get_group_settings ()->connect (" group_changed" , callable_mp (this , &GroupsEditor::_update_groups_and_tree));
877940}
0 commit comments