Skip to content

Commit

Permalink
Connect signal by dragging on SceneTree item
Browse files Browse the repository at this point in the history
  • Loading branch information
jmb462 committed Oct 1, 2023
1 parent 0ca8542 commit 906413b
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 12 deletions.
69 changes: 58 additions & 11 deletions editor/connections_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include "scene/gui/option_button.h"
#include "scene/gui/popup_menu.h"
#include "scene/gui/spin_box.h"
#include "scene/gui/texture_rect.h"
#include "scene/resources/packed_scene.h"

static Node *_find_first_script(Node *p_root, Node *p_node) {
Expand Down Expand Up @@ -148,7 +149,7 @@ void ConnectDialog::ok_pressed() {
return;
}
}
emit_signal(SNAME("connected"));
emit_signal(SNAME("connected"), get_dst_path(), get_signal_name(), get_dst_method_name(), get_unbinds(), get_deferred(), get_one_shot());
hide();
}

Expand Down Expand Up @@ -876,27 +877,38 @@ void ConnectionsDock::_filter_changed(const String &p_text) {
update_tree();
}

void ConnectionsDock::_signal_dropped(const NodePath p_dest_path) {
Node *target = selected_node->get_node(p_dest_path);
ERR_FAIL_NULL(target);
TreeItem *item = tree->get_selected();
if (!item || !selected_node) {
return;
}
String signal_name = item->get_metadata(0).get("name");
String method = ConnectDialog::generate_method_callback_name(selected_node, signal_name, target);
_make_or_edit_connection(p_dest_path, signal_name, method, 0, false, false);
}

