| 
									
										
										
										
											2016-06-18 14:46:12 +02:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  navigation_mesh.cpp                                                  */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							|  |  |  | /*                    http://www.godotengine.org                         */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2017-01-01 22:01:57 +01:00
										 |  |  | /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							| 
									
										
										
										
											2016-06-18 14:46:12 +02:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | #include "navigation_mesh.h"
 | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | #include "mesh_instance.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | #include "navigation.h"
 | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void NavigationMesh::create_from_mesh(const Ref<Mesh> &p_mesh) { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	vertices = PoolVector<Vector3>(); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 	clear_polygons(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < p_mesh->get_surface_count(); i++) { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		if (p_mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 			continue; | 
					
						
							|  |  |  | 		Array arr = p_mesh->surface_get_arrays(i); | 
					
						
							| 
									
										
										
										
											2017-01-07 18:25:37 -03:00
										 |  |  | 		PoolVector<Vector3> varr = arr[Mesh::ARRAY_VERTEX]; | 
					
						
							|  |  |  | 		PoolVector<int> iarr = arr[Mesh::ARRAY_INDEX]; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		if (varr.size() == 0 || iarr.size() == 0) | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 			continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		int from = vertices.size(); | 
					
						
							|  |  |  | 		vertices.append_array(varr); | 
					
						
							|  |  |  | 		int rlen = iarr.size(); | 
					
						
							| 
									
										
										
										
											2017-01-07 18:25:37 -03:00
										 |  |  | 		PoolVector<int>::Read r = iarr.read(); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		for (int j = 0; j < rlen; j += 3) { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 			Vector<int> vi; | 
					
						
							|  |  |  | 			vi.resize(3); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			vi[0] = r[j + 0] + from; | 
					
						
							|  |  |  | 			vi[1] = r[j + 1] + from; | 
					
						
							|  |  |  | 			vi[2] = r[j + 2] + from; | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			add_polygon(vi); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void NavigationMesh::set_vertices(const PoolVector<Vector3> &p_vertices) { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	vertices = p_vertices; | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | PoolVector<Vector3> NavigationMesh::get_vertices() const { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return vertices; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void NavigationMesh::_set_polygons(const Array &p_array) { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	polygons.resize(p_array.size()); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < p_array.size(); i++) { | 
					
						
							|  |  |  | 		polygons[i].indices = p_array[i]; | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Array NavigationMesh::_get_polygons() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Array ret; | 
					
						
							|  |  |  | 	ret.resize(polygons.size()); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < ret.size(); i++) { | 
					
						
							|  |  |  | 		ret[i] = polygons[i].indices; | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void NavigationMesh::add_polygon(const Vector<int> &p_polygon) { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Polygon polygon; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	polygon.indices = p_polygon; | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 	polygons.push_back(polygon); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | int NavigationMesh::get_polygon_count() const { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return polygons.size(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Vector<int> NavigationMesh::get_polygon(int p_idx) { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ERR_FAIL_INDEX_V(p_idx, polygons.size(), Vector<int>()); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 	return polygons[p_idx].indices; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void NavigationMesh::clear_polygons() { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	polygons.clear(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | Ref<Mesh> NavigationMesh::get_debug_mesh() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (debug_mesh.is_valid()) | 
					
						
							|  |  |  | 		return debug_mesh; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-07 18:25:37 -03:00
										 |  |  | 	PoolVector<Vector3> vertices = get_vertices(); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	PoolVector<Vector3>::Read vr = vertices.read(); | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 	List<Face3> faces; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < get_polygon_count(); i++) { | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 		Vector<int> p = get_polygon(i); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		for (int j = 2; j < p.size(); j++) { | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 			Face3 f; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			f.vertex[0] = vr[p[0]]; | 
					
						
							|  |  |  | 			f.vertex[1] = vr[p[j - 1]]; | 
					
						
							|  |  |  | 			f.vertex[2] = vr[p[j]]; | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			faces.push_back(f); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	Map<_EdgeKey, bool> edge_map; | 
					
						
							| 
									
										
										
										
											2017-01-07 18:25:37 -03:00
										 |  |  | 	PoolVector<Vector3> tmeshfaces; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	tmeshfaces.resize(faces.size() * 3); | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		PoolVector<Vector3>::Write tw = tmeshfaces.write(); | 
					
						
							|  |  |  | 		int tidx = 0; | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		for (List<Face3>::Element *E = faces.front(); E; E = E->next()) { | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			const Face3 &f = E->get(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			for (int j = 0; j < 3; j++) { | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				tw[tidx++] = f.vertex[j]; | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 				_EdgeKey ek; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				ek.from = f.vertex[j].snapped(CMP_EPSILON); | 
					
						
							|  |  |  | 				ek.to = f.vertex[(j + 1) % 3].snapped(CMP_EPSILON); | 
					
						
							|  |  |  | 				if (ek.from < ek.to) | 
					
						
							|  |  |  | 					SWAP(ek.from, ek.to); | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				Map<_EdgeKey, bool>::Element *E = edge_map.find(ek); | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				if (E) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 					E->get() = false; | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 					edge_map[ek] = true; | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	List<Vector3> lines; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (Map<_EdgeKey, bool>::Element *E = edge_map.front(); E; E = E->next()) { | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (E->get()) { | 
					
						
							|  |  |  | 			lines.push_back(E->key().from); | 
					
						
							|  |  |  | 			lines.push_back(E->key().to); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-07 18:25:37 -03:00
										 |  |  | 	PoolVector<Vector3> varr; | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 	varr.resize(lines.size()); | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2017-01-07 18:25:37 -03:00
										 |  |  | 		PoolVector<Vector3>::Write w = varr.write(); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		int idx = 0; | 
					
						
							|  |  |  | 		for (List<Vector3>::Element *E = lines.front(); E; E = E->next()) { | 
					
						
							|  |  |  | 			w[idx++] = E->get(); | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	debug_mesh = Ref<Mesh>(memnew(Mesh)); | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Array arr; | 
					
						
							|  |  |  | 	arr.resize(Mesh::ARRAY_MAX); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	arr[Mesh::ARRAY_VERTEX] = varr; | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	debug_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, arr); | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return debug_mesh; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | void NavigationMesh::_bind_methods() { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_vertices", "vertices"), &NavigationMesh::set_vertices); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_vertices"), &NavigationMesh::get_vertices); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("add_polygon", "polygon"), &NavigationMesh::add_polygon); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_polygon_count"), &NavigationMesh::get_polygon_count); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_polygon", "idx"), &NavigationMesh::get_polygon); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("clear_polygons"), &NavigationMesh::clear_polygons); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("_set_polygons", "polygons"), &NavigationMesh::_set_polygons); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("_get_polygons"), &NavigationMesh::_get_polygons); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR3_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_vertices", "get_vertices"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_polygons", "_get_polygons"); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NavigationMesh::NavigationMesh() { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void NavigationMeshInstance::set_enabled(bool p_enabled) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	if (enabled == p_enabled) | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	enabled = p_enabled; | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-05 21:20:42 -03:00
										 |  |  | 	if (!is_inside_tree()) | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!enabled) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		if (nav_id != -1) { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 			navigation->navmesh_remove(nav_id); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			nav_id = -1; | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (navigation) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (navmesh.is_valid()) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				nav_id = navigation->navmesh_create(navmesh, get_relative_transform(navigation), this); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 	if (debug_view) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		MeshInstance *dm = debug_view->cast_to<MeshInstance>(); | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 		if (is_enabled()) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			dm->set_material_override(get_tree()->get_debug_navigation_material()); | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			dm->set_material_override(get_tree()->get_debug_navigation_disabled_material()); | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 	update_gizmo(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool NavigationMeshInstance::is_enabled() const { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return enabled; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void NavigationMeshInstance::_notification(int p_what) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	switch (p_what) { | 
					
						
							| 
									
										
										
										
											2014-11-05 21:20:42 -03:00
										 |  |  | 		case NOTIFICATION_ENTER_TREE: { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			Spatial *c = this; | 
					
						
							|  |  |  | 			while (c) { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				navigation = c->cast_to<Navigation>(); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 				if (navigation) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					if (enabled && navmesh.is_valid()) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 						nav_id = navigation->navmesh_create(navmesh, get_relative_transform(navigation), this); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				c = c->get_parent_spatial(); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 			if (navmesh.is_valid() && get_tree()->is_debugging_navigation_hint()) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				MeshInstance *dm = memnew(MeshInstance); | 
					
						
							|  |  |  | 				dm->set_mesh(navmesh->get_debug_mesh()); | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 				if (is_enabled()) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 					dm->set_material_override(get_tree()->get_debug_navigation_material()); | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 					dm->set_material_override(get_tree()->get_debug_navigation_disabled_material()); | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				add_child(dm); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				debug_view = dm; | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 		} break; | 
					
						
							|  |  |  | 		case NOTIFICATION_TRANSFORM_CHANGED: { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			if (navigation && nav_id != -1) { | 
					
						
							|  |  |  | 				navigation->navmesh_set_transform(nav_id, get_relative_transform(navigation)); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} break; | 
					
						
							| 
									
										
										
										
											2014-11-05 21:20:42 -03:00
										 |  |  | 		case NOTIFICATION_EXIT_TREE: { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if (navigation) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				if (nav_id != -1) { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 					navigation->navmesh_remove(nav_id); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 					nav_id = -1; | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if (debug_view) { | 
					
						
							|  |  |  | 				debug_view->queue_delete(); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				debug_view = NULL; | 
					
						
							| 
									
										
										
										
											2015-09-20 13:03:46 -03:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			navigation = NULL; | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 		} break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void NavigationMeshInstance::set_navigation_mesh(const Ref<NavigationMesh> &p_navmesh) { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	if (p_navmesh == navmesh) | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	if (navigation && nav_id != -1) { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 		navigation->navmesh_remove(nav_id); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		nav_id = -1; | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	navmesh = p_navmesh; | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (navigation && navmesh.is_valid() && enabled) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		nav_id = navigation->navmesh_create(navmesh, get_relative_transform(navigation), this); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-29 12:16:36 +01:00
										 |  |  | 	if (debug_view && navmesh.is_valid()) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		debug_view->cast_to<MeshInstance>()->set_mesh(navmesh->get_debug_mesh()); | 
					
						
							| 
									
										
										
										
											2016-12-29 12:16:36 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 	update_gizmo(); | 
					
						
							| 
									
										
										
										
											2016-05-17 18:27:15 -03:00
										 |  |  | 	update_configuration_warning(); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Ref<NavigationMesh> NavigationMeshInstance::get_navigation_mesh() const { | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return navmesh; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-17 18:27:15 -03:00
										 |  |  | String NavigationMeshInstance::get_configuration_warning() const { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-13 10:45:50 -03:00
										 |  |  | 	if (!is_visible_in_tree() || !is_inside_tree()) | 
					
						
							| 
									
										
										
										
											2016-05-17 18:27:15 -03:00
										 |  |  | 		return String(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!navmesh.is_valid()) { | 
					
						
							|  |  |  | 		return TTR("A NavigationMesh resource must be set or created for this node to work."); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	const Spatial *c = this; | 
					
						
							|  |  |  | 	while (c) { | 
					
						
							| 
									
										
										
										
											2016-05-17 18:27:15 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (c->cast_to<Navigation>()) | 
					
						
							|  |  |  | 			return String(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		c = c->get_parent()->cast_to<Spatial>(); | 
					
						
							| 
									
										
										
										
											2016-05-17 18:27:15 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return TTR("NavigationMeshInstance must be a child or grandchild to a Navigation node. It only provides navigation data."); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | void NavigationMeshInstance::_bind_methods() { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_navigation_mesh", "navmesh"), &NavigationMeshInstance::set_navigation_mesh); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_navigation_mesh"), &NavigationMeshInstance::get_navigation_mesh); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationMeshInstance::set_enabled); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationMeshInstance::is_enabled); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NavigationMeshInstance::NavigationMeshInstance() { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	debug_view = NULL; | 
					
						
							|  |  |  | 	navigation = NULL; | 
					
						
							|  |  |  | 	nav_id = -1; | 
					
						
							|  |  |  | 	enabled = true; | 
					
						
							| 
									
										
										
										
											2017-01-12 20:35:46 -03:00
										 |  |  | 	set_notify_transform(true); | 
					
						
							| 
									
										
										
										
											2014-08-01 22:10:38 -03:00
										 |  |  | } |