Skip to content

Commit f619ca2

Browse files
committed
Merge pull request godotengine#60143 from Rindbee/better-connection-dialog
Add a flag to make the connection automatically emit the source object.
2 parents b09c70c + 5e2396e commit f619ca2

File tree

6 files changed

+95
-21
lines changed

6 files changed

+95
-21
lines changed

core/object/object.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,6 +1924,7 @@ void Object::_bind_methods() {
19241924
BIND_ENUM_CONSTANT(CONNECT_PERSIST);
19251925
BIND_ENUM_CONSTANT(CONNECT_ONE_SHOT);
19261926
BIND_ENUM_CONSTANT(CONNECT_REFERENCE_COUNTED);
1927+
BIND_ENUM_CONSTANT(CONNECT_APPEND_SOURCE_OBJECT);
19271928
}
19281929

19291930
void Object::set_deferred(const StringName &p_property, const Variant &p_value) {

core/object/object.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -573,10 +573,11 @@ class Object {
573573

574574
enum ConnectFlags {
575575
CONNECT_DEFERRED = 1,
576-
CONNECT_PERSIST = 2, // hint for scene to save this connection
576+
CONNECT_PERSIST = 2, // Hint for scene to save this connection.
577577
CONNECT_ONE_SHOT = 4,
578578
CONNECT_REFERENCE_COUNTED = 8,
579-
CONNECT_INHERITED = 16, // Used in editor builds.
579+
CONNECT_APPEND_SOURCE_OBJECT = 16,
580+
CONNECT_INHERITED = 32, // Used in editor builds.
580581
};
581582

582583
struct Connection {

doc/classes/Object.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,5 +1039,8 @@
10391039
<constant name="CONNECT_REFERENCE_COUNTED" value="8" enum="ConnectFlags">
10401040
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.
10411041
</constant>
1042+
<constant name="CONNECT_APPEND_SOURCE_OBJECT" value="16" enum="ConnectFlags">
1043+
The source object is automatically bound when a [PackedScene] is instantiated. If this flag bit is enabled, the source object will be appended right after the original arguments of the signal.
1044+
</constant>
10421045
</constants>
10431046
</class>

editor/connections_dialog.cpp

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "editor/themes/editor_scale.h"
4747
#include "scene/gui/button.h"
4848
#include "scene/gui/check_box.h"
49+
#include "scene/gui/flow_container.h"
4950
#include "scene/gui/label.h"
5051
#include "scene/gui/line_edit.h"
5152
#include "scene/gui/margin_container.h"
@@ -195,6 +196,8 @@ void ConnectDialog::_unbind_count_changed(double p_count) {
195196
e->set_read_only(p_count > 0);
196197
}
197198
}
199+
200+
append_source->set_disabled(p_count > 0);
198201
}
199202

200203
void ConnectDialog::_method_selected() {
@@ -626,6 +629,10 @@ bool ConnectDialog::get_one_shot() const {
626629
return one_shot->is_pressed();
627630
}
628631

632+
bool ConnectDialog::get_append_source() const {
633+
return !append_source->is_disabled() && append_source->is_pressed();
634+
}
635+
629636
/*
630637
* Returns true if ConnectDialog is being used to edit an existing connection.
631638
*/
@@ -667,14 +674,15 @@ void ConnectDialog::init(const ConnectionData &p_cd, const PackedStringArray &p_
667674

668675
_update_ok_enabled();
669676

670-
bool b_deferred = (p_cd.flags & CONNECT_DEFERRED) == CONNECT_DEFERRED;
671-
bool b_oneshot = (p_cd.flags & CONNECT_ONE_SHOT) == CONNECT_ONE_SHOT;
677+
bool b_deferred = (p_cd.flags & CONNECT_DEFERRED);
678+
bool b_oneshot = (p_cd.flags & CONNECT_ONE_SHOT);
679+
bool b_append_source = (p_cd.flags & CONNECT_APPEND_SOURCE_OBJECT);
672680

673681
deferred->set_pressed(b_deferred);
674682
one_shot->set_pressed(b_oneshot);
683+
append_source->set_pressed(b_append_source);
675684

676685
unbind_count->set_max(p_signal_args.size());
677-
678686
unbind_count->set_value(p_cd.unbinds);
679687
_unbind_count_changed(p_cd.unbinds);
680688

@@ -892,20 +900,23 @@ ConnectDialog::ConnectDialog() {
892900
advanced->set_pressed(EditorSettings::get_singleton()->get_project_metadata("editor_metadata", "use_advanced_connections", false));
893901
advanced->connect(SceneStringName(pressed), callable_mp(this, &ConnectDialog::_advanced_pressed));
894902

895-
HBoxContainer *hbox = memnew(HBoxContainer);
896-
vbc_right->add_child(hbox);
903+
FlowContainer *fc_flags = memnew(FlowContainer);
904+
vbc_right->add_child(fc_flags);
897905

898906
deferred = memnew(CheckBox);
899-
deferred->set_h_size_flags(0);
900907
deferred->set_text(TTR("Deferred"));
901908
deferred->set_tooltip_text(TTR("Defers the signal, storing it in a queue and only firing it at idle time."));
902-
hbox->add_child(deferred);
909+
fc_flags->add_child(deferred);
903910

904911
one_shot = memnew(CheckBox);
905-
one_shot->set_h_size_flags(0);
906912
one_shot->set_text(TTR("One Shot"));
907913
one_shot->set_tooltip_text(TTR("Disconnects the signal after its first emission."));
908-
hbox->add_child(one_shot);
914+
fc_flags->add_child(one_shot);
915+
916+
append_source = memnew(CheckBox);
917+
append_source->set_text(TTRC("Append Source"));
918+
append_source->set_tooltip_text(TTRC("The source object is automatically sent when the signal is emitted."));
919+
fc_flags->add_child(append_source);
909920

910921
cdbinds = memnew(ConnectDialogBinds);
911922

@@ -961,7 +972,8 @@ void ConnectionsDock::_make_or_edit_connection() {
961972
}
962973
bool b_deferred = connect_dialog->get_deferred();
963974
bool b_oneshot = connect_dialog->get_one_shot();
964-
cd.flags = CONNECT_PERSIST | (b_deferred ? CONNECT_DEFERRED : 0) | (b_oneshot ? CONNECT_ONE_SHOT : 0);
975+
bool b_append_source = connect_dialog->get_append_source();
976+
cd.flags = CONNECT_PERSIST | (b_deferred ? CONNECT_DEFERRED : 0) | (b_oneshot ? CONNECT_ONE_SHOT : 0) | (b_append_source ? CONNECT_APPEND_SOURCE_OBJECT : 0);
965977

966978
// If the function is found in target's own script, check the editor setting
967979
// to determine if the script should be opened.
@@ -1003,6 +1015,45 @@ void ConnectionsDock::_make_or_edit_connection() {
10031015
if (add_script_function_request) {
10041016
PackedStringArray script_function_args = connect_dialog->get_signal_args();
10051017
script_function_args.resize(script_function_args.size() - cd.unbinds);
1018+
1019+
// Append the source.
1020+
if (b_append_source) {
1021+
String class_name = cd.source->get_class();
1022+
bool found = false;
1023+
1024+
Ref<Script> source_script = cd.source->get_script();
1025+
if (source_script.is_valid()) {
1026+
found = source_script->has_script_signal(cd.signal);
1027+
if (found) {
1028+
// Check global name in script inheritance chain.
1029+
bool need_check = found;
1030+
Ref<Script> base_script = source_script->get_base_script();
1031+
while (base_script.is_valid()) {
1032+
need_check = base_script->has_script_signal(cd.signal);
1033+
if (!need_check) {
1034+
break;
1035+
}
1036+
source_script = base_script;
1037+
base_script = source_script->get_base_script();
1038+
}
1039+
class_name = source_script->get_global_name();
1040+
}
1041+
}
1042+
1043+
if (!found) {
1044+
while (!class_name.is_empty()) {
1045+
// Search in ClassDB according to the inheritance chain.
1046+
found = ClassDB::has_signal(class_name, cd.signal, true);
1047+
if (found) {
1048+
break;
1049+
}
1050+
class_name = ClassDB::get_parent_class(class_name);
1051+
}
1052+
}
1053+
1054+
script_function_args.push_back("source:" + class_name);
1055+
}
1056+
10061057
for (int i = 0; i < cd.binds.size(); i++) {
10071058
script_function_args.push_back("extra_arg_" + itos(i) + ":" + Variant::get_type_name(cd.binds[i].get_type()));
10081059
}
@@ -1587,6 +1638,9 @@ void ConnectionsDock::update_tree() {
15871638
if (cd.flags & CONNECT_ONE_SHOT) {
15881639
path += " (one-shot)";
15891640
}
1641+
if (cd.flags & CONNECT_APPEND_SOURCE_OBJECT) {
1642+
path += " (source)";
1643+
}
15901644
if (cd.unbinds > 0) {
15911645
path += " unbinds(" + itos(cd.unbinds) + ")";
15921646
} else if (!cd.binds.is_empty()) {

editor/connections_dialog.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ class ConnectDialog : public ConfirmationDialog {
7171
CallableCustomBind *ccb = dynamic_cast<CallableCustomBind *>(p_connection.callable.get_custom());
7272
if (ccb) {
7373
binds = ccb->get_binds();
74+
75+
// The source object may already be bound, ignore it to prevent display of the source object.
76+
if ((flags & CONNECT_APPEND_SOURCE_OBJECT) && (source == binds[0])) {
77+
binds.remove_at(0);
78+
}
79+
7480
base_callable = ccb->get_callable();
7581
}
7682

@@ -130,6 +136,7 @@ class ConnectDialog : public ConfirmationDialog {
130136
OptionButton *type_list = nullptr;
131137
CheckBox *deferred = nullptr;
132138
CheckBox *one_shot = nullptr;
139+
CheckBox *append_source = nullptr;
133140
CheckButton *advanced = nullptr;
134141
Vector<Control *> bind_controls;
135142

@@ -177,6 +184,7 @@ class ConnectDialog : public ConfirmationDialog {
177184

178185
bool get_deferred() const;
179186
bool get_one_shot() const;
187+
bool get_append_source() const;
180188
bool is_editing() const;
181189

182190
virtual void shortcut_input(const Ref<InputEvent> &p_event) override;

scene/resources/packed_scene.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -592,20 +592,21 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
592592
Callable callable(cto, snames[c.method]);
593593
if (c.unbinds > 0) {
594594
callable = callable.unbind(c.unbinds);
595-
} else if (!c.binds.is_empty()) {
596-
Vector<Variant> binds;
597-
if (c.binds.size()) {
598-
binds.resize(c.binds.size());
595+
} else {
596+
Array binds;
597+
if (c.flags & CONNECT_APPEND_SOURCE_OBJECT) {
598+
binds.push_back(cfrom);
599+
}
600+
601+
if (!c.binds.is_empty()) {
599602
for (int j = 0; j < c.binds.size(); j++) {
600-
binds.write[j] = props[c.binds[j]];
603+
binds.push_back(props[c.binds[j]]);
601604
}
602605
}
603606

604-
const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *) * binds.size());
605-
for (int j = 0; j < binds.size(); j++) {
606-
argptrs[j] = &binds[j];
607+
if (!binds.is_empty()) {
608+
callable = callable.bindv(binds);
607609
}
608-
callable = callable.bindp(argptrs, binds.size());
609610
}
610611

611612
cfrom->connect(snames[c.signal], callable, CONNECT_PERSIST | c.flags | (p_edit_state == GEN_EDIT_STATE_MAIN ? 0 : CONNECT_INHERITED));
@@ -1079,6 +1080,12 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, HashMap<String
10791080
CallableCustomBind *ccb = dynamic_cast<CallableCustomBind *>(c.callable.get_custom());
10801081
if (ccb) {
10811082
binds = ccb->get_binds();
1083+
1084+
// The source object may already be bound, ignore it to avoid saving the source object.
1085+
if ((c.flags & CONNECT_APPEND_SOURCE_OBJECT) && (p_node == binds[0])) {
1086+
binds.remove_at(0);
1087+
}
1088+
10821089
base_callable = ccb->get_callable();
10831090
}
10841091

0 commit comments

Comments
 (0)