|
|
@@ -93,6 +93,41 @@ void GroupsEditor::_set_group_checked(const String &p_name, bool p_checked) {
|
|
|
ti->set_checked(0, p_checked);
|
|
|
}
|
|
|
|
|
|
+void GroupsEditor::_add_to_group(const StringName &p_name, bool p_persist, const Array &p_nodes) {
|
|
|
+ for (const Variant &v : p_nodes) {
|
|
|
+ Node *node = Object::cast_to<Node>(v.get_validated_object());
|
|
|
+ if (node) {
|
|
|
+ node->add_to_group(p_name, p_persist);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void GroupsEditor::_remove_from_group(const StringName &p_name, const Array &p_nodes) {
|
|
|
+ for (const Variant &v : p_nodes) {
|
|
|
+ Node *node = Object::cast_to<Node>(v.get_validated_object());
|
|
|
+ if (node) {
|
|
|
+ node->remove_from_group(p_name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void GroupsEditor::_get_group_mask(const StringName &p_name, Array &r_nodes, bool p_invert) {
|
|
|
+ for (Node *p_node : selection) {
|
|
|
+ if (p_invert != p_node->is_in_group(p_name)) {
|
|
|
+ r_nodes.push_back(p_node);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+bool GroupsEditor::_can_edit(const StringName &p_group) {
|
|
|
+ for (Node *p_node : selection) {
|
|
|
+ if (!can_edit(p_node, p_group)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
bool GroupsEditor::_has_group(const String &p_name) {
|
|
|
return global_groups.has(p_name) || scene_groups.has(p_name);
|
|
|
}
|
|
|
@@ -102,7 +137,7 @@ void GroupsEditor::_modify_group(Object *p_item, int p_column, int p_id, MouseBu
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (!node) {
|
|
|
+ if (selection.is_empty()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -177,7 +212,7 @@ void GroupsEditor::_update_tree() {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (!node) {
|
|
|
+ if (selection.is_empty()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -190,7 +225,9 @@ void GroupsEditor::_update_tree() {
|
|
|
tree->clear();
|
|
|
|
|
|
List<Node::GroupInfo> groups;
|
|
|
- node->get_groups(&groups);
|
|
|
+ for (Node *p_node : selection) {
|
|
|
+ p_node->get_groups(&groups);
|
|
|
+ }
|
|
|
groups.sort_custom<_GroupInfoComparator>();
|
|
|
|
|
|
List<StringName> current_groups;
|
|
|
@@ -220,7 +257,7 @@ void GroupsEditor::_update_tree() {
|
|
|
|
|
|
TreeItem *item = tree->create_item(local_root);
|
|
|
item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
|
|
|
- item->set_editable(0, can_edit(node, E));
|
|
|
+ item->set_editable(0, _can_edit(E));
|
|
|
item->set_checked(0, current_groups.find(E) != nullptr);
|
|
|
item->set_text(0, E);
|
|
|
item->set_meta("__local", true);
|
|
|
@@ -252,7 +289,7 @@ void GroupsEditor::_update_tree() {
|
|
|
|
|
|
TreeItem *item = tree->create_item(global_root);
|
|
|
item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
|
|
|
- item->set_editable(0, can_edit(node, E));
|
|
|
+ item->set_editable(0, _can_edit(E));
|
|
|
item->set_checked(0, current_groups.find(E) != nullptr);
|
|
|
item->set_text(0, E);
|
|
|
item->set_meta("__local", false);
|
|
|
@@ -307,15 +344,18 @@ void GroupsEditor::_cache_scene_groups(const ObjectID &p_id) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void GroupsEditor::set_current(Node *p_node) {
|
|
|
- if (node == p_node) {
|
|
|
+void GroupsEditor::set_selection(const Vector<Node *> &p_nodes) {
|
|
|
+ if (p_nodes.is_empty()) {
|
|
|
+ holder->hide();
|
|
|
+ select_a_node->show();
|
|
|
+ selection.clear();
|
|
|
return;
|
|
|
}
|
|
|
- node = p_node;
|
|
|
|
|
|
- if (!node) {
|
|
|
- return;
|
|
|
- }
|
|
|
+ selection = p_nodes;
|
|
|
+
|
|
|
+ holder->show();
|
|
|
+ select_a_node->hide();
|
|
|
|
|
|
if (scene_tree->get_edited_scene_root() != scene_root_node) {
|
|
|
scene_root_node = scene_tree->get_edited_scene_root();
|
|
|
@@ -338,8 +378,10 @@ void GroupsEditor::_item_edited() {
|
|
|
if (ti->is_checked(0)) {
|
|
|
undo_redo->create_action(TTR("Add to Group"));
|
|
|
|
|
|
- undo_redo->add_do_method(node, "add_to_group", name, true);
|
|
|
- undo_redo->add_undo_method(node, "remove_from_group", name);
|
|
|
+ Array nodes;
|
|
|
+ _get_group_mask(name, nodes, true);
|
|
|
+ undo_redo->add_do_method(this, "_add_to_group", name, true, nodes);
|
|
|
+ undo_redo->add_undo_method(this, "_remove_from_group", name, nodes);
|
|
|
|
|
|
undo_redo->add_do_method(this, "_set_group_checked", name, true);
|
|
|
undo_redo->add_undo_method(this, "_set_group_checked", name, false);
|
|
|
@@ -353,8 +395,10 @@ void GroupsEditor::_item_edited() {
|
|
|
} else {
|
|
|
undo_redo->create_action(TTR("Remove from Group"));
|
|
|
|
|
|
- undo_redo->add_do_method(node, "remove_from_group", name);
|
|
|
- undo_redo->add_undo_method(node, "add_to_group", name, true);
|
|
|
+ Array nodes;
|
|
|
+ _get_group_mask(name, nodes, false);
|
|
|
+ undo_redo->add_do_method(this, "_remove_from_group", name, nodes);
|
|
|
+ undo_redo->add_undo_method(this, "_add_to_group", name, true, nodes);
|
|
|
|
|
|
undo_redo->add_do_method(this, "_set_group_checked", name, false);
|
|
|
undo_redo->add_undo_method(this, "_set_group_checked", name, true);
|
|
|
@@ -489,8 +533,10 @@ void GroupsEditor::_confirm_add() {
|
|
|
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
|
|
|
undo_redo->create_action(TTR("Add to Group"));
|
|
|
|
|
|
- undo_redo->add_do_method(node, "add_to_group", name, true);
|
|
|
- undo_redo->add_undo_method(node, "remove_from_group", name);
|
|
|
+ Array nodes;
|
|
|
+ _get_group_mask(name, nodes, true);
|
|
|
+ undo_redo->add_do_method(this, "_add_to_group", name, true, nodes);
|
|
|
+ undo_redo->add_undo_method(this, "_remove_from_group", name, nodes);
|
|
|
|
|
|
bool is_local = !global_group_button->is_pressed();
|
|
|
if (is_local) {
|
|
|
@@ -819,6 +865,9 @@ void GroupsEditor::_bind_methods() {
|
|
|
ClassDB::bind_method("_rename_scene_group", &GroupsEditor::_rename_scene_group);
|
|
|
ClassDB::bind_method("_remove_scene_group", &GroupsEditor::_remove_scene_group);
|
|
|
ClassDB::bind_method("_set_group_checked", &GroupsEditor::_set_group_checked);
|
|
|
+
|
|
|
+ ClassDB::bind_method("_add_to_group", &GroupsEditor::_add_to_group);
|
|
|
+ ClassDB::bind_method("_remove_from_group", &GroupsEditor::_remove_from_group);
|
|
|
}
|
|
|
|
|
|
void GroupsEditor::_node_removed(Node *p_node) {
|
|
|
@@ -834,15 +883,19 @@ void GroupsEditor::_node_removed(Node *p_node) {
|
|
|
}
|
|
|
|
|
|
GroupsEditor::GroupsEditor() {
|
|
|
- node = nullptr;
|
|
|
scene_tree = SceneTree::get_singleton();
|
|
|
|
|
|
ED_SHORTCUT("groups_editor/delete", TTRC("Delete"), Key::KEY_DELETE);
|
|
|
ED_SHORTCUT("groups_editor/rename", TTRC("Rename"), Key::F2);
|
|
|
ED_SHORTCUT_OVERRIDE("groups_editor/rename", "macos", Key::ENTER);
|
|
|
|
|
|
+ holder = memnew(VBoxContainer);
|
|
|
+ holder->set_v_size_flags(SIZE_EXPAND_FILL);
|
|
|
+ holder->hide();
|
|
|
+ add_child(holder);
|
|
|
+
|
|
|
HBoxContainer *hbc = memnew(HBoxContainer);
|
|
|
- add_child(hbc);
|
|
|
+ holder->add_child(hbc);
|
|
|
|
|
|
add = memnew(Button);
|
|
|
add->set_theme_type_variation("FlatMenuButton");
|
|
|
@@ -867,11 +920,21 @@ GroupsEditor::GroupsEditor() {
|
|
|
tree->connect("button_clicked", callable_mp(this, &GroupsEditor::_modify_group));
|
|
|
tree->connect("item_mouse_selected", callable_mp(this, &GroupsEditor::_item_mouse_selected));
|
|
|
tree->connect(SceneStringName(gui_input), callable_mp(this, &GroupsEditor::_groups_gui_input));
|
|
|
- add_child(tree);
|
|
|
+ holder->add_child(tree);
|
|
|
|
|
|
menu = memnew(PopupMenu);
|
|
|
menu->connect(SceneStringName(id_pressed), callable_mp(this, &GroupsEditor::_menu_id_pressed));
|
|
|
tree->add_child(menu);
|
|
|
|
|
|
+ select_a_node = memnew(Label);
|
|
|
+ select_a_node->set_focus_mode(FOCUS_ACCESSIBILITY);
|
|
|
+ select_a_node->set_text(TTRC("Select one or more nodes to edit their groups."));
|
|
|
+ select_a_node->set_custom_minimum_size(Size2(100 * EDSCALE, 0));
|
|
|
+ select_a_node->set_v_size_flags(SIZE_EXPAND_FILL);
|
|
|
+ select_a_node->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER);
|
|
|
+ select_a_node->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
|
|
|
+ select_a_node->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
|
|
|
+ add_child(select_a_node);
|
|
|
+
|
|
|
ProjectSettingsEditor::get_singleton()->get_group_settings()->connect("group_changed", callable_mp(this, &GroupsEditor::_update_groups_and_tree));
|
|
|
}
|