Browse Source

WIP bugfix for existing connections

Juan Linietsky 9 years ago
parent
commit
9de33e18f1
4 changed files with 140 additions and 15 deletions
  1. 32 0
      scene/main/node.cpp
  2. 1 0
      scene/main/node.h
  3. 104 15
      scene/resources/packed_scene.cpp
  4. 3 0
      scene/resources/packed_scene.h

+ 32 - 0
scene/main/node.cpp

@@ -1121,6 +1121,38 @@ Node *Node::get_owner() const {
 	return data.owner;
 	return data.owner;
 }
 }
 
 
+
+Node* Node::find_common_parent_with(const Node *p_node) const {
+
+	if (this==p_node)
+		return const_cast<Node*>(p_node);
+
+	Set<const Node*> 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<Node*>(common_parent);
+
+}
+
 NodePath Node::get_path_to(const Node *p_node) const {
 NodePath Node::get_path_to(const Node *p_node) const {
 
 
 	ERR_FAIL_NULL_V(p_node,NodePath());
 	ERR_FAIL_NULL_V(p_node,NodePath());

+ 1 - 0
scene/main/node.h

@@ -215,6 +215,7 @@ public:
 
 
 	NodePath get_path() const;
 	NodePath get_path() const;
 	NodePath get_path_to(const Node *p_node) 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 add_to_group(const StringName& p_identifier,bool p_persistent=false);
 	void remove_from_group(const StringName& p_identifier);
 	void remove_from_group(const StringName& p_identifier);

+ 104 - 15
scene/resources/packed_scene.cpp

@@ -732,22 +732,81 @@ Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Map<StringName,
 			// only connections that originate or end into main saved scene are saved
 			// only connections that originate or end into main saved scene are saved
 			// everything else is discarded
 			// everything else is discarded
 
 
-			Node *n=c.target->cast_to<Node>();
-			if (!n) {
+
+			Node *target=c.target->cast_to<Node>();
+
+
+			if (!target) {
 				continue;
 				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);
+
+			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<SceneState> ps;
 
 
-			//if both are out, ignore connection
-			if (src_is_out && dst_is_out) {
+				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;
 				continue;
 			}
 			}
 
 
 
 
+
 			{
 			{
 				Node *nl=p_node;
 				Node *nl=p_node;
 
 
@@ -760,7 +819,7 @@ Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Map<StringName,
 						Ref<SceneState> state = nl->get_scene_inherited_state();
 						Ref<SceneState> state = nl->get_scene_inherited_state();
 						if (state.is_valid()) {
 						if (state.is_valid()) {
 							int from_node = state->find_node_by_path(nl->get_path_to(p_node));
 							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) {
 							if (from_node>=0 && to_node>=0) {
 								//this one has state for this node, save
 								//this one has state for this node, save
@@ -778,7 +837,7 @@ Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Map<StringName,
 							Ref<SceneState> state = nl->get_scene_instance_state();
 							Ref<SceneState> state = nl->get_scene_instance_state();
 							if (state.is_valid()) {
 							if (state.is_valid()) {
 								int from_node = state->find_node_by_path(nl->get_path_to(p_node));
 								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) {
 								if (from_node>=0 && to_node>=0) {
 									//this one has state for this node, save
 									//this one has state for this node, save
@@ -819,14 +878,14 @@ Error SceneState::_parse_connections(Node *p_owner,Node *p_node, Map<StringName,
 
 
 			int target_id;
 			int target_id;
 
 
-			if (node_map.has(n)) {
-				target_id=node_map[n];
+			if (node_map.has(target)) {
+				target_id=node_map[target];
 			} else {
 			} else {
-				if (nodepath_map.has(n)) {
-					target_id=FLAG_ID_IS_PATH|nodepath_map[n];
+				if (nodepath_map.has(target)) {
+					target_id=FLAG_ID_IS_PATH|nodepath_map[target];
 				} else {
 				} else {
 					int sidx=nodepath_map.size();
 					int sidx=nodepath_map.size();
-					nodepath_map[n]=sidx;
+					nodepath_map[target]=sidx;
 					target_id=FLAG_ID_IS_PATH|sidx;
 					target_id=FLAG_ID_IS_PATH|sidx;
 				}
 				}
 			}
 			}
@@ -1478,6 +1537,8 @@ StringName SceneState::get_connection_method(int p_idx) const{
 	return names[connections[p_idx].method];
 	return names[connections[p_idx].method];
 
 
 }
 }
+
+
 int SceneState::get_connection_flags(int p_idx) const{
 int SceneState::get_connection_flags(int p_idx) const{
 
 
 	ERR_FAIL_INDEX_V(p_idx,connections.size(),-1);
 	ERR_FAIL_INDEX_V(p_idx,connections.size(),-1);
@@ -1494,6 +1555,24 @@ Array SceneState::get_connection_binds(int p_idx) const {
 	return binds;
 	return binds;
 }
 }
 
 
+bool SceneState::has_connection(int p_node_from, int p_signal, int p_node_to, int p_method) const {
+
+	for(int i=0;i<connections.size();i++) {
+		const ConnectionData &c = connections[i];
+
+		print_line("from: "+itos(c.from)+" vs "+itos(p_node_from));
+		print_line("to: "+itos(c.to)+" vs "+itos(p_node_to));
+		print_line("signal: "+itos(c.signal)+" vs "+itos(p_signal));
+		print_line("method: "+itos(c.method)+" vs "+itos(p_method));
+
+		if (c.from==p_node_from && c.signal==p_signal && c.to==p_node_to && c.method==p_method) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
 Vector<NodePath> SceneState::get_editable_instances() const {
 Vector<NodePath> SceneState::get_editable_instances() const {
 	return editable_instances;
 	return editable_instances;
 }
 }
@@ -1505,6 +1584,16 @@ int SceneState::add_name(const StringName& p_name) {
 	return names.size()-1;
 	return names.size()-1;
 }
 }
 
 
+int SceneState::find_name(const StringName& p_name) const {
+
+	for(int i=0;i<names.size();i++) {
+		if (names[i]==p_name)
+			return i;
+	}
+
+	return -1;
+}
+
 int SceneState::add_value(const Variant& p_value) {
 int SceneState::add_value(const Variant& p_value) {
 
 
 	variants.push_back(p_value);
 	variants.push_back(p_value);

+ 3 - 0
scene/resources/packed_scene.h

@@ -163,11 +163,14 @@ public:
 	int get_connection_flags(int p_idx) const;
 	int get_connection_flags(int p_idx) const;
 	Array get_connection_binds(int p_idx) const;
 	Array get_connection_binds(int p_idx) const;
 
 
+	bool has_connection(int p_node_from, int p_signal, int p_node_to, int p_method) const;
+
 	Vector<NodePath> get_editable_instances() const;
 	Vector<NodePath> get_editable_instances() const;
 
 
 	//build API
 	//build API
 
 
 	int add_name(const StringName& p_name);
 	int add_name(const StringName& p_name);
+	int find_name(const StringName& p_name) const;
 	int add_value(const Variant& p_value);
 	int add_value(const Variant& p_value);
 	int add_node_path(const NodePath& p_path);
 	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);
 	int add_node(int p_parent,int p_owner,int p_type,int p_name, int p_instance);