Serialization of Callable now works with bind and unbind at the same time

Removed exclusivity between unbind and bind in many places, both on display elements, connection dock and within serialization.

A signal can now be connected with both unbound and bound arguments through the editor
This commit is contained in:
Aria
2025-07-18 01:35:59 +02:00
parent 2a9ff39264
commit caa2a388bb
3 changed files with 45 additions and 57 deletions

View File

@ -185,22 +185,6 @@ void ConnectDialog::_focus_currently_connected() {
tree->set_selected(source); tree->set_selected(source);
} }
void ConnectDialog::_unbind_count_changed(double p_count) {
for (Control *control : bind_controls) {
BaseButton *b = Object::cast_to<BaseButton>(control);
if (b) {
b->set_disabled(p_count > 0);
}
EditorInspector *e = Object::cast_to<EditorInspector>(control);
if (e) {
e->set_read_only(p_count > 0);
}
}
append_source->set_disabled(p_count > 0);
}
void ConnectDialog::_method_selected() { void ConnectDialog::_method_selected() {
TreeItem *selected_item = method_tree->get_selected(); TreeItem *selected_item = method_tree->get_selected();
dst_method->set_text(selected_item->get_metadata(0)); dst_method->set_text(selected_item->get_metadata(0));
@ -295,10 +279,9 @@ List<MethodInfo> ConnectDialog::_filter_method_list(const List<MethodInfo> &p_me
PropertyInfo pi = p_signal.arguments[i]; PropertyInfo pi = p_signal.arguments[i];
effective_args.push_back(Pair(pi.type, pi.class_name)); effective_args.push_back(Pair(pi.type, pi.class_name));
} }
if (unbind == 0) {
for (const Variant &variant : get_binds()) { for (const Variant &variant : get_binds()) {
effective_args.push_back(Pair(variant.get_type(), StringName())); effective_args.push_back(Pair(variant.get_type(), StringName()));
}
} }
for (const MethodInfo &mi : p_methods) { for (const MethodInfo &mi : p_methods) {
@ -687,7 +670,6 @@ void ConnectDialog::init(const ConnectionData &p_cd, const PackedStringArray &p_
unbind_count->set_max(p_signal_args.size()); unbind_count->set_max(p_signal_args.size());
unbind_count->set_value(p_cd.unbinds); unbind_count->set_value(p_cd.unbinds);
_unbind_count_changed(p_cd.unbinds);
cdbinds->params.clear(); cdbinds->params.clear();
cdbinds->params = p_cd.binds; cdbinds->params = p_cd.binds;
@ -872,7 +854,6 @@ ConnectDialog::ConnectDialog() {
unbind_count = memnew(SpinBox); unbind_count = memnew(SpinBox);
unbind_count->set_tooltip_text(TTR("Allows to drop arguments sent by signal emitter.")); unbind_count->set_tooltip_text(TTR("Allows to drop arguments sent by signal emitter."));
unbind_count->set_accessibility_name(TTRC("Unbind Signal Arguments:")); unbind_count->set_accessibility_name(TTRC("Unbind Signal Arguments:"));
unbind_count->connect(SceneStringName(value_changed), callable_mp(this, &ConnectDialog::_unbind_count_changed));
vbc_right->add_margin_child(TTR("Unbind Signal Arguments:"), unbind_count); vbc_right->add_margin_child(TTR("Unbind Signal Arguments:"), unbind_count);
@ -963,9 +944,8 @@ void ConnectionsDock::_make_or_edit_connection() {
cd.signal = connect_dialog->get_signal_name(); cd.signal = connect_dialog->get_signal_name();
cd.method = connect_dialog->get_dst_method_name(); cd.method = connect_dialog->get_dst_method_name();
cd.unbinds = connect_dialog->get_unbinds(); cd.unbinds = connect_dialog->get_unbinds();
if (cd.unbinds == 0) { cd.binds = connect_dialog->get_binds();
cd.binds = connect_dialog->get_binds();
}
bool b_deferred = connect_dialog->get_deferred(); bool b_deferred = connect_dialog->get_deferred();
bool b_oneshot = connect_dialog->get_one_shot(); bool b_oneshot = connect_dialog->get_one_shot();
bool b_append_source = connect_dialog->get_append_source(); bool b_append_source = connect_dialog->get_append_source();
@ -1639,7 +1619,8 @@ void ConnectionsDock::update_tree() {
} }
if (cd.unbinds > 0) { if (cd.unbinds > 0) {
path += " unbinds(" + itos(cd.unbinds) + ")"; path += " unbinds(" + itos(cd.unbinds) + ")";
} else if (!cd.binds.is_empty()) { }
if (!cd.binds.is_empty()) {
path += " binds("; path += " binds(";
for (int i = 0; i < cd.binds.size(); i++) { for (int i = 0; i < cd.binds.size(); i++) {
if (i > 0) { if (i > 0) {

View File

@ -72,20 +72,22 @@ public:
CallableCustomBind *ccb = dynamic_cast<CallableCustomBind *>(p_connection.callable.get_custom()); CallableCustomBind *ccb = dynamic_cast<CallableCustomBind *>(p_connection.callable.get_custom());
if (ccb) { if (ccb) {
binds = ccb->get_binds(); binds = ccb->get_binds();
unbinds = ccb->get_unbound_arguments_count();
// The source object may already be bound, ignore it to prevent display of the source object.
if ((flags & CONNECT_APPEND_SOURCE_OBJECT) && (source == binds[0])) {
binds.remove_at(0);
}
base_callable = ccb->get_callable(); base_callable = ccb->get_callable();
} }
CallableCustomUnbind *ccu = dynamic_cast<CallableCustomUnbind *>(p_connection.callable.get_custom()); CallableCustomUnbind *ccu = dynamic_cast<CallableCustomUnbind *>(p_connection.callable.get_custom());
if (ccu) { if (ccu) {
ccu->get_bound_arguments(binds);
unbinds = ccu->get_unbinds(); unbinds = ccu->get_unbinds();
base_callable = ccu->get_callable(); base_callable = ccu->get_callable();
} }
// The source object may already be bound, ignore it to prevent display of the source object.
if ((flags & CONNECT_APPEND_SOURCE_OBJECT) && (source == binds[0])) {
binds.remove_at(0);
}
} else { } else {
base_callable = p_connection.callable; base_callable = p_connection.callable;
} }
@ -93,17 +95,21 @@ public:
} }
Callable get_callable() const { Callable get_callable() const {
if (unbinds > 0) { Callable callable = Callable(target, method);
return Callable(target, method).unbind(unbinds);
} else if (!binds.is_empty()) { if (!binds.is_empty()) {
const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *) * binds.size()); const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *) * binds.size());
for (int i = 0; i < binds.size(); i++) { for (int i = 0; i < binds.size(); i++) {
argptrs[i] = &binds[i]; argptrs[i] = &binds[i];
} }
return Callable(target, method).bindp(argptrs, binds.size()); callable = callable.bindp(argptrs, binds.size());
} else {
return Callable(target, method);
} }
if (unbinds > 0) {
callable = callable.unbind(unbinds);
}
return callable;
} }
}; };

View File

@ -593,23 +593,22 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const {
} }
Callable callable(cto, snames[c.method]); Callable callable(cto, snames[c.method]);
Array binds;
if (c.flags & CONNECT_APPEND_SOURCE_OBJECT) {
binds.push_back(cfrom);
}
for (int bind : c.binds) {
binds.push_back(props[bind]);
}
if (!binds.is_empty()) {
callable = callable.bindv(binds);
}
if (c.unbinds > 0) { if (c.unbinds > 0) {
callable = callable.unbind(c.unbinds); callable = callable.unbind(c.unbinds);
} else {
Array binds;
if (c.flags & CONNECT_APPEND_SOURCE_OBJECT) {
binds.push_back(cfrom);
}
if (!c.binds.is_empty()) {
for (int j = 0; j < c.binds.size(); j++) {
binds.push_back(props[c.binds[j]]);
}
}
if (!binds.is_empty()) {
callable = callable.bindv(binds);
}
} }
cfrom->connect(snames[c.signal], callable, CONNECT_PERSIST | c.flags | (p_edit_state == GEN_EDIT_STATE_MAIN ? 0 : CONNECT_INHERITED)); cfrom->connect(snames[c.signal], callable, CONNECT_PERSIST | c.flags | (p_edit_state == GEN_EDIT_STATE_MAIN ? 0 : CONNECT_INHERITED));
@ -1083,20 +1082,22 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, HashMap<String
CallableCustomBind *ccb = dynamic_cast<CallableCustomBind *>(c.callable.get_custom()); CallableCustomBind *ccb = dynamic_cast<CallableCustomBind *>(c.callable.get_custom());
if (ccb) { if (ccb) {
binds = ccb->get_binds(); binds = ccb->get_binds();
unbinds = ccb->get_unbound_arguments_count();
// The source object may already be bound, ignore it to avoid saving the source object.
if ((c.flags & CONNECT_APPEND_SOURCE_OBJECT) && (p_node == binds[0])) {
binds.remove_at(0);
}
base_callable = ccb->get_callable(); base_callable = ccb->get_callable();
} }
CallableCustomUnbind *ccu = dynamic_cast<CallableCustomUnbind *>(c.callable.get_custom()); CallableCustomUnbind *ccu = dynamic_cast<CallableCustomUnbind *>(c.callable.get_custom());
if (ccu) { if (ccu) {
ccu->get_bound_arguments(binds);
unbinds = ccu->get_unbinds(); unbinds = ccu->get_unbinds();
base_callable = ccu->get_callable(); base_callable = ccu->get_callable();
} }
// The source object may already be bound, ignore it to avoid saving the source object.
if ((c.flags & CONNECT_APPEND_SOURCE_OBJECT) && (p_node == binds[0])) {
binds.remove_at(0);
}
} else { } else {
base_callable = c.callable; base_callable = c.callable;
} }