From aac14cc0165c948764d5d7f232886f3526a758b9 Mon Sep 17 00:00:00 2001 From: Rindbee Date: Mon, 11 Apr 2022 17:37:23 +0800 Subject: [PATCH] Add a flag to make the connection automatically emit the source object. Mainly used to improve the connection dialog. --- core/object/object.cpp | 14 ++++++++++++ core/object/object.h | 3 ++- doc/classes/Object.xml | 3 +++ editor/connections_dialog.cpp | 43 +++++++++++++++++++++++++++++++++-- editor/connections_dialog.h | 2 ++ 5 files changed, 62 insertions(+), 3 deletions(-) diff --git a/core/object/object.cpp b/core/object/object.cpp index 57aa1339ece0..1eab6b970cf8 100644 --- a/core/object/object.cpp +++ b/core/object/object.cpp @@ -1024,6 +1024,7 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int OBJ_DEBUG_LOCK Error err = OK; + Variant appended_self; for (int i = 0; i < ssize; i++) { const Connection &c = slot_map.getv(i).conn; @@ -1037,6 +1038,18 @@ Error Object::emit_signalp(const StringName &p_name, const Variant **p_args, int const Variant **args = p_args; int argc = p_argcount; + if (c.flags & CONNECT_APPEND_SOURCE_OBJECT) { + argc += 1; + args = (const Variant **)alloca(sizeof(Variant *) * argc); + for (int j = 0; j < p_argcount; j++) { + args[j] = (const Variant *)p_args[j]; + } + if (unlikely(appended_self.get_type() == Variant::NIL)) { + appended_self = this; + } + args[p_argcount] = &appended_self; + } + if (c.flags & CONNECT_DEFERRED) { MessageQueue::get_singleton()->push_callablep(c.callable, args, argc, true); } else { @@ -1582,6 +1595,7 @@ void Object::_bind_methods() { BIND_ENUM_CONSTANT(CONNECT_PERSIST); BIND_ENUM_CONSTANT(CONNECT_ONE_SHOT); BIND_ENUM_CONSTANT(CONNECT_REFERENCE_COUNTED); + BIND_ENUM_CONSTANT(CONNECT_APPEND_SOURCE_OBJECT); } void Object::set_deferred(const StringName &p_property, const Variant &p_value) { diff --git a/core/object/object.h b/core/object/object.h index 5ec69a371b0b..ec3fe0f58625 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -553,10 +553,11 @@ class Object { public: enum ConnectFlags { CONNECT_DEFERRED = 1, - CONNECT_PERSIST = 2, // hint for scene to save this connection + CONNECT_PERSIST = 2, // Hint for scene to save this connection CONNECT_ONE_SHOT = 4, CONNECT_REFERENCE_COUNTED = 8, CONNECT_INHERITED = 16, // Used in editor builds. + CONNECT_APPEND_SOURCE_OBJECT = 32, // Hint for the connection dialog to append the source object as the last call argument. }; struct Connection { diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index 46c1229bb316..e6329cab3f0f 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -955,5 +955,8 @@ Reference-counted connections can be assigned to the same [Callable] multiple times. Each disconnection decreases the internal counter. The signal fully disconnects only when the counter reaches 0. + + Automatically sends the source object when emitting the signal. Mainly used to improve the usability of the connection dialog. If this flag bit is enabled, the source object will be appended right after the original arguments of the signal. + diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index befe84f31156..8adf4aa22eb9 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -186,6 +186,8 @@ void ConnectDialog::_unbind_count_changed(double p_count) { e->set_read_only(p_count > 0); } } + + append_source->set_disabled(p_count > 0); } void ConnectDialog::_method_selected() { @@ -532,6 +534,10 @@ bool ConnectDialog::get_one_shot() const { return one_shot->is_pressed(); } +bool ConnectDialog::get_append_source() const { + return !append_source->is_disabled() && append_source->is_pressed(); +} + /* * Returns true if ConnectDialog is being used to edit an existing connection. */ @@ -563,12 +569,13 @@ void ConnectDialog::init(const ConnectionData &p_cd, const PackedStringArray &p_ bool b_deferred = (p_cd.flags & CONNECT_DEFERRED) == CONNECT_DEFERRED; bool b_oneshot = (p_cd.flags & CONNECT_ONE_SHOT) == CONNECT_ONE_SHOT; + bool b_append_source = (p_cd.flags & CONNECT_APPEND_SOURCE_OBJECT) == CONNECT_APPEND_SOURCE_OBJECT; deferred->set_pressed(b_deferred); one_shot->set_pressed(b_oneshot); + append_source->set_pressed(b_append_source); unbind_count->set_max(p_signal_args.size()); - unbind_count->set_value(p_cd.unbinds); _unbind_count_changed(p_cd.unbinds); @@ -783,6 +790,12 @@ ConnectDialog::ConnectDialog() { one_shot->set_tooltip_text(TTR("Disconnects the signal after its first emission.")); hbox->add_child(one_shot); + append_source = memnew(CheckBox); + append_source->set_h_size_flags(0); + append_source->set_text(TTR("Append source")); + append_source->set_tooltip_text(TTR("The source object is automatically sent when the signal is emitted.")); + vbc_right->add_child(append_source); + cdbinds = memnew(ConnectDialogBinds); error = memnew(AcceptDialog); @@ -855,7 +868,8 @@ void ConnectionsDock::_make_or_edit_connection() { } bool b_deferred = connect_dialog->get_deferred(); bool b_oneshot = connect_dialog->get_one_shot(); - cd.flags = CONNECT_PERSIST | (b_deferred ? CONNECT_DEFERRED : 0) | (b_oneshot ? CONNECT_ONE_SHOT : 0); + bool b_append_source = connect_dialog->get_append_source(); + cd.flags = CONNECT_PERSIST | (b_deferred ? CONNECT_DEFERRED : 0) | (b_oneshot ? CONNECT_ONE_SHOT : 0) | (b_append_source ? CONNECT_APPEND_SOURCE_OBJECT : 0); // Conditions to add function: must have a script and must not have the method already // (in the class, the script itself, or inherited). @@ -888,6 +902,28 @@ void ConnectionsDock::_make_or_edit_connection() { if (add_script_function) { PackedStringArray script_function_args = connect_dialog->get_signal_args(); script_function_args.resize(script_function_args.size() - cd.unbinds); + + // Append the source. + if (b_append_source) { + String class_name = cd.source->get_class(); + bool found = false; + + Ref