diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 55106f5ee75..a53c19d2e76 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1121,6 +1121,38 @@ Node *Node::get_owner() const { return data.owner; } + +Node* Node::find_common_parent_with(const Node *p_node) const { + + if (this==p_node) + return const_cast(p_node); + + Set visited; + + const Node *n=this; + + while(n) { + + visited.insert(n); + n=n->data.parent; + } + + const Node *common_parent=p_node; + + while(common_parent) { + + if (visited.has(common_parent)) + break; + common_parent=common_parent->data.parent; + } + + if (!common_parent) + return NULL; + + return const_cast(common_parent); + +} + NodePath Node::get_path_to(const Node *p_node) const { ERR_FAIL_NULL_V(p_node,NodePath()); diff --git a/scene/main/node.h b/scene/main/node.h index 10cfc5f9e66..18e403cd615 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -215,6 +215,7 @@ public: NodePath get_path() const; NodePath get_path_to(const Node *p_node) const; + Node* find_common_parent_with(const Node *p_node) const; void add_to_group(const StringName& p_identifier,bool p_persistent=false); void remove_from_group(const StringName& p_identifier); diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index c36480420b3..51e5b611038 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -732,22 +732,81 @@ Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Mapcast_to(); - if (!n) { + + Node *target=c.target->cast_to(); + + + if (!target) { continue; } - //source node is outside saved scene? - bool src_is_out = p_node!=p_owner && (p_node->get_filename()!=String() || p_node->get_owner()!=p_owner); - //target node is outside saved scene? - bool dst_is_out = n!=p_owner && (n->get_filename()!=String() || n->get_owner()!=p_owner); + //find if this connection already exists + Node *common_parent = target->find_common_parent_with(p_node); - //if both are out, ignore connection - if (src_is_out && dst_is_out) { + ERR_CONTINUE(!common_parent); + + if (common_parent!=p_owner && common_parent->get_filename()==String()) { + common_parent=common_parent->get_owner(); + } + + bool exists=false; + + //go through ownership chain to see if this exists + while(common_parent) { + + + + print_line("AT : "+String(p_owner->get_path_to(target))); + print_line("CP : "+String(p_owner->get_path_to(common_parent))); + Ref ps; + + if (common_parent==p_owner) + ps=common_parent->get_scene_inherited_state(); + else + ps=common_parent->get_scene_instance_state(); + + + if (ps.is_valid()) { + + print_line("PS VALID"); + + NodePath signal_from = common_parent->get_path_to(p_node); + NodePath signal_to = common_parent->get_path_to(target); + + int path_from = ps->find_node_by_path(signal_from); + int path_to = ps->find_node_by_path(signal_to); + int signal_name = ps->find_name(c.signal); + int method_name = ps->find_name(c.method); + + print_line("path_from "+itos(path_from)); + print_line("path_to "+itos(path_to)); + print_line("signal_name "+itos(signal_name)); + print_line("method_name "+itos(method_name)); + + if (path_from>=0 && path_to>=0 && signal_name>=0 && method_name>=0) { + //if valid + print_line("EXISTS"); + if (ps->has_connection(path_from,signal_name,path_to,method_name)) { + print_line("YES"); + exists=true; + break; + } + } + + } + + if (common_parent==p_owner) + break; + else + common_parent=common_parent->get_owner(); + } + + if (exists) { //already exists (comes from instance or inheritance), so don't save continue; } + { Node *nl=p_node; @@ -760,7 +819,7 @@ Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Map state = nl->get_scene_inherited_state(); if (state.is_valid()) { int from_node = state->find_node_by_path(nl->get_path_to(p_node)); - int to_node = state->find_node_by_path(nl->get_path_to(n)); + int to_node = state->find_node_by_path(nl->get_path_to(target)); if (from_node>=0 && to_node>=0) { //this one has state for this node, save @@ -778,7 +837,7 @@ Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Map state = nl->get_scene_instance_state(); if (state.is_valid()) { int from_node = state->find_node_by_path(nl->get_path_to(p_node)); - int to_node = state->find_node_by_path(nl->get_path_to(n)); + int to_node = state->find_node_by_path(nl->get_path_to(target)); if (from_node>=0 && to_node>=0) { //this one has state for this node, save @@ -819,14 +878,14 @@ Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Map SceneState::get_editable_instances() const { return editable_instances; } @@ -1505,6 +1584,16 @@ int SceneState::add_name(const StringName& p_name) { return names.size()-1; } +int SceneState::find_name(const StringName& p_name) const { + + for(int i=0;i get_editable_instances() const; //build API int add_name(const StringName& p_name); + int find_name(const StringName& p_name) const; int add_value(const Variant& p_value); int add_node_path(const NodePath& p_path); int add_node(int p_parent,int p_owner,int p_type,int p_name, int p_instance);