From caa2a388bb6a7b6aa72e3f8ea8798c672b82f3a2 Mon Sep 17 00:00:00 2001 From: Aria <105683700+AriaTheCurseling@users.noreply.github.com> Date: Fri, 18 Jul 2025 01:35:59 +0200 Subject: [PATCH] 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 --- editor/scene/connections_dialog.cpp | 33 +++++------------------ editor/scene/connections_dialog.h | 28 ++++++++++++-------- scene/resources/packed_scene.cpp | 41 +++++++++++++++-------------- 3 files changed, 45 insertions(+), 57 deletions(-) diff --git a/editor/scene/connections_dialog.cpp b/editor/scene/connections_dialog.cpp index f5b0f8b49a0..1fd2a39e89a 100644 --- a/editor/scene/connections_dialog.cpp +++ b/editor/scene/connections_dialog.cpp @@ -185,22 +185,6 @@ void ConnectDialog::_focus_currently_connected() { tree->set_selected(source); } -void ConnectDialog::_unbind_count_changed(double p_count) { - for (Control *control : bind_controls) { - BaseButton *b = Object::cast_to(control); - if (b) { - b->set_disabled(p_count > 0); - } - - EditorInspector *e = Object::cast_to(control); - if (e) { - e->set_read_only(p_count > 0); - } - } - - append_source->set_disabled(p_count > 0); -} - void ConnectDialog::_method_selected() { TreeItem *selected_item = method_tree->get_selected(); dst_method->set_text(selected_item->get_metadata(0)); @@ -295,10 +279,9 @@ List ConnectDialog::_filter_method_list(const List &p_me PropertyInfo pi = p_signal.arguments[i]; effective_args.push_back(Pair(pi.type, pi.class_name)); } - if (unbind == 0) { - for (const Variant &variant : get_binds()) { - effective_args.push_back(Pair(variant.get_type(), StringName())); - } + + for (const Variant &variant : get_binds()) { + effective_args.push_back(Pair(variant.get_type(), StringName())); } 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_value(p_cd.unbinds); - _unbind_count_changed(p_cd.unbinds); cdbinds->params.clear(); cdbinds->params = p_cd.binds; @@ -872,7 +854,6 @@ ConnectDialog::ConnectDialog() { unbind_count = memnew(SpinBox); 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->connect(SceneStringName(value_changed), callable_mp(this, &ConnectDialog::_unbind_count_changed)); 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.method = connect_dialog->get_dst_method_name(); 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_oneshot = connect_dialog->get_one_shot(); bool b_append_source = connect_dialog->get_append_source(); @@ -1639,7 +1619,8 @@ void ConnectionsDock::update_tree() { } if (cd.unbinds > 0) { path += " unbinds(" + itos(cd.unbinds) + ")"; - } else if (!cd.binds.is_empty()) { + } + if (!cd.binds.is_empty()) { path += " binds("; for (int i = 0; i < cd.binds.size(); i++) { if (i > 0) { diff --git a/editor/scene/connections_dialog.h b/editor/scene/connections_dialog.h index ae129b25204..363a857cf6f 100644 --- a/editor/scene/connections_dialog.h +++ b/editor/scene/connections_dialog.h @@ -72,20 +72,22 @@ public: CallableCustomBind *ccb = dynamic_cast(p_connection.callable.get_custom()); if (ccb) { binds = ccb->get_binds(); - - // 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); - } + unbinds = ccb->get_unbound_arguments_count(); base_callable = ccb->get_callable(); } CallableCustomUnbind *ccu = dynamic_cast(p_connection.callable.get_custom()); if (ccu) { + ccu->get_bound_arguments(binds); unbinds = ccu->get_unbinds(); 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 { base_callable = p_connection.callable; } @@ -93,17 +95,21 @@ public: } Callable get_callable() const { - if (unbinds > 0) { - return Callable(target, method).unbind(unbinds); - } else if (!binds.is_empty()) { + Callable callable = Callable(target, method); + + if (!binds.is_empty()) { const Variant **argptrs = (const Variant **)alloca(sizeof(Variant *) * binds.size()); for (int i = 0; i < binds.size(); i++) { argptrs[i] = &binds[i]; } - return Callable(target, method).bindp(argptrs, binds.size()); - } else { - return Callable(target, method); + callable = callable.bindp(argptrs, binds.size()); } + + if (unbinds > 0) { + callable = callable.unbind(unbinds); + } + + return callable; } }; diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 786b551b89c..33c2d6b524b 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -593,23 +593,22 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { } 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) { 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)); @@ -1083,20 +1082,22 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, HashMap(c.callable.get_custom()); if (ccb) { binds = ccb->get_binds(); - - // 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); - } + unbinds = ccb->get_unbound_arguments_count(); base_callable = ccb->get_callable(); } CallableCustomUnbind *ccu = dynamic_cast(c.callable.get_custom()); if (ccu) { + ccu->get_bound_arguments(binds); unbinds = ccu->get_unbinds(); 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 { base_callable = c.callable; }