/*
* Post-ConnectDialog callback for creating/editing connections.
* Creates or edits connections based on state of the ConnectDialog when "Connect" is pressed.
* Callback method for creating/editing connections.
* Creates or edits connections when ConnectDialog "Connect" is pressed or signal dragged on SceneTree.
*/
void ConnectionsDock::_make_or_edit_connection() {
NodePath dst_path = connect_dialog->get_dst_path();
Node *target = selected_node->get_node(dst_path);
void ConnectionsDock::_make_or_edit_connection(const NodePath p_dest_path, const StringName p_signal, const StringName p_method, int p_unbinds, bool p_deferred, bool p_one_shot) {
Node *target = selected_node->get_node(p_dest_path);
ERR_FAIL_NULL(target);

ConnectDialog::ConnectionData cd;
cd.source = connect_dialog->get_source();
cd.source = selected_node;
cd.target = target;
cd.signal = connect_dialog->get_signal_name();
cd.method = connect_dialog->get_dst_method_name();
cd.unbinds = connect_dialog->get_unbinds();
cd.signal = p_signal;
cd.method = p_method;
cd.unbinds = p_unbinds;
if (cd.unbinds == 0) {
cd.binds = connect_dialog->get_binds();
}
bool b_deferred = connect_dialog->get_deferred();

Check failure on line 909 in editor/connections_dialog.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor w/ Mono (target=editor)

unused variable 'b_deferred' [-Werror=unused-variable]

Check failure on line 909 in editor/connections_dialog.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with doubles and GCC sanitizers (target=editor, tests=yes, dev_build=yes, scu_build=yes, precision=double, use_asan=yes, use_ubsan=yes, linker=gold)

unused variable 'b_deferred' [-Werror=unused-variable]

Check failure on line 909 in editor/connections_dialog.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with clang sanitizers (target=editor, tests=yes, dev_build=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes, linker=lld)

unused variable 'b_deferred' [-Werror,-Wunused-variable]

Check failure on line 909 in editor/connections_dialog.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with ThreadSanitizer (target=editor, tests=yes, dev_build=yes, use_tsan=yes, use_llvm=yes, linker=lld)

unused variable 'b_deferred' [-Werror,-Wunused-variable]

Check warning on line 909 in editor/connections_dialog.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Editor (target=editor, tests=yes)

'b_deferred': local variable is initialized but not referenced
bool b_oneshot = connect_dialog->get_one_shot();

Check failure on line 910 in editor/connections_dialog.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor w/ Mono (target=editor)

unused variable 'b_oneshot' [-Werror=unused-variable]

Check failure on line 910 in editor/connections_dialog.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with doubles and GCC sanitizers (target=editor, tests=yes, dev_build=yes, scu_build=yes, precision=double, use_asan=yes, use_ubsan=yes, linker=gold)

unused variable 'b_oneshot' [-Werror=unused-variable]

Check failure on line 910 in editor/connections_dialog.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with clang sanitizers (target=editor, tests=yes, dev_build=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes, linker=lld)

unused variable 'b_oneshot' [-Werror,-Wunused-variable]

Check failure on line 910 in editor/connections_dialog.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor with ThreadSanitizer (target=editor, tests=yes, dev_build=yes, use_tsan=yes, use_llvm=yes, linker=lld)

unused variable 'b_oneshot' [-Werror,-Wunused-variable]

Check failure on line 910 in editor/connections_dialog.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Editor (target=editor, tests=yes)

the following warning is treated as an error

Check warning on line 910 in editor/connections_dialog.cpp

View workflow job for this annotation

GitHub Actions / 🏁 Windows / Editor (target=editor, tests=yes)

'b_oneshot': local variable is initialized but not referenced
cd.flags = CONNECT_PERSIST | (b_deferred ? CONNECT_DEFERRED : 0) | (b_oneshot ? CONNECT_ONE_SHOT : 0);
cd.flags = CONNECT_PERSIST | (p_deferred ? CONNECT_DEFERRED : 0) | (p_one_shot ? CONNECT_ONE_SHOT : 0);

// Conditions to add function: must have a script and must not have the method already
// (in the class, the script itself, or inherited).
Expand Down Expand Up @@ -1272,6 +1284,37 @@ void ConnectionsDock::_close() {
hide();
}

Variant ConnectionsDock::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
TreeItem *item_selected = tree->get_selected();

if (!item_selected) {
return Variant();
}

String signal_name = Dictionary(item_selected->get_metadata(0)).get("name", "");

if (signal_name.is_empty()) {
return Variant();
}

Ref<Texture2D> icon = Control::get_theme_icon(SNAME("Signal"), SNAME("EditorIcons"));

HBoxContainer *hb = memnew(HBoxContainer);
TextureRect *tf = memnew(TextureRect);
tf->set_texture(icon);
tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
hb->add_child(tf);
Label *label = memnew(Label(item_selected->get_text(0)));
hb->add_child(label);
set_drag_preview(hb);

Dictionary drag_data;
drag_data["type"] = "signal";
drag_data["signal"] = signal_name;

return drag_data;
}

void ConnectionsDock::_connect_pressed() {
TreeItem *item = tree->get_selected();
if (!item) {
Expand Down Expand Up @@ -1314,6 +1357,7 @@ void ConnectionsDock::_notification(int p_what) {

void ConnectionsDock::_bind_methods() {
ClassDB::bind_method("update_tree", &ConnectionsDock::update_tree);
ClassDB::bind_method(D_METHOD("_get_drag_data_fw"), &ConnectionsDock::get_drag_data_fw);
}

void ConnectionsDock::set_node(Node *p_node) {
Expand Down Expand Up @@ -1558,6 +1602,9 @@ ConnectionsDock::ConnectionsDock() {
vbc->add_child(tree);
tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
tree->set_allow_rmb_select(true);
tree->set_drag_forwarding(callable_mp(this, &ConnectionsDock::get_drag_data_fw).bind(tree), Callable(), Callable());

SceneTreeDock::get_singleton()->get_tree_editor()->connect("signal_dropped", callable_mp(this, &ConnectionsDock::_signal_dropped));

connect_button = memnew(Button);
HBoxContainer *hb = memnew(HBoxContainer);
Expand Down
7 changes: 6 additions & 1 deletion editor/connections_dialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#define CONNECTIONS_DIALOG_H

#include "scene/gui/check_button.h"
#include "scene/gui/control.h"
#include "scene/gui/dialogs.h"
#include "scene/gui/tree.h"

Expand All @@ -45,6 +46,7 @@ class OptionButton;
class PopupMenu;
class SceneTreeEditor;
class SpinBox;
class TextureRect;

class ConnectDialog : public ConfirmationDialog {
GDCLASS(ConnectDialog, ConfirmationDialog);
Expand Down Expand Up @@ -234,8 +236,9 @@ class ConnectionsDock : public VBoxContainer {
HashMap<StringName, HashMap<StringName, String>> descr_cache;

void _filter_changed(const String &p_text);
void _signal_dropped(const NodePath p_dest_path);

void _make_or_edit_connection();
void _make_or_edit_connection(const NodePath p_dest_path, const StringName p_signal, const StringName p_method, int p_unbinds, bool p_deferred, bool p_one_shot);
void _connect(const ConnectDialog::ConnectionData &p_cd);
void _disconnect(const ConnectDialog::ConnectionData &p_cd);
void _disconnect_all();
Expand All @@ -258,6 +261,8 @@ class ConnectionsDock : public VBoxContainer {
void _rmb_pressed(const Ref<InputEvent> &p_event);
void _close();

Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);

protected:
void _connect_pressed();
void _notification(int p_what);
Expand Down
15 changes: 15 additions & 0 deletions editor/gui/scene_tree_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1336,6 +1336,16 @@ bool SceneTreeEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_d
}
}

if (String(d["type"]) == "signal") {
NodePath np = item->get_metadata(0);
Node *n = get_node(np);
if (!n || !n->get_script()) {
return false;
}
tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM);
return true;
}

return String(d["type"]) == "nodes" && filter.is_empty();
}

Expand Down Expand Up @@ -1386,6 +1396,10 @@ void SceneTreeEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data,
}
}
}

if (String(d["type"]) == "signal") {
emit_signal(SNAME("signal_dropped"), np);
}
}

void SceneTreeEditor::_empty_clicked(const Vector2 &p_pos, MouseButton p_button) {
Expand Down Expand Up @@ -1443,6 +1457,7 @@ void SceneTreeEditor::_bind_methods() {
ADD_SIGNAL(MethodInfo("nodes_rearranged", PropertyInfo(Variant::ARRAY, "paths"), PropertyInfo(Variant::NODE_PATH, "to_path"), PropertyInfo(Variant::INT, "type")));
ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files"), PropertyInfo(Variant::NODE_PATH, "to_path"), PropertyInfo(Variant::INT, "type")));
ADD_SIGNAL(MethodInfo("script_dropped", PropertyInfo(Variant::STRING, "file"), PropertyInfo(Variant::NODE_PATH, "to_path")));
ADD_SIGNAL(MethodInfo("signal_dropped", PropertyInfo(Variant::NODE_PATH, "to_path")));
ADD_SIGNAL(MethodInfo("rmb_pressed", PropertyInfo(Variant::VECTOR2, "position")));

ADD_SIGNAL(MethodInfo("open"));
Expand Down

0 comments on commit 906413b

Please sign in to comment.