You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-12-03 16:55:53 +00:00
Merge pull request #112729 from KoBeWi/multi_group_yoink
Edit groups on multiple nodes
This commit is contained in:
@@ -93,6 +93,41 @@ void GroupsEditor::_set_group_checked(const String &p_name, bool p_checked) {
|
|||||||
ti->set_checked(0, 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) {
|
bool GroupsEditor::_has_group(const String &p_name) {
|
||||||
return global_groups.has(p_name) || scene_groups.has(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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!node) {
|
if (selection.is_empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +212,7 @@ void GroupsEditor::_update_tree() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!node) {
|
if (selection.is_empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +225,9 @@ void GroupsEditor::_update_tree() {
|
|||||||
tree->clear();
|
tree->clear();
|
||||||
|
|
||||||
List<Node::GroupInfo> groups;
|
List<Node::GroupInfo> groups;
|
||||||
node->get_groups(&groups);
|
for (Node *p_node : selection) {
|
||||||
|
p_node->get_groups(&groups);
|
||||||
|
}
|
||||||
groups.sort_custom<_GroupInfoComparator>();
|
groups.sort_custom<_GroupInfoComparator>();
|
||||||
|
|
||||||
List<StringName> current_groups;
|
List<StringName> current_groups;
|
||||||
@@ -220,7 +257,7 @@ void GroupsEditor::_update_tree() {
|
|||||||
|
|
||||||
TreeItem *item = tree->create_item(local_root);
|
TreeItem *item = tree->create_item(local_root);
|
||||||
item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
|
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_checked(0, current_groups.find(E) != nullptr);
|
||||||
item->set_text(0, E);
|
item->set_text(0, E);
|
||||||
item->set_meta("__local", true);
|
item->set_meta("__local", true);
|
||||||
@@ -252,7 +289,7 @@ void GroupsEditor::_update_tree() {
|
|||||||
|
|
||||||
TreeItem *item = tree->create_item(global_root);
|
TreeItem *item = tree->create_item(global_root);
|
||||||
item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
|
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_checked(0, current_groups.find(E) != nullptr);
|
||||||
item->set_text(0, E);
|
item->set_text(0, E);
|
||||||
item->set_meta("__local", false);
|
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) {
|
void GroupsEditor::set_selection(const Vector<Node *> &p_nodes) {
|
||||||
if (node == p_node) {
|
if (p_nodes.is_empty()) {
|
||||||
|
holder->hide();
|
||||||
|
select_a_node->show();
|
||||||
|
selection.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
node = p_node;
|
|
||||||
|
|
||||||
if (!node) {
|
selection = p_nodes;
|
||||||
return;
|
|
||||||
}
|
holder->show();
|
||||||
|
select_a_node->hide();
|
||||||
|
|
||||||
if (scene_tree->get_edited_scene_root() != scene_root_node) {
|
if (scene_tree->get_edited_scene_root() != scene_root_node) {
|
||||||
scene_root_node = scene_tree->get_edited_scene_root();
|
scene_root_node = scene_tree->get_edited_scene_root();
|
||||||
@@ -338,8 +378,10 @@ void GroupsEditor::_item_edited() {
|
|||||||
if (ti->is_checked(0)) {
|
if (ti->is_checked(0)) {
|
||||||
undo_redo->create_action(TTR("Add to Group"));
|
undo_redo->create_action(TTR("Add to Group"));
|
||||||
|
|
||||||
undo_redo->add_do_method(node, "add_to_group", name, true);
|
Array nodes;
|
||||||
undo_redo->add_undo_method(node, "remove_from_group", name);
|
_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_do_method(this, "_set_group_checked", name, true);
|
||||||
undo_redo->add_undo_method(this, "_set_group_checked", name, false);
|
undo_redo->add_undo_method(this, "_set_group_checked", name, false);
|
||||||
@@ -353,8 +395,10 @@ void GroupsEditor::_item_edited() {
|
|||||||
} else {
|
} else {
|
||||||
undo_redo->create_action(TTR("Remove from Group"));
|
undo_redo->create_action(TTR("Remove from Group"));
|
||||||
|
|
||||||
undo_redo->add_do_method(node, "remove_from_group", name);
|
Array nodes;
|
||||||
undo_redo->add_undo_method(node, "add_to_group", name, true);
|
_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_do_method(this, "_set_group_checked", name, false);
|
||||||
undo_redo->add_undo_method(this, "_set_group_checked", name, true);
|
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();
|
EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
|
||||||
undo_redo->create_action(TTR("Add to Group"));
|
undo_redo->create_action(TTR("Add to Group"));
|
||||||
|
|
||||||
undo_redo->add_do_method(node, "add_to_group", name, true);
|
Array nodes;
|
||||||
undo_redo->add_undo_method(node, "remove_from_group", name);
|
_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();
|
bool is_local = !global_group_button->is_pressed();
|
||||||
if (is_local) {
|
if (is_local) {
|
||||||
@@ -819,6 +865,9 @@ void GroupsEditor::_bind_methods() {
|
|||||||
ClassDB::bind_method("_rename_scene_group", &GroupsEditor::_rename_scene_group);
|
ClassDB::bind_method("_rename_scene_group", &GroupsEditor::_rename_scene_group);
|
||||||
ClassDB::bind_method("_remove_scene_group", &GroupsEditor::_remove_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("_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) {
|
void GroupsEditor::_node_removed(Node *p_node) {
|
||||||
@@ -834,15 +883,19 @@ void GroupsEditor::_node_removed(Node *p_node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GroupsEditor::GroupsEditor() {
|
GroupsEditor::GroupsEditor() {
|
||||||
node = nullptr;
|
|
||||||
scene_tree = SceneTree::get_singleton();
|
scene_tree = SceneTree::get_singleton();
|
||||||
|
|
||||||
ED_SHORTCUT("groups_editor/delete", TTRC("Delete"), Key::KEY_DELETE);
|
ED_SHORTCUT("groups_editor/delete", TTRC("Delete"), Key::KEY_DELETE);
|
||||||
ED_SHORTCUT("groups_editor/rename", TTRC("Rename"), Key::F2);
|
ED_SHORTCUT("groups_editor/rename", TTRC("Rename"), Key::F2);
|
||||||
ED_SHORTCUT_OVERRIDE("groups_editor/rename", "macos", Key::ENTER);
|
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);
|
HBoxContainer *hbc = memnew(HBoxContainer);
|
||||||
add_child(hbc);
|
holder->add_child(hbc);
|
||||||
|
|
||||||
add = memnew(Button);
|
add = memnew(Button);
|
||||||
add->set_theme_type_variation("FlatMenuButton");
|
add->set_theme_type_variation("FlatMenuButton");
|
||||||
@@ -867,11 +920,21 @@ GroupsEditor::GroupsEditor() {
|
|||||||
tree->connect("button_clicked", callable_mp(this, &GroupsEditor::_modify_group));
|
tree->connect("button_clicked", callable_mp(this, &GroupsEditor::_modify_group));
|
||||||
tree->connect("item_mouse_selected", callable_mp(this, &GroupsEditor::_item_mouse_selected));
|
tree->connect("item_mouse_selected", callable_mp(this, &GroupsEditor::_item_mouse_selected));
|
||||||
tree->connect(SceneStringName(gui_input), callable_mp(this, &GroupsEditor::_groups_gui_input));
|
tree->connect(SceneStringName(gui_input), callable_mp(this, &GroupsEditor::_groups_gui_input));
|
||||||
add_child(tree);
|
holder->add_child(tree);
|
||||||
|
|
||||||
menu = memnew(PopupMenu);
|
menu = memnew(PopupMenu);
|
||||||
menu->connect(SceneStringName(id_pressed), callable_mp(this, &GroupsEditor::_menu_id_pressed));
|
menu->connect(SceneStringName(id_pressed), callable_mp(this, &GroupsEditor::_menu_id_pressed));
|
||||||
tree->add_child(menu);
|
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));
|
ProjectSettingsEditor::get_singleton()->get_group_settings()->connect("group_changed", callable_mp(this, &GroupsEditor::_update_groups_and_tree));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ class GroupsEditor : public VBoxContainer {
|
|||||||
bool groups_dirty = false;
|
bool groups_dirty = false;
|
||||||
bool update_groups_and_tree_queued = false;
|
bool update_groups_and_tree_queued = false;
|
||||||
|
|
||||||
Node *node = nullptr;
|
LocalVector<Node *> selection;
|
||||||
Node *scene_root_node = nullptr;
|
Node *scene_root_node = nullptr;
|
||||||
SceneTree *scene_tree = nullptr;
|
SceneTree *scene_tree = nullptr;
|
||||||
|
|
||||||
@@ -73,9 +73,11 @@ class GroupsEditor : public VBoxContainer {
|
|||||||
|
|
||||||
PopupMenu *menu = nullptr;
|
PopupMenu *menu = nullptr;
|
||||||
|
|
||||||
|
VBoxContainer *holder = nullptr;
|
||||||
LineEdit *filter = nullptr;
|
LineEdit *filter = nullptr;
|
||||||
Button *add = nullptr;
|
Button *add = nullptr;
|
||||||
Tree *tree = nullptr;
|
Tree *tree = nullptr;
|
||||||
|
Label *select_a_node = nullptr;
|
||||||
|
|
||||||
HashMap<ObjectID, HashMap<StringName, bool>> scene_groups_cache;
|
HashMap<ObjectID, HashMap<StringName, bool>> scene_groups_cache;
|
||||||
HashMap<StringName, bool> scene_groups_for_caching;
|
HashMap<StringName, bool> scene_groups_for_caching;
|
||||||
@@ -122,6 +124,11 @@ class GroupsEditor : public VBoxContainer {
|
|||||||
|
|
||||||
void _node_removed(Node *p_node);
|
void _node_removed(Node *p_node);
|
||||||
|
|
||||||
|
void _add_to_group(const StringName &p_name, bool p_persist, const Array &p_nodes);
|
||||||
|
void _remove_from_group(const StringName &p_name, const Array &p_nodes);
|
||||||
|
void _get_group_mask(const StringName &p_name, Array &r_nodes, bool p_invert);
|
||||||
|
bool _can_edit(const StringName &p_group);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
@@ -134,7 +141,7 @@ public:
|
|||||||
CONVERT_GROUP,
|
CONVERT_GROUP,
|
||||||
};
|
};
|
||||||
|
|
||||||
void set_current(Node *p_node);
|
void set_selection(const Vector<Node *> &p_nodes);
|
||||||
|
|
||||||
GroupsEditor();
|
GroupsEditor();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -55,15 +55,7 @@ void NodeDock::save_layout_to_config(Ref<ConfigFile> &p_layout, const String &p_
|
|||||||
|
|
||||||
void NodeDock::load_layout_from_config(const Ref<ConfigFile> &p_layout, const String &p_section) {
|
void NodeDock::load_layout_from_config(const Ref<ConfigFile> &p_layout, const String &p_section) {
|
||||||
const int current_tab = p_layout->get_value(p_section, "current_tab", 0);
|
const int current_tab = p_layout->get_value(p_section, "current_tab", 0);
|
||||||
if (select_a_node->is_visible()) {
|
if (current_tab == 0) {
|
||||||
if (current_tab == 0) {
|
|
||||||
groups_button->set_pressed_no_signal(false);
|
|
||||||
connections_button->set_pressed_no_signal(true);
|
|
||||||
} else if (current_tab == 1) {
|
|
||||||
groups_button->set_pressed_no_signal(true);
|
|
||||||
connections_button->set_pressed_no_signal(false);
|
|
||||||
}
|
|
||||||
} else if (current_tab == 0) {
|
|
||||||
show_connections();
|
show_connections();
|
||||||
} else if (current_tab == 1) {
|
} else if (current_tab == 1) {
|
||||||
show_groups();
|
show_groups();
|
||||||
@@ -83,32 +75,17 @@ void NodeDock::update_lists() {
|
|||||||
connections->update_tree();
|
connections->update_tree();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDock::set_object(Object *p_object) {
|
void NodeDock::set_selection(const Vector<Object *> &p_objects) {
|
||||||
connections->set_object(p_object);
|
connections->set_selection(p_objects);
|
||||||
groups->set_current(Object::cast_to<Node>(p_object));
|
|
||||||
|
|
||||||
if (p_object) {
|
Vector<Node *> nodes;
|
||||||
if (connections_button->is_pressed()) {
|
for (Object *obj : p_objects) {
|
||||||
connections->show();
|
Node *n = Object::cast_to<Node>(obj);
|
||||||
} else {
|
if (n) {
|
||||||
groups->show();
|
nodes.append(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Object::cast_to<Resource>(p_object)) {
|
|
||||||
show_connections();
|
|
||||||
groups_button->set_disabled(true);
|
|
||||||
} else {
|
|
||||||
groups_button->set_disabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
mode_hb->show();
|
|
||||||
select_a_node->hide();
|
|
||||||
} else {
|
|
||||||
connections->hide();
|
|
||||||
groups->hide();
|
|
||||||
mode_hb->hide();
|
|
||||||
select_a_node->show();
|
|
||||||
}
|
}
|
||||||
|
groups->set_selection(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeDock::NodeDock() {
|
NodeDock::NodeDock() {
|
||||||
@@ -123,13 +100,11 @@ NodeDock::NodeDock() {
|
|||||||
|
|
||||||
mode_hb = memnew(HBoxContainer);
|
mode_hb = memnew(HBoxContainer);
|
||||||
main_vb->add_child(mode_hb);
|
main_vb->add_child(mode_hb);
|
||||||
mode_hb->hide();
|
|
||||||
|
|
||||||
connections_button = memnew(Button);
|
connections_button = memnew(Button);
|
||||||
connections_button->set_theme_type_variation(SceneStringName(FlatButton));
|
connections_button->set_theme_type_variation(SceneStringName(FlatButton));
|
||||||
connections_button->set_text(TTRC("Signals"));
|
connections_button->set_text(TTRC("Signals"));
|
||||||
connections_button->set_toggle_mode(true);
|
connections_button->set_toggle_mode(true);
|
||||||
connections_button->set_pressed(true);
|
|
||||||
connections_button->set_h_size_flags(SIZE_EXPAND_FILL);
|
connections_button->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||||
connections_button->set_clip_text(true);
|
connections_button->set_clip_text(true);
|
||||||
mode_hb->add_child(connections_button);
|
mode_hb->add_child(connections_button);
|
||||||
@@ -139,7 +114,6 @@ NodeDock::NodeDock() {
|
|||||||
groups_button->set_theme_type_variation(SceneStringName(FlatButton));
|
groups_button->set_theme_type_variation(SceneStringName(FlatButton));
|
||||||
groups_button->set_text(TTRC("Groups"));
|
groups_button->set_text(TTRC("Groups"));
|
||||||
groups_button->set_toggle_mode(true);
|
groups_button->set_toggle_mode(true);
|
||||||
groups_button->set_pressed(false);
|
|
||||||
groups_button->set_h_size_flags(SIZE_EXPAND_FILL);
|
groups_button->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||||
groups_button->set_clip_text(true);
|
groups_button->set_clip_text(true);
|
||||||
mode_hb->add_child(groups_button);
|
mode_hb->add_child(groups_button);
|
||||||
@@ -155,15 +129,7 @@ NodeDock::NodeDock() {
|
|||||||
groups->set_v_size_flags(SIZE_EXPAND_FILL);
|
groups->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||||
groups->hide();
|
groups->hide();
|
||||||
|
|
||||||
select_a_node = memnew(Label);
|
show_connections();
|
||||||
select_a_node->set_focus_mode(FOCUS_ACCESSIBILITY);
|
|
||||||
select_a_node->set_text(TTRC("Select a single node to edit its signals and groups, or select an independent resource to view its signals."));
|
|
||||||
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);
|
|
||||||
main_vb->add_child(select_a_node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeDock::~NodeDock() {
|
NodeDock::~NodeDock() {
|
||||||
|
|||||||
@@ -47,8 +47,6 @@ class NodeDock : public EditorDock {
|
|||||||
|
|
||||||
HBoxContainer *mode_hb = nullptr;
|
HBoxContainer *mode_hb = nullptr;
|
||||||
|
|
||||||
Label *select_a_node = nullptr;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline static NodeDock *singleton = nullptr;
|
inline static NodeDock *singleton = nullptr;
|
||||||
|
|
||||||
@@ -62,7 +60,7 @@ protected:
|
|||||||
virtual void load_layout_from_config(const Ref<ConfigFile> &p_layout, const String &p_section) override;
|
virtual void load_layout_from_config(const Ref<ConfigFile> &p_layout, const String &p_section) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void set_object(Object *p_object);
|
void set_selection(const Vector<Object *> &p_objects);
|
||||||
|
|
||||||
void show_groups();
|
void show_groups();
|
||||||
void show_connections();
|
void show_connections();
|
||||||
|
|||||||
@@ -1351,7 +1351,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
|
|||||||
undo_redo->add_undo_method(node, "set_scene_file_path", node->get_scene_file_path());
|
undo_redo->add_undo_method(node, "set_scene_file_path", node->get_scene_file_path());
|
||||||
_node_replace_owner(node, node, root);
|
_node_replace_owner(node, node, root);
|
||||||
_node_strip_signal_inheritance(node);
|
_node_strip_signal_inheritance(node);
|
||||||
NodeDock::get_singleton()->set_object(node); // Refresh.
|
NodeDock::get_singleton()->set_selection(Vector<Object *>{ node }); // Refresh.
|
||||||
undo_redo->add_do_method(scene_tree, "update_tree");
|
undo_redo->add_do_method(scene_tree, "update_tree");
|
||||||
undo_redo->add_undo_method(scene_tree, "update_tree");
|
undo_redo->add_undo_method(scene_tree, "update_tree");
|
||||||
undo_redo->commit_action();
|
undo_redo->commit_action();
|
||||||
@@ -2855,7 +2855,7 @@ void SceneTreeDock::_delete_confirm(bool p_cut) {
|
|||||||
editor_history->cleanup_history();
|
editor_history->cleanup_history();
|
||||||
InspectorDock::get_singleton()->call("_prepare_history");
|
InspectorDock::get_singleton()->call("_prepare_history");
|
||||||
InspectorDock::get_singleton()->update(nullptr);
|
InspectorDock::get_singleton()->update(nullptr);
|
||||||
NodeDock::get_singleton()->set_object(nullptr);
|
NodeDock::get_singleton()->set_selection(Vector<Object *>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneTreeDock::_update_script_button() {
|
void SceneTreeDock::_update_script_button() {
|
||||||
|
|||||||
@@ -2888,7 +2888,7 @@ void EditorNode::push_node_item(Node *p_node) {
|
|||||||
void EditorNode::push_item(Object *p_object, const String &p_property, bool p_inspector_only) {
|
void EditorNode::push_item(Object *p_object, const String &p_property, bool p_inspector_only) {
|
||||||
if (!p_object) {
|
if (!p_object) {
|
||||||
InspectorDock::get_inspector_singleton()->edit(nullptr);
|
InspectorDock::get_inspector_singleton()->edit(nullptr);
|
||||||
NodeDock::get_singleton()->set_object(nullptr);
|
NodeDock::get_singleton()->set_selection(Vector<Object *>());
|
||||||
SceneTreeDock::get_singleton()->set_selected(nullptr);
|
SceneTreeDock::get_singleton()->set_selected(nullptr);
|
||||||
InspectorDock::get_singleton()->update(nullptr);
|
InspectorDock::get_singleton()->update(nullptr);
|
||||||
hide_unused_editors();
|
hide_unused_editors();
|
||||||
@@ -2999,7 +2999,7 @@ void EditorNode::_edit_current(bool p_skip_foreign, bool p_skip_inspector_update
|
|||||||
if (!current_obj) {
|
if (!current_obj) {
|
||||||
SceneTreeDock::get_singleton()->set_selected(nullptr);
|
SceneTreeDock::get_singleton()->set_selected(nullptr);
|
||||||
InspectorDock::get_inspector_singleton()->edit(nullptr);
|
InspectorDock::get_inspector_singleton()->edit(nullptr);
|
||||||
NodeDock::get_singleton()->set_object(nullptr);
|
NodeDock::get_singleton()->set_selection(Vector<Object *>());
|
||||||
InspectorDock::get_singleton()->update(nullptr);
|
InspectorDock::get_singleton()->update(nullptr);
|
||||||
EditorDebuggerNode::get_singleton()->clear_remote_tree_selection();
|
EditorDebuggerNode::get_singleton()->clear_remote_tree_selection();
|
||||||
hide_unused_editors();
|
hide_unused_editors();
|
||||||
@@ -3033,7 +3033,7 @@ void EditorNode::_edit_current(bool p_skip_foreign, bool p_skip_inspector_update
|
|||||||
if (!p_skip_inspector_update) {
|
if (!p_skip_inspector_update) {
|
||||||
InspectorDock::get_inspector_singleton()->edit(current_res);
|
InspectorDock::get_inspector_singleton()->edit(current_res);
|
||||||
SceneTreeDock::get_singleton()->set_selected(nullptr);
|
SceneTreeDock::get_singleton()->set_selected(nullptr);
|
||||||
NodeDock::get_singleton()->set_object(current_res);
|
NodeDock::get_singleton()->set_selection(Vector<Object *>{ current_res });
|
||||||
InspectorDock::get_singleton()->update(nullptr);
|
InspectorDock::get_singleton()->update(nullptr);
|
||||||
EditorDebuggerNode::get_singleton()->clear_remote_tree_selection();
|
EditorDebuggerNode::get_singleton()->clear_remote_tree_selection();
|
||||||
ImportDock::get_singleton()->set_edit_path(current_res->get_path());
|
ImportDock::get_singleton()->set_edit_path(current_res->get_path());
|
||||||
@@ -3063,7 +3063,7 @@ void EditorNode::_edit_current(bool p_skip_foreign, bool p_skip_inspector_update
|
|||||||
|
|
||||||
InspectorDock::get_inspector_singleton()->edit(current_node);
|
InspectorDock::get_inspector_singleton()->edit(current_node);
|
||||||
if (current_node->is_inside_tree()) {
|
if (current_node->is_inside_tree()) {
|
||||||
NodeDock::get_singleton()->set_object(current_node);
|
NodeDock::get_singleton()->set_selection(Vector<Object *>{ current_node });
|
||||||
SceneTreeDock::get_singleton()->set_selected(current_node);
|
SceneTreeDock::get_singleton()->set_selected(current_node);
|
||||||
SceneTreeDock::get_singleton()->set_selection({ current_node });
|
SceneTreeDock::get_singleton()->set_selection({ current_node });
|
||||||
InspectorDock::get_singleton()->update(current_node);
|
InspectorDock::get_singleton()->update(current_node);
|
||||||
@@ -3075,7 +3075,7 @@ void EditorNode::_edit_current(bool p_skip_foreign, bool p_skip_inspector_update
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
NodeDock::get_singleton()->set_object(nullptr);
|
NodeDock::get_singleton()->set_selection(Vector<Object *>());
|
||||||
SceneTreeDock::get_singleton()->set_selected(nullptr);
|
SceneTreeDock::get_singleton()->set_selected(nullptr);
|
||||||
InspectorDock::get_singleton()->update(nullptr);
|
InspectorDock::get_singleton()->update(nullptr);
|
||||||
}
|
}
|
||||||
@@ -3122,8 +3122,15 @@ void EditorNode::_edit_current(bool p_skip_foreign, bool p_skip_inspector_update
|
|||||||
EditorDebuggerNode::get_singleton()->clear_remote_tree_selection();
|
EditorDebuggerNode::get_singleton()->clear_remote_tree_selection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This can be replaced by some casting operator.
|
||||||
|
Vector<Object *> nodes_as_objects;
|
||||||
|
nodes_as_objects.reserve_exact(multi_nodes.size());
|
||||||
|
for (Node *n : multi_nodes) {
|
||||||
|
nodes_as_objects.append(n);
|
||||||
|
}
|
||||||
|
|
||||||
InspectorDock::get_inspector_singleton()->edit(current_obj);
|
InspectorDock::get_inspector_singleton()->edit(current_obj);
|
||||||
NodeDock::get_singleton()->set_object(nullptr);
|
NodeDock::get_singleton()->set_selection(nodes_as_objects);
|
||||||
SceneTreeDock::get_singleton()->set_selected(selected_node);
|
SceneTreeDock::get_singleton()->set_selected(selected_node);
|
||||||
SceneTreeDock::get_singleton()->set_selection(multi_nodes);
|
SceneTreeDock::get_singleton()->set_selection(multi_nodes);
|
||||||
InspectorDock::get_singleton()->update(nullptr);
|
InspectorDock::get_singleton()->update(nullptr);
|
||||||
|
|||||||
@@ -1503,8 +1503,16 @@ void ConnectionsDock::_bind_methods() {
|
|||||||
ClassDB::bind_method("update_tree", &ConnectionsDock::update_tree);
|
ClassDB::bind_method("update_tree", &ConnectionsDock::update_tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionsDock::set_object(Object *p_obj) {
|
void ConnectionsDock::set_selection(const Vector<Object *> &p_objects) {
|
||||||
selected_object = p_obj;
|
if (p_objects.size() != 1) {
|
||||||
|
select_a_node->show();
|
||||||
|
holder->hide();
|
||||||
|
selected_object = nullptr;
|
||||||
|
} else {
|
||||||
|
select_a_node->hide();
|
||||||
|
holder->show();
|
||||||
|
selected_object = p_objects[0];
|
||||||
|
}
|
||||||
is_editing_resource = (Object::cast_to<Resource>(selected_object) != nullptr);
|
is_editing_resource = (Object::cast_to<Resource>(selected_object) != nullptr);
|
||||||
update_tree();
|
update_tree();
|
||||||
}
|
}
|
||||||
@@ -1699,7 +1707,10 @@ void ConnectionsDock::update_tree() {
|
|||||||
ConnectionsDock::ConnectionsDock() {
|
ConnectionsDock::ConnectionsDock() {
|
||||||
set_name(TTR("Signals"));
|
set_name(TTR("Signals"));
|
||||||
|
|
||||||
VBoxContainer *vbc = this;
|
holder = memnew(VBoxContainer);
|
||||||
|
holder->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||||
|
holder->hide();
|
||||||
|
add_child(holder);
|
||||||
|
|
||||||
search_box = memnew(LineEdit);
|
search_box = memnew(LineEdit);
|
||||||
search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
@@ -1707,7 +1718,7 @@ ConnectionsDock::ConnectionsDock() {
|
|||||||
search_box->set_accessibility_name(TTRC("Filter Signals"));
|
search_box->set_accessibility_name(TTRC("Filter Signals"));
|
||||||
search_box->set_clear_button_enabled(true);
|
search_box->set_clear_button_enabled(true);
|
||||||
search_box->connect(SceneStringName(text_changed), callable_mp(this, &ConnectionsDock::_filter_changed));
|
search_box->connect(SceneStringName(text_changed), callable_mp(this, &ConnectionsDock::_filter_changed));
|
||||||
vbc->add_child(search_box);
|
holder->add_child(search_box);
|
||||||
|
|
||||||
tree = memnew(ConnectionsDockTree);
|
tree = memnew(ConnectionsDockTree);
|
||||||
tree->set_accessibility_name(TTRC("Connections"));
|
tree->set_accessibility_name(TTRC("Connections"));
|
||||||
@@ -1716,24 +1727,24 @@ ConnectionsDock::ConnectionsDock() {
|
|||||||
tree->set_select_mode(Tree::SELECT_ROW);
|
tree->set_select_mode(Tree::SELECT_ROW);
|
||||||
tree->set_hide_root(true);
|
tree->set_hide_root(true);
|
||||||
tree->set_column_clip_content(0, true);
|
tree->set_column_clip_content(0, true);
|
||||||
vbc->add_child(tree);
|
holder->add_child(tree);
|
||||||
tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
tree->set_allow_rmb_select(true);
|
tree->set_allow_rmb_select(true);
|
||||||
|
|
||||||
connect_button = memnew(Button);
|
connect_button = memnew(Button);
|
||||||
connect_button->set_accessibility_name(TTRC("Connect"));
|
connect_button->set_accessibility_name(TTRC("Connect"));
|
||||||
HBoxContainer *hb = memnew(HBoxContainer);
|
HBoxContainer *hb = memnew(HBoxContainer);
|
||||||
vbc->add_child(hb);
|
holder->add_child(hb);
|
||||||
hb->add_spacer();
|
hb->add_spacer();
|
||||||
hb->add_child(connect_button);
|
hb->add_child(connect_button);
|
||||||
connect_button->connect(SceneStringName(pressed), callable_mp(this, &ConnectionsDock::_connect_pressed));
|
connect_button->connect(SceneStringName(pressed), callable_mp(this, &ConnectionsDock::_connect_pressed));
|
||||||
|
|
||||||
connect_dialog = memnew(ConnectDialog);
|
connect_dialog = memnew(ConnectDialog);
|
||||||
connect_dialog->set_process_shortcut_input(true);
|
connect_dialog->set_process_shortcut_input(true);
|
||||||
add_child(connect_dialog);
|
holder->add_child(connect_dialog);
|
||||||
|
|
||||||
disconnect_all_dialog = memnew(ConfirmationDialog);
|
disconnect_all_dialog = memnew(ConfirmationDialog);
|
||||||
add_child(disconnect_all_dialog);
|
holder->add_child(disconnect_all_dialog);
|
||||||
disconnect_all_dialog->connect(SceneStringName(confirmed), callable_mp(this, &ConnectionsDock::_disconnect_all));
|
disconnect_all_dialog->connect(SceneStringName(confirmed), callable_mp(this, &ConnectionsDock::_disconnect_all));
|
||||||
disconnect_all_dialog->set_text(TTR("Are you sure you want to remove all connections from this signal?"));
|
disconnect_all_dialog->set_text(TTR("Are you sure you want to remove all connections from this signal?"));
|
||||||
|
|
||||||
@@ -1741,7 +1752,7 @@ ConnectionsDock::ConnectionsDock() {
|
|||||||
class_menu->connect(SceneStringName(id_pressed), callable_mp(this, &ConnectionsDock::_handle_class_menu_option));
|
class_menu->connect(SceneStringName(id_pressed), callable_mp(this, &ConnectionsDock::_handle_class_menu_option));
|
||||||
class_menu->connect("about_to_popup", callable_mp(this, &ConnectionsDock::_class_menu_about_to_popup));
|
class_menu->connect("about_to_popup", callable_mp(this, &ConnectionsDock::_class_menu_about_to_popup));
|
||||||
class_menu->add_item(TTR("Open Documentation"), CLASS_MENU_OPEN_DOCS);
|
class_menu->add_item(TTR("Open Documentation"), CLASS_MENU_OPEN_DOCS);
|
||||||
add_child(class_menu);
|
holder->add_child(class_menu);
|
||||||
|
|
||||||
signal_menu = memnew(PopupMenu);
|
signal_menu = memnew(PopupMenu);
|
||||||
signal_menu->connect(SceneStringName(id_pressed), callable_mp(this, &ConnectionsDock::_handle_signal_menu_option));
|
signal_menu->connect(SceneStringName(id_pressed), callable_mp(this, &ConnectionsDock::_handle_signal_menu_option));
|
||||||
@@ -1751,7 +1762,7 @@ ConnectionsDock::ConnectionsDock() {
|
|||||||
signal_menu->add_item(TTR("Copy Name"), SIGNAL_MENU_COPY_NAME);
|
signal_menu->add_item(TTR("Copy Name"), SIGNAL_MENU_COPY_NAME);
|
||||||
signal_menu->add_separator();
|
signal_menu->add_separator();
|
||||||
signal_menu->add_item(TTR("Open Documentation"), SIGNAL_MENU_OPEN_DOCS);
|
signal_menu->add_item(TTR("Open Documentation"), SIGNAL_MENU_OPEN_DOCS);
|
||||||
add_child(signal_menu);
|
holder->add_child(signal_menu);
|
||||||
|
|
||||||
slot_menu = memnew(PopupMenu);
|
slot_menu = memnew(PopupMenu);
|
||||||
slot_menu->connect(SceneStringName(id_pressed), callable_mp(this, &ConnectionsDock::_handle_slot_menu_option));
|
slot_menu->connect(SceneStringName(id_pressed), callable_mp(this, &ConnectionsDock::_handle_slot_menu_option));
|
||||||
@@ -1759,7 +1770,7 @@ ConnectionsDock::ConnectionsDock() {
|
|||||||
slot_menu->add_item(TTR("Edit..."), SLOT_MENU_EDIT);
|
slot_menu->add_item(TTR("Edit..."), SLOT_MENU_EDIT);
|
||||||
slot_menu->add_item(TTR("Go to Method"), SLOT_MENU_GO_TO_METHOD);
|
slot_menu->add_item(TTR("Go to Method"), SLOT_MENU_GO_TO_METHOD);
|
||||||
slot_menu->add_shortcut(ED_SHORTCUT("connections_editor/disconnect", TTRC("Disconnect"), Key::KEY_DELETE), SLOT_MENU_DISCONNECT);
|
slot_menu->add_shortcut(ED_SHORTCUT("connections_editor/disconnect", TTRC("Disconnect"), Key::KEY_DELETE), SLOT_MENU_DISCONNECT);
|
||||||
add_child(slot_menu);
|
holder->add_child(slot_menu);
|
||||||
|
|
||||||
connect_dialog->connect("connected", callable_mp(this, &ConnectionsDock::_make_or_edit_connection));
|
connect_dialog->connect("connected", callable_mp(this, &ConnectionsDock::_make_or_edit_connection));
|
||||||
tree->connect(SceneStringName(item_selected), callable_mp(this, &ConnectionsDock::_tree_item_selected));
|
tree->connect(SceneStringName(item_selected), callable_mp(this, &ConnectionsDock::_tree_item_selected));
|
||||||
@@ -1767,4 +1778,14 @@ ConnectionsDock::ConnectionsDock() {
|
|||||||
tree->connect(SceneStringName(gui_input), callable_mp(this, &ConnectionsDock::_tree_gui_input));
|
tree->connect(SceneStringName(gui_input), callable_mp(this, &ConnectionsDock::_tree_gui_input));
|
||||||
|
|
||||||
add_theme_constant_override("separation", 3 * EDSCALE);
|
add_theme_constant_override("separation", 3 * EDSCALE);
|
||||||
|
|
||||||
|
select_a_node = memnew(Label);
|
||||||
|
select_a_node->set_focus_mode(FOCUS_ACCESSIBILITY);
|
||||||
|
select_a_node->set_text(TTRC("Select a single node or resource to edit its signals."));
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -237,6 +237,9 @@ class ConnectionsDock : public VBoxContainer {
|
|||||||
SLOT_MENU_DISCONNECT,
|
SLOT_MENU_DISCONNECT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VBoxContainer *holder = nullptr;
|
||||||
|
Label *select_a_node = nullptr;
|
||||||
|
|
||||||
Object *selected_object = nullptr;
|
Object *selected_object = nullptr;
|
||||||
ConnectionsDockTree *tree = nullptr;
|
ConnectionsDockTree *tree = nullptr;
|
||||||
|
|
||||||
@@ -282,7 +285,7 @@ protected:
|
|||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void set_object(Object *p_obj);
|
void set_selection(const Vector<Object *> &p_objects);
|
||||||
void update_tree();
|
void update_tree();
|
||||||
|
|
||||||
ConnectionsDock();
|
ConnectionsDock();
|
||||||
|
|||||||
Reference in New Issue
Block a user