| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2020-02-11 14:01:43 +01:00
										 |  |  | /*  navigation_obstacle_2d.cpp                                           */ | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							|  |  |  | /*                      https://godotengine.org                          */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							| 
									
										
										
										
											2020-02-11 14:01:43 +01:00
										 |  |  | /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01: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.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "navigation_obstacle_2d.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "scene/2d/collision_shape_2d.h"
 | 
					
						
							|  |  |  | #include "scene/2d/navigation_2d.h"
 | 
					
						
							|  |  |  | #include "scene/2d/physics_body_2d.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-27 15:21:27 -03:00
										 |  |  | #include "servers/navigation_server_2d.h"
 | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | void NavigationObstacle2D::_bind_methods() { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle2D::set_navigation_node); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle2D::get_navigation_node); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void NavigationObstacle2D::_notification(int p_what) { | 
					
						
							|  |  |  | 	switch (p_what) { | 
					
						
							|  |  |  | 		case NOTIFICATION_READY: { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			update_agent_shape(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Search the navigation node and set it
 | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				Navigation2D *nav = NULL; | 
					
						
							|  |  |  | 				Node *p = get_parent(); | 
					
						
							|  |  |  | 				while (p != NULL) { | 
					
						
							|  |  |  | 					nav = Object::cast_to<Navigation2D>(p); | 
					
						
							|  |  |  | 					if (nav != NULL) | 
					
						
							|  |  |  | 						p = NULL; | 
					
						
							|  |  |  | 					else | 
					
						
							|  |  |  | 						p = p->get_parent(); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				set_navigation(nav); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			set_physics_process_internal(true); | 
					
						
							|  |  |  | 		} break; | 
					
						
							|  |  |  | 		case NOTIFICATION_EXIT_TREE: { | 
					
						
							|  |  |  | 			set_navigation(NULL); | 
					
						
							|  |  |  | 			set_physics_process_internal(false); | 
					
						
							|  |  |  | 		} break; | 
					
						
							|  |  |  | 		case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { | 
					
						
							|  |  |  | 			Node2D *node = Object::cast_to<Node2D>(get_parent()); | 
					
						
							|  |  |  | 			if (node) { | 
					
						
							| 
									
										
										
										
											2020-03-27 15:21:27 -03:00
										 |  |  | 				NavigationServer2D::get_singleton()->agent_set_position(agent, node->get_global_transform().get_origin()); | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NavigationObstacle2D::NavigationObstacle2D() : | 
					
						
							|  |  |  | 		navigation(NULL), | 
					
						
							|  |  |  | 		agent(RID()) { | 
					
						
							| 
									
										
										
										
											2020-03-27 15:21:27 -03:00
										 |  |  | 	agent = NavigationServer2D::get_singleton()->agent_create(); | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NavigationObstacle2D::~NavigationObstacle2D() { | 
					
						
							| 
									
										
										
										
											2020-03-27 15:21:27 -03:00
										 |  |  | 	NavigationServer2D::get_singleton()->free(agent); | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | 	agent = RID(); // Pointless
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void NavigationObstacle2D::set_navigation(Navigation2D *p_nav) { | 
					
						
							|  |  |  | 	if (navigation == p_nav) | 
					
						
							|  |  |  | 		return; // Pointless
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	navigation = p_nav; | 
					
						
							| 
									
										
										
										
											2020-03-27 15:21:27 -03:00
										 |  |  | 	NavigationServer2D::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void NavigationObstacle2D::set_navigation_node(Node *p_nav) { | 
					
						
							|  |  |  | 	Navigation2D *nav = Object::cast_to<Navigation2D>(p_nav); | 
					
						
							|  |  |  | 	ERR_FAIL_COND(nav == NULL); | 
					
						
							|  |  |  | 	set_navigation(nav); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Node *NavigationObstacle2D::get_navigation_node() const { | 
					
						
							|  |  |  | 	return Object::cast_to<Node>(navigation); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String NavigationObstacle2D::get_configuration_warning() const { | 
					
						
							|  |  |  | 	if (!Object::cast_to<Node2D>(get_parent())) { | 
					
						
							|  |  |  | 		return TTR("The NavigationObstacle2D only serves to provide collision avoidance to a Node2D object."); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return String(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void NavigationObstacle2D::update_agent_shape() { | 
					
						
							|  |  |  | 	Node *node = get_parent(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Estimate the radius of this physics body
 | 
					
						
							|  |  |  | 	real_t radius = 0.0; | 
					
						
							|  |  |  | 	for (int i(0); i < node->get_child_count(); i++) { | 
					
						
							|  |  |  | 		// For each collision shape
 | 
					
						
							|  |  |  | 		CollisionShape2D *cs = Object::cast_to<CollisionShape2D>(node->get_child(i)); | 
					
						
							|  |  |  | 		if (cs) { | 
					
						
							|  |  |  | 			// Take the distance between the Body center to the shape center
 | 
					
						
							|  |  |  | 			real_t r = cs->get_transform().get_origin().length(); | 
					
						
							|  |  |  | 			if (cs->get_shape().is_valid()) { | 
					
						
							|  |  |  | 				// and add the enclosing shape radius
 | 
					
						
							|  |  |  | 				r += cs->get_shape()->get_enclosing_radius(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			Size2 s = cs->get_global_transform().get_scale(); | 
					
						
							|  |  |  | 			r *= MAX(s.x, s.y); | 
					
						
							|  |  |  | 			// Takes the biggest radius
 | 
					
						
							|  |  |  | 			radius = MAX(radius, r); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	Node2D *node_2d = Object::cast_to<Node2D>(node); | 
					
						
							|  |  |  | 	if (node_2d) { | 
					
						
							|  |  |  | 		Vector2 s = node_2d->get_global_transform().get_scale(); | 
					
						
							|  |  |  | 		radius *= MAX(s.x, s.y); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (radius == 0.0) | 
					
						
							|  |  |  | 		radius = 1.0; // Never a 0 radius
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Initialize the Agent as an object
 | 
					
						
							| 
									
										
										
										
											2020-03-27 15:21:27 -03:00
										 |  |  | 	NavigationServer2D::get_singleton()->agent_set_neighbor_dist(agent, 0.0); | 
					
						
							|  |  |  | 	NavigationServer2D::get_singleton()->agent_set_max_neighbors(agent, 0); | 
					
						
							|  |  |  | 	NavigationServer2D::get_singleton()->agent_set_time_horizon(agent, 0.0); | 
					
						
							|  |  |  | 	NavigationServer2D::get_singleton()->agent_set_radius(agent, radius); | 
					
						
							|  |  |  | 	NavigationServer2D::get_singleton()->agent_set_max_speed(agent, 0.0); | 
					
						
							| 
									
										
										
										
											2020-01-10 12:22:34 +01:00
										 |  |  | } |