diff options
-rw-r--r-- | core/variant/callable_bind.h | 6 | ||||
-rw-r--r-- | doc/classes/SceneState.xml | 7 | ||||
-rw-r--r-- | editor/connections_dialog.cpp | 98 | ||||
-rw-r--r-- | editor/connections_dialog.h | 49 | ||||
-rw-r--r-- | editor/inspector_dock.h | 1 | ||||
-rw-r--r-- | editor/node_dock.cpp | 1 | ||||
-rw-r--r-- | editor/node_dock.h | 3 | ||||
-rw-r--r-- | editor/scene_tree_dock.h | 1 | ||||
-rw-r--r-- | scene/resources/packed_scene.cpp | 63 | ||||
-rw-r--r-- | scene/resources/packed_scene.h | 4 | ||||
-rw-r--r-- | scene/resources/resource_format_text.cpp | 11 |
11 files changed, 184 insertions, 60 deletions
diff --git a/core/variant/callable_bind.h b/core/variant/callable_bind.h index feb40d1de9..1cfb943678 100644 --- a/core/variant/callable_bind.h +++ b/core/variant/callable_bind.h @@ -51,6 +51,9 @@ public: virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const; virtual const Callable *get_base_comparator() const; + Callable get_callable() { return callable; } + Vector<Variant> get_binds() { return binds; } + CallableCustomBind(const Callable &p_callable, const Vector<Variant> &p_binds); virtual ~CallableCustomBind(); }; @@ -72,6 +75,9 @@ public: virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const; virtual const Callable *get_base_comparator() const; + Callable get_callable() { return callable; } + int get_unbinds() { return argcount; } + CallableCustomUnbind(const Callable &p_callable, int p_argcount); virtual ~CallableCustomUnbind(); }; diff --git a/doc/classes/SceneState.xml b/doc/classes/SceneState.xml index 1c3bac9270..b29cf0d968 100644 --- a/doc/classes/SceneState.xml +++ b/doc/classes/SceneState.xml @@ -59,6 +59,13 @@ Returns the path to the node that owns the method connected to the signal at [code]idx[/code], relative to the root node. </description> </method> + <method name="get_connection_unbinds" qualifiers="const"> + <return type="int" /> + <argument index="0" name="idx" type="int" /> + <description> + Returns the number of unbound parameters for the signal at [code]idx[/code]. + </description> + </method> <method name="get_node_count" qualifiers="const"> <return type="int" /> <description> diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index c773f51342..fafd2bb195 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -38,6 +38,7 @@ #include "plugins/script_editor_plugin.h" #include "scene/gui/label.h" #include "scene/gui/popup_menu.h" +#include "scene/gui/spin_box.h" static Node *_find_first_script(Node *p_root, Node *p_node) { if (p_node != p_root && p_node->get_owner() != p_root) { @@ -164,6 +165,20 @@ void ConnectDialog::_tree_node_selected() { _update_ok_enabled(); } +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); + } + } +} + /* * Adds a new parameter bind to connection. */ @@ -305,6 +320,10 @@ void ConnectDialog::set_dst_method(const StringName &p_method) { dst_method->set_text(p_method); } +int ConnectDialog::get_unbinds() const { + return int(unbind_count->get_value()); +} + Vector<Variant> ConnectDialog::get_binds() const { return cdbinds->params; } @@ -350,6 +369,8 @@ void ConnectDialog::init(ConnectionData c, bool bEdit) { deferred->set_pressed(bDeferred); oneshot->set_pressed(bOneshot); + unbind_count->set_value(c.unbinds); + _unbind_count_changed(c.unbinds); cdbinds->params.clear(); cdbinds->params = c.binds; @@ -449,23 +470,33 @@ ConnectDialog::ConnectDialog() { type_list->add_item("Transform3D", Variant::TRANSFORM3D); type_list->add_item("Color", Variant::COLOR); type_list->select(0); + bind_controls.push_back(type_list); Button *add_bind = memnew(Button); add_bind->set_text(TTR("Add")); add_bind_hb->add_child(add_bind); add_bind->connect("pressed", callable_mp(this, &ConnectDialog::_add_bind)); + bind_controls.push_back(add_bind); Button *del_bind = memnew(Button); del_bind->set_text(TTR("Remove")); add_bind_hb->add_child(del_bind); del_bind->connect("pressed", callable_mp(this, &ConnectDialog::_remove_bind)); + bind_controls.push_back(del_bind); vbc_right->add_margin_child(TTR("Add Extra Call Argument:"), add_bind_hb); bind_editor = memnew(EditorInspector); + bind_controls.push_back(bind_editor); vbc_right->add_margin_child(TTR("Extra Call Arguments:"), bind_editor, true); + unbind_count = memnew(SpinBox); + unbind_count->set_tooltip(TTR("Allows to drop arguments sent by signal emitter.")); + unbind_count->connect("value_changed", callable_mp(this, &ConnectDialog::_unbind_count_changed)); + + vbc_right->add_margin_child(TTR("Unbind Signal Arguments:"), unbind_count); + HBoxContainer *dstm_hb = memnew(HBoxContainer); vbc_left->add_margin_child(TTR("Receiver Method:"), dstm_hb); @@ -541,26 +572,29 @@ void ConnectionsDock::_make_or_edit_connection() { Node *target = selectedNode->get_node(dst_path); ERR_FAIL_COND(!target); - ConnectDialog::ConnectionData cToMake; - cToMake.source = connect_dialog->get_source(); - cToMake.target = target; - cToMake.signal = connect_dialog->get_signal_name(); - cToMake.method = connect_dialog->get_dst_method_name(); - cToMake.binds = connect_dialog->get_binds(); + ConnectDialog::ConnectionData connection; + connection.source = connect_dialog->get_source(); + connection.target = target; + connection.signal = connect_dialog->get_signal_name(); + connection.method = connect_dialog->get_dst_method_name(); + connection.unbinds = connect_dialog->get_unbinds(); + if (connection.unbinds == 0) { + connection.binds = connect_dialog->get_binds(); + } bool defer = connect_dialog->get_deferred(); bool oshot = connect_dialog->get_oneshot(); - cToMake.flags = CONNECT_PERSIST | (defer ? CONNECT_DEFERRED : 0) | (oshot ? CONNECT_ONESHOT : 0); + connection.flags = CONNECT_PERSIST | (defer ? CONNECT_DEFERRED : 0) | (oshot ? CONNECT_ONESHOT : 0); // Conditions to add function: must have a script and must not have the method already // (in the class, the script itself, or inherited). bool add_script_function = false; Ref<Script> script = target->get_script(); - if (!target->get_script().is_null() && !ClassDB::has_method(target->get_class(), cToMake.method)) { + if (!target->get_script().is_null() && !ClassDB::has_method(target->get_class(), connection.method)) { // There is a chance that the method is inherited from another script. bool found_inherited_function = false; Ref<Script> inherited_script = script->get_base_script(); while (!inherited_script.is_null()) { - int line = inherited_script->get_language()->find_function(cToMake.method, inherited_script->get_source_code()); + int line = inherited_script->get_language()->find_function(connection.method, inherited_script->get_source_code()); if (line != -1) { found_inherited_function = true; break; @@ -575,23 +609,23 @@ void ConnectionsDock::_make_or_edit_connection() { if (add_script_function) { // Pick up args here before "it" is deleted by update_tree. script_function_args = it->get_metadata(0).operator Dictionary()["args"]; - for (int i = 0; i < cToMake.binds.size(); i++) { - script_function_args.push_back("extra_arg_" + itos(i) + ":" + Variant::get_type_name(cToMake.binds[i].get_type())); + for (int i = 0; i < connection.binds.size(); i++) { + script_function_args.push_back("extra_arg_" + itos(i) + ":" + Variant::get_type_name(connection.binds[i].get_type())); } } if (connect_dialog->is_editing()) { _disconnect(*it); - _connect(cToMake); + _connect(connection); } else { - _connect(cToMake); + _connect(connection); } // IMPORTANT NOTE: _disconnect and _connect cause an update_tree, which will delete the object "it" is pointing to. it = nullptr; if (add_script_function) { - editor->emit_signal(SNAME("script_add_function_request"), target, cToMake.method, script_function_args); + editor->emit_signal(SNAME("script_add_function_request"), target, connection.method, script_function_args); hide(); } @@ -601,20 +635,18 @@ void ConnectionsDock::_make_or_edit_connection() { /* * Creates single connection w/ undo-redo functionality. */ -void ConnectionsDock::_connect(ConnectDialog::ConnectionData cToMake) { - Node *source = static_cast<Node *>(cToMake.source); - Node *target = static_cast<Node *>(cToMake.target); +void ConnectionsDock::_connect(ConnectDialog::ConnectionData p_connection) { + Node *source = Object::cast_to<Node>(p_connection.source); + Node *target = Object::cast_to<Node>(p_connection.target); if (!source || !target) { return; } - undo_redo->create_action(vformat(TTR("Connect '%s' to '%s'"), String(cToMake.signal), String(cToMake.method))); - - Callable c(target, cToMake.method); - - undo_redo->add_do_method(source, "connect", cToMake.signal, c, cToMake.binds, cToMake.flags); - undo_redo->add_undo_method(source, "disconnect", cToMake.signal, c); + Callable callable = p_connection.get_callable(); + undo_redo->create_action(vformat(TTR("Connect '%s' to '%s'"), String(p_connection.signal), String(p_connection.method))); + undo_redo->add_do_method(source, "connect", p_connection.signal, callable, varray(), p_connection.flags); + undo_redo->add_undo_method(source, "disconnect", p_connection.signal, callable); undo_redo->add_do_method(this, "update_tree"); undo_redo->add_undo_method(this, "update_tree"); undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); //to force redraw of scene tree @@ -634,8 +666,9 @@ void ConnectionsDock::_disconnect(TreeItem &item) { undo_redo->create_action(vformat(TTR("Disconnect '%s' from '%s'"), c.signal, c.method)); - undo_redo->add_do_method(selectedNode, "disconnect", c.signal, Callable(c.target, c.method)); - undo_redo->add_undo_method(selectedNode, "connect", c.signal, Callable(c.target, c.method), c.binds, c.flags); + Callable callable = c.get_callable(); + undo_redo->add_do_method(selectedNode, "disconnect", c.signal, callable); + undo_redo->add_undo_method(selectedNode, "connect", c.signal, callable, c.binds, c.flags); undo_redo->add_do_method(this, "update_tree"); undo_redo->add_undo_method(this, "update_tree"); undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); // To force redraw of scene tree. @@ -662,8 +695,8 @@ void ConnectionsDock::_disconnect_all() { while (child) { Connection cd = child->get_metadata(0); ConnectDialog::ConnectionData c = cd; - undo_redo->add_do_method(selectedNode, "disconnect", c.signal, Callable(c.target, c.method)); - undo_redo->add_undo_method(selectedNode, "connect", c.signal, Callable(c.target, c.method), c.binds, c.flags); + undo_redo->add_do_method(selectedNode, "disconnect", c.signal, c.get_callable()); + undo_redo->add_undo_method(selectedNode, "connect", c.signal, c.get_callable(), c.binds, c.flags); child = child->get_next(); } @@ -752,8 +785,8 @@ void ConnectionsDock::_open_connection_dialog(TreeItem &item) { * Open connection dialog with Connection data to EDIT an existing connection. */ void ConnectionsDock::_open_connection_dialog(ConnectDialog::ConnectionData cToEdit) { - Node *src = static_cast<Node *>(cToEdit.source); - Node *dst = static_cast<Node *>(cToEdit.target); + Node *src = Object::cast_to<Node>(cToEdit.source); + Node *dst = Object::cast_to<Node>(cToEdit.target); if (src && dst) { const String &signalname = cToEdit.signal; @@ -1042,7 +1075,9 @@ void ConnectionsDock::update_tree() { if (c.flags & CONNECT_ONESHOT) { path += " (oneshot)"; } - if (c.binds.size()) { + if (c.unbinds > 0) { + path += " unbinds(" + itos(c.unbinds) + ")"; + } else if (!c.binds.is_empty()) { path += " binds("; for (int i = 0; i < c.binds.size(); i++) { if (i > 0) { @@ -1055,8 +1090,7 @@ void ConnectionsDock::update_tree() { TreeItem *connection_item = tree->create_item(signal_item); connection_item->set_text(0, path); - Connection cd = c; - connection_item->set_metadata(0, cd); + connection_item->set_metadata(0, cn); connection_item->set_icon(0, get_theme_icon(SNAME("Slot"), SNAME("EditorIcons"))); } } diff --git a/editor/connections_dialog.h b/editor/connections_dialog.h index b9911c1cc5..474838df54 100644 --- a/editor/connections_dialog.h +++ b/editor/connections_dialog.h @@ -48,6 +48,7 @@ class PopupMenu; class ConnectDialogBinds; +class SpinBox; class ConnectDialog : public ConfirmationDialog { GDCLASS(ConnectDialog, ConfirmationDialog); @@ -59,25 +60,45 @@ public: StringName signal; StringName method; uint32_t flags = 0; + int unbinds = 0; Vector<Variant> binds; - ConnectionData() { - } + ConnectionData() {} + ConnectionData(const Connection &p_connection) { source = Object::cast_to<Node>(p_connection.signal.get_object()); signal = p_connection.signal.get_name(); target = Object::cast_to<Node>(p_connection.callable.get_object()); - method = p_connection.callable.get_method(); flags = p_connection.flags; - binds = p_connection.binds; + + Callable base_callable; + if (p_connection.callable.is_custom()) { + CallableCustomBind *ccb = dynamic_cast<CallableCustomBind *>(p_connection.callable.get_custom()); + if (ccb) { + binds = ccb->get_binds(); + base_callable = ccb->get_callable(); + } + + CallableCustomUnbind *ccu = dynamic_cast<CallableCustomUnbind *>(p_connection.callable.get_custom()); + if (ccu) { + unbinds = ccu->get_unbinds(); + base_callable = ccu->get_callable(); + } + } else { + base_callable = p_connection.callable; + } + method = base_callable.get_method(); } - operator Connection() { - Connection c; - c.signal = ::Signal(source, signal); - c.callable = Callable(target, method); - c.flags = flags; - c.binds = binds; - return c; + + Callable get_callable() { + if (unbinds > 0) { + return Callable(target, method).unbind(unbinds); + } else if (!binds.is_empty()) { + const Variant *args = binds.ptr(); + return Callable(target, method).bind(&args, binds.size()); + } else { + return Callable(target, method); + } } }; @@ -94,11 +115,13 @@ private: SceneTreeEditor *tree; AcceptDialog *error; + SpinBox *unbind_count; EditorInspector *bind_editor; OptionButton *type_list; CheckBox *deferred; CheckBox *oneshot; CheckButton *advanced; + Vector<Control *> bind_controls; Label *error_label; @@ -107,6 +130,7 @@ private: void _item_activated(); void _text_submitted(const String &_text); void _tree_node_selected(); + void _unbind_count_changed(double p_count); void _add_bind(); void _remove_bind(); void _advanced_pressed(); @@ -123,6 +147,7 @@ public: void set_dst_node(Node *p_node); StringName get_dst_method_name() const; void set_dst_method(const StringName &p_method); + int get_unbinds() const; Vector<Variant> get_binds() const; bool get_deferred() const; @@ -176,7 +201,7 @@ class ConnectionsDock : public VBoxContainer { void _filter_changed(const String &p_text); void _make_or_edit_connection(); - void _connect(ConnectDialog::ConnectionData cToMake); + void _connect(ConnectDialog::ConnectionData p_connection); void _disconnect(TreeItem &item); void _disconnect_all(); diff --git a/editor/inspector_dock.h b/editor/inspector_dock.h index 5bf6a34617..97c7836bf2 100644 --- a/editor/inspector_dock.h +++ b/editor/inspector_dock.h @@ -32,7 +32,6 @@ #define INSPECTOR_DOCK_H #include "editor/animation_track_editor.h" -#include "editor/connections_dialog.h" #include "editor/create_dialog.h" #include "editor/editor_data.h" #include "editor/editor_inspector.h" diff --git a/editor/node_dock.cpp b/editor/node_dock.cpp index 532413897b..a22b43aaa3 100644 --- a/editor/node_dock.cpp +++ b/editor/node_dock.cpp @@ -30,6 +30,7 @@ #include "node_dock.h" +#include "connections_dialog.h" #include "editor_node.h" #include "editor_scale.h" diff --git a/editor/node_dock.h b/editor/node_dock.h index 280369bb09..fcb996b221 100644 --- a/editor/node_dock.h +++ b/editor/node_dock.h @@ -31,9 +31,10 @@ #ifndef NODE_DOCK_H #define NODE_DOCK_H -#include "connections_dialog.h" #include "groups_editor.h" +class ConnectionsDock; + class NodeDock : public VBoxContainer { GDCLASS(NodeDock, VBoxContainer); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 255e026887..f8a480b92b 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -31,7 +31,6 @@ #ifndef SCENE_TREE_DOCK_H #define SCENE_TREE_DOCK_H -#include "editor/connections_dialog.h" #include "editor/create_dialog.h" #include "editor/editor_data.h" #include "editor/groups_editor.h" diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index c8d3ea5e37..5a95cbda0c 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -320,15 +320,23 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { continue; } - Vector<Variant> binds; - if (c.binds.size()) { - binds.resize(c.binds.size()); - for (int j = 0; j < c.binds.size(); j++) { - binds.write[j] = props[c.binds[j]]; + Callable callable(cto, snames[c.method]); + if (c.unbinds > 0) { + callable = callable.unbind(c.unbinds); + } else if (!c.binds.is_empty()) { + Vector<Variant> binds; + if (c.binds.size()) { + binds.resize(c.binds.size()); + for (int j = 0; j < c.binds.size(); j++) { + binds.write[j] = props[c.binds[j]]; + } } + + const Variant *args = binds.ptr(); + callable = callable.bind(&args, binds.size()); } - cfrom->connect(snames[c.signal], Callable(cto, snames[c.method]), binds, CONNECT_PERSIST | c.flags); + cfrom->connect(snames[c.signal], callable, varray(), CONNECT_PERSIST | c.flags); } //Node *s = ret_nodes[0]; @@ -709,6 +717,26 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName continue; } + Vector<Variant> binds; + int unbinds = 0; + Callable base_callable; + + if (c.callable.is_custom()) { + CallableCustomBind *ccb = dynamic_cast<CallableCustomBind *>(c.callable.get_custom()); + if (ccb) { + binds = ccb->get_binds(); + base_callable = ccb->get_callable(); + } + + CallableCustomUnbind *ccu = dynamic_cast<CallableCustomUnbind *>(c.callable.get_custom()); + if (ccu) { + unbinds = ccu->get_unbinds(); + base_callable = ccu->get_callable(); + } + } else { + base_callable = c.callable; + } + //find if this connection already exists Node *common_parent = target->find_common_parent_with(p_node); @@ -734,7 +762,7 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName NodePath signal_from = common_parent->get_path_to(p_node); NodePath signal_to = common_parent->get_path_to(target); - if (ps->has_connection(signal_from, c.signal.get_name(), signal_to, c.callable.get_method())) { + if (ps->has_connection(signal_from, c.signal.get_name(), signal_to, base_callable.get_method())) { exists = true; break; } @@ -765,7 +793,7 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName if (from_node >= 0 && to_node >= 0) { //this one has state for this node, save - if (state->is_connection(from_node, c.signal.get_name(), to_node, c.callable.get_method())) { + if (state->is_connection(from_node, c.signal.get_name(), to_node, base_callable.get_method())) { exists2 = true; break; } @@ -783,7 +811,7 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName if (from_node >= 0 && to_node >= 0) { //this one has state for this node, save - if (state->is_connection(from_node, c.signal.get_name(), to_node, c.callable.get_method())) { + if (state->is_connection(from_node, c.signal.get_name(), to_node, base_callable.get_method())) { exists2 = true; break; } @@ -830,12 +858,16 @@ Error SceneState::_parse_connections(Node *p_owner, Node *p_node, Map<StringName ConnectionData cd; cd.from = src_id; cd.to = target_id; - cd.method = _nm_get_string(c.callable.get_method(), name_map); + cd.method = _nm_get_string(base_callable.get_method(), name_map); cd.signal = _nm_get_string(c.signal.get_name(), name_map); cd.flags = c.flags; - for (int i = 0; i < c.binds.size(); i++) { + cd.unbinds = unbinds; + for (int i = 0; i < c.binds.size(); i++) { // TODO: This could be removed now. cd.binds.push_back(_vm_get_variant(c.binds[i], variant_map)); } + for (int i = 0; i < binds.size(); i++) { + cd.binds.push_back(_vm_get_variant(binds[i], variant_map)); + } connections.push_back(cd); } } @@ -1447,6 +1479,11 @@ int SceneState::get_connection_flags(int p_idx) const { return connections[p_idx].flags; } +int SceneState::get_connection_unbinds(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx, connections.size(), -1); + return connections[p_idx].unbinds; +} + Array SceneState::get_connection_binds(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, connections.size(), Array()); Array binds; @@ -1551,7 +1588,7 @@ void SceneState::set_base_scene(int p_idx) { base_scene_idx = p_idx; } -void SceneState::add_connection(int p_from, int p_to, int p_signal, int p_method, int p_flags, const Vector<int> &p_binds) { +void SceneState::add_connection(int p_from, int p_to, int p_signal, int p_method, int p_flags, int p_unbinds, const Vector<int> &p_binds) { ERR_FAIL_INDEX(p_signal, names.size()); ERR_FAIL_INDEX(p_method, names.size()); @@ -1564,6 +1601,7 @@ void SceneState::add_connection(int p_from, int p_to, int p_signal, int p_method c.signal = p_signal; c.method = p_method; c.flags = p_flags; + c.unbinds = p_unbinds; c.binds = p_binds; connections.push_back(c); } @@ -1606,6 +1644,7 @@ void SceneState::_bind_methods() { ClassDB::bind_method(D_METHOD("get_connection_method", "idx"), &SceneState::get_connection_method); ClassDB::bind_method(D_METHOD("get_connection_flags", "idx"), &SceneState::get_connection_flags); ClassDB::bind_method(D_METHOD("get_connection_binds", "idx"), &SceneState::get_connection_binds); + ClassDB::bind_method(D_METHOD("get_connection_unbinds", "idx"), &SceneState::get_connection_unbinds); BIND_ENUM_CONSTANT(GEN_EDIT_STATE_DISABLED); BIND_ENUM_CONSTANT(GEN_EDIT_STATE_INSTANCE); diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h index 55708f7914..2dcdb10cc6 100644 --- a/scene/resources/packed_scene.h +++ b/scene/resources/packed_scene.h @@ -82,6 +82,7 @@ class SceneState : public RefCounted { int signal = 0; int method = 0; int flags = 0; + int unbinds = 0; Vector<int> binds; }; @@ -162,6 +163,7 @@ public: NodePath get_connection_target(int p_idx) const; StringName get_connection_method(int p_idx) const; int get_connection_flags(int p_idx) const; + int get_connection_unbinds(int p_idx) const; Array get_connection_binds(int p_idx) const; bool has_connection(const NodePath &p_node_from, const StringName &p_signal, const NodePath &p_node_to, const StringName &p_method); @@ -177,7 +179,7 @@ public: void add_node_property(int p_node, int p_name, int p_value); void add_node_group(int p_node, int p_group); void set_base_scene(int p_idx); - void add_connection(int p_from, int p_to, int p_signal, int p_method, int p_flags, const Vector<int> &p_binds); + void add_connection(int p_from, int p_to, int p_signal, int p_method, int p_flags, int p_unbinds, const Vector<int> &p_binds); void add_editable_instance(const NodePath &p_path); virtual void set_last_modified_time(uint64_t p_time) { last_modified_time = p_time; } diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index 77d915aef9..60e87b30e8 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -313,6 +313,7 @@ Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourcePars StringName method = next_tag.fields["method"]; StringName signal = next_tag.fields["signal"]; int flags = Object::CONNECT_PERSIST; + int unbinds = 0; Array binds; if (next_tag.fields.has("flags")) { @@ -323,6 +324,10 @@ Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourcePars binds = next_tag.fields["binds"]; } + if (next_tag.fields.has("unbinds")) { + unbinds = next_tag.fields["unbinds"]; + } + Vector<int> bind_ints; for (int i = 0; i < binds.size(); i++) { bind_ints.push_back(packed_scene->get_state()->add_value(binds[i])); @@ -334,6 +339,7 @@ Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourcePars packed_scene->get_state()->add_name(signal), packed_scene->get_state()->add_name(method), flags, + unbinds, bind_ints); error = VariantParser::parse_tag(&stream, lines, error_text, next_tag, &parser); @@ -1909,6 +1915,11 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r connstr += " flags=" + itos(flags); } + int unbinds = state->get_connection_unbinds(i); + if (unbinds > 0) { + connstr += " unbinds=" + itos(unbinds); + } + Array binds = state->get_connection_binds(i); f->store_string(connstr); if (binds.size()) { |