Browse Source

Update NavigationAgent to use query_path

This paves the way for having agents respond to link traversal.
Josh Jones 2 years ago
parent
commit
a2c53b881b

+ 8 - 0
doc/classes/NavigationPathQueryResult2D.xml

@@ -8,6 +8,14 @@
 	</description>
 	<tutorials>
 	</tutorials>
+	<methods>
+		<method name="reset">
+			<return type="void" />
+			<description>
+				Reset the result object to its initial state.  This is useful to reuse the object across multiple queries.
+			</description>
+		</method>
+	</methods>
 	<members>
 		<member name="path" type="PackedVector2Array" setter="set_path" getter="get_path" default="PackedVector2Array()">
 			The resulting path array from the navigation query. All path array positions are in global coordinates. Without customized query parameters this is the same path as returned by [method NavigationServer2D.map_get_path].

+ 8 - 0
doc/classes/NavigationPathQueryResult3D.xml

@@ -8,6 +8,14 @@
 	</description>
 	<tutorials>
 	</tutorials>
+	<methods>
+		<method name="reset">
+			<return type="void" />
+			<description>
+				Reset the result object to its initial state.  This is useful to reuse the object across multiple queries.
+			</description>
+		</method>
+	</methods>
 	<members>
 		<member name="path" type="PackedVector3Array" setter="set_path" getter="get_path" default="PackedVector3Array()">
 			The resulting path array from the navigation query. All path array positions are in global coordinates. Without customized query parameters this is the same path as returned by [method NavigationServer3D.map_get_path].

+ 33 - 9
scene/2d/navigation_agent_2d.cpp

@@ -178,6 +178,13 @@ NavigationAgent2D::NavigationAgent2D() {
 	set_time_horizon(20.0);
 	set_radius(10.0);
 	set_max_speed(200.0);
+
+	// Preallocate query and result objects to improve performance.
+	navigation_query = Ref<NavigationPathQueryParameters2D>();
+	navigation_query.instantiate();
+
+	navigation_result = Ref<NavigationPathQueryResult2D>();
+	navigation_result.instantiate();
 }
 
 NavigationAgent2D::~NavigationAgent2D() {
@@ -314,6 +321,8 @@ Vector2 NavigationAgent2D::get_target_location() const {
 
 Vector2 NavigationAgent2D::get_next_location() {
 	update_navigation();
+
+	const Vector<Vector2> &navigation_path = navigation_result->get_path();
 	if (navigation_path.size() == 0) {
 		ERR_FAIL_COND_V_MSG(agent_parent == nullptr, Vector2(), "The agent has no parent.");
 		return agent_parent->get_global_position();
@@ -322,6 +331,10 @@ Vector2 NavigationAgent2D::get_next_location() {
 	}
 }
 
+const Vector<Vector2> &NavigationAgent2D::get_nav_path() const {
+	return navigation_result->get_path();
+}
+
 real_t NavigationAgent2D::distance_to_target() const {
 	ERR_FAIL_COND_V_MSG(agent_parent == nullptr, 0.0, "The agent has no parent.");
 	return agent_parent->get_global_position().distance_to(target_location);
@@ -342,6 +355,8 @@ bool NavigationAgent2D::is_navigation_finished() {
 
 Vector2 NavigationAgent2D::get_final_location() {
 	update_navigation();
+
+	const Vector<Vector2> &navigation_path = navigation_result->get_path();
 	if (navigation_path.size() == 0) {
 		return Vector2();
 	}
@@ -391,22 +406,24 @@ void NavigationAgent2D::update_navigation() {
 
 	update_frame_id = Engine::get_singleton()->get_physics_frames();
 
-	Vector2 o = agent_parent->get_global_position();
+	Vector2 origin = agent_parent->get_global_position();
 
 	bool reload_path = false;
 
 	if (NavigationServer2D::get_singleton()->agent_is_map_changed(agent)) {
 		reload_path = true;
-	} else if (navigation_path.size() == 0) {
+	} else if (navigation_result->get_path().size() == 0) {
 		reload_path = true;
 	} else {
 		// Check if too far from the navigation path
 		if (nav_path_index > 0) {
+			const Vector<Vector2> &navigation_path = navigation_result->get_path();
+
 			Vector2 segment[2];
 			segment[0] = navigation_path[nav_path_index - 1];
 			segment[1] = navigation_path[nav_path_index];
-			Vector2 p = Geometry2D::get_closest_point_to_segment(o, segment);
-			if (o.distance_to(p) >= path_max_distance) {
+			Vector2 p = Geometry2D::get_closest_point_to_segment(origin, segment);
+			if (origin.distance_to(p) >= path_max_distance) {
 				// To faraway, reload path
 				reload_path = true;
 			}
@@ -414,24 +431,31 @@ void NavigationAgent2D::update_navigation() {
 	}
 
 	if (reload_path) {
+		navigation_query->set_start_position(origin);
+		navigation_query->set_target_position(target_location);
+		navigation_query->set_navigation_layers(navigation_layers);
+
 		if (map_override.is_valid()) {
-			navigation_path = NavigationServer2D::get_singleton()->map_get_path(map_override, o, target_location, true, navigation_layers);
+			navigation_query->set_map(map_override);
 		} else {
-			navigation_path = NavigationServer2D::get_singleton()->map_get_path(agent_parent->get_world_2d()->get_navigation_map(), o, target_location, true, navigation_layers);
+			navigation_query->set_map(agent_parent->get_world_2d()->get_navigation_map());
 		}
+
+		NavigationServer2D::get_singleton()->query_path(navigation_query, navigation_result);
 		navigation_finished = false;
 		nav_path_index = 0;
 		emit_signal(SNAME("path_changed"));
 	}
 
-	if (navigation_path.size() == 0) {
+	if (navigation_result->get_path().size() == 0) {
 		return;
 	}
 
 	// Check if we can advance the navigation path
 	if (navigation_finished == false) {
 		// Advances to the next far away location.
-		while (o.distance_to(navigation_path[nav_path_index]) < path_desired_distance) {
+		const Vector<Vector2> &navigation_path = navigation_result->get_path();
+		while (origin.distance_to(navigation_path[nav_path_index]) < path_desired_distance) {
 			nav_path_index += 1;
 			if (nav_path_index == navigation_path.size()) {
 				_check_distance_to_target();
@@ -445,7 +469,7 @@ void NavigationAgent2D::update_navigation() {
 }
 
 void NavigationAgent2D::_request_repath() {
-	navigation_path.clear();
+	navigation_result->reset();
 	target_reached = false;
 	navigation_finished = false;
 	update_frame_id = 0;

+ 5 - 4
scene/2d/navigation_agent_2d.h

@@ -34,6 +34,8 @@
 #include "scene/main/node.h"
 
 class Node2D;
+class NavigationPathQueryParameters2D;
+class NavigationPathQueryResult2D;
 
 class NavigationAgent2D : public Node {
 	GDCLASS(NavigationAgent2D, Node);
@@ -58,7 +60,8 @@ class NavigationAgent2D : public Node {
 	real_t path_max_distance = 3.0;
 
 	Vector2 target_location;
-	Vector<Vector2> navigation_path;
+	Ref<NavigationPathQueryParameters2D> navigation_query;
+	Ref<NavigationPathQueryResult2D> navigation_result;
 	int nav_path_index = 0;
 	bool velocity_submitted = false;
 	Vector2 prev_safe_velocity;
@@ -138,9 +141,7 @@ public:
 
 	Vector2 get_next_location();
 
-	Vector<Vector2> get_nav_path() const {
-		return navigation_path;
-	}
+	const Vector<Vector2> &get_nav_path() const;
 
 	int get_nav_path_index() const {
 		return nav_path_index;

+ 33 - 9
scene/3d/navigation_agent_3d.cpp

@@ -185,6 +185,13 @@ NavigationAgent3D::NavigationAgent3D() {
 	set_radius(1.0);
 	set_max_speed(10.0);
 	set_ignore_y(true);
+
+	// Preallocate query and result objects to improve performance.
+	navigation_query = Ref<NavigationPathQueryParameters3D>();
+	navigation_query.instantiate();
+
+	navigation_result = Ref<NavigationPathQueryResult3D>();
+	navigation_result.instantiate();
 }
 
 NavigationAgent3D::~NavigationAgent3D() {
@@ -330,6 +337,8 @@ Vector3 NavigationAgent3D::get_target_location() const {
 
 Vector3 NavigationAgent3D::get_next_location() {
 	update_navigation();
+
+	const Vector<Vector3> &navigation_path = navigation_result->get_path();
 	if (navigation_path.size() == 0) {
 		ERR_FAIL_COND_V_MSG(agent_parent == nullptr, Vector3(), "The agent has no parent.");
 		return agent_parent->get_global_transform().origin;
@@ -338,6 +347,10 @@ Vector3 NavigationAgent3D::get_next_location() {
 	}
 }
 
+const Vector<Vector3> &NavigationAgent3D::get_nav_path() const {
+	return navigation_result->get_path();
+}
+
 real_t NavigationAgent3D::distance_to_target() const {
 	ERR_FAIL_COND_V_MSG(agent_parent == nullptr, 0.0, "The agent has no parent.");
 	return agent_parent->get_global_transform().origin.distance_to(target_location);
@@ -358,6 +371,8 @@ bool NavigationAgent3D::is_navigation_finished() {
 
 Vector3 NavigationAgent3D::get_final_location() {
 	update_navigation();
+
+	const Vector<Vector3> &navigation_path = navigation_result->get_path();
 	if (navigation_path.size() == 0) {
 		return Vector3();
 	}
@@ -406,24 +421,26 @@ void NavigationAgent3D::update_navigation() {
 
 	update_frame_id = Engine::get_singleton()->get_physics_frames();
 
-	Vector3 o = agent_parent->get_global_transform().origin;
+	Vector3 origin = agent_parent->get_global_transform().origin;
 
 	bool reload_path = false;
 
 	if (NavigationServer3D::get_singleton()->agent_is_map_changed(agent)) {
 		reload_path = true;
-	} else if (navigation_path.size() == 0) {
+	} else if (navigation_result->get_path().size() == 0) {
 		reload_path = true;
 	} else {
 		// Check if too far from the navigation path
 		if (nav_path_index > 0) {
+			const Vector<Vector3> &navigation_path = navigation_result->get_path();
+
 			Vector3 segment[2];
 			segment[0] = navigation_path[nav_path_index - 1];
 			segment[1] = navigation_path[nav_path_index];
 			segment[0].y -= navigation_height_offset;
 			segment[1].y -= navigation_height_offset;
-			Vector3 p = Geometry3D::get_closest_point_to_segment(o, segment);
-			if (o.distance_to(p) >= path_max_distance) {
+			Vector3 p = Geometry3D::get_closest_point_to_segment(origin, segment);
+			if (origin.distance_to(p) >= path_max_distance) {
 				// To faraway, reload path
 				reload_path = true;
 			}
@@ -431,24 +448,31 @@ void NavigationAgent3D::update_navigation() {
 	}
 
 	if (reload_path) {
+		navigation_query->set_start_position(origin);
+		navigation_query->set_target_position(target_location);
+		navigation_query->set_navigation_layers(navigation_layers);
+
 		if (map_override.is_valid()) {
-			navigation_path = NavigationServer3D::get_singleton()->map_get_path(map_override, o, target_location, true, navigation_layers);
+			navigation_query->set_map(map_override);
 		} else {
-			navigation_path = NavigationServer3D::get_singleton()->map_get_path(agent_parent->get_world_3d()->get_navigation_map(), o, target_location, true, navigation_layers);
+			navigation_query->set_map(agent_parent->get_world_3d()->get_navigation_map());
 		}
+
+		NavigationServer3D::get_singleton()->query_path(navigation_query, navigation_result);
 		navigation_finished = false;
 		nav_path_index = 0;
 		emit_signal(SNAME("path_changed"));
 	}
 
-	if (navigation_path.size() == 0) {
+	if (navigation_result->get_path().size() == 0) {
 		return;
 	}
 
 	// Check if we can advance the navigation path
 	if (navigation_finished == false) {
 		// Advances to the next far away location.
-		while (o.distance_to(navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0)) < path_desired_distance) {
+		const Vector<Vector3> &navigation_path = navigation_result->get_path();
+		while (origin.distance_to(navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0)) < path_desired_distance) {
 			nav_path_index += 1;
 			if (nav_path_index == navigation_path.size()) {
 				_check_distance_to_target();
@@ -462,7 +486,7 @@ void NavigationAgent3D::update_navigation() {
 }
 
 void NavigationAgent3D::_request_repath() {
-	navigation_path.clear();
+	navigation_result->reset();
 	target_reached = false;
 	navigation_finished = false;
 	update_frame_id = 0;

+ 5 - 4
scene/3d/navigation_agent_3d.h

@@ -34,6 +34,8 @@
 #include "scene/main/node.h"
 
 class Node3D;
+class NavigationPathQueryParameters3D;
+class NavigationPathQueryResult3D;
 
 class NavigationAgent3D : public Node {
 	GDCLASS(NavigationAgent3D, Node);
@@ -60,7 +62,8 @@ class NavigationAgent3D : public Node {
 	real_t path_max_distance = 3.0;
 
 	Vector3 target_location;
-	Vector<Vector3> navigation_path;
+	Ref<NavigationPathQueryParameters3D> navigation_query;
+	Ref<NavigationPathQueryResult3D> navigation_result;
 	int nav_path_index = 0;
 	bool velocity_submitted = false;
 	Vector3 prev_safe_velocity;
@@ -150,9 +153,7 @@ public:
 
 	Vector3 get_next_location();
 
-	Vector<Vector3> get_nav_path() const {
-		return navigation_path;
-	}
+	const Vector<Vector3> &get_nav_path() const;
 
 	int get_nav_path_index() const {
 		return nav_path_index;

+ 6 - 0
servers/navigation/navigation_path_query_result_2d.cpp

@@ -38,9 +38,15 @@ const Vector<Vector2> &NavigationPathQueryResult2D::get_path() const {
 	return path;
 }
 
+void NavigationPathQueryResult2D::reset() {
+	path.clear();
+}
+
 void NavigationPathQueryResult2D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_path", "path"), &NavigationPathQueryResult2D::set_path);
 	ClassDB::bind_method(D_METHOD("get_path"), &NavigationPathQueryResult2D::get_path);
 
+	ClassDB::bind_method(D_METHOD("reset"), &NavigationPathQueryResult2D::reset);
+
 	ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "path"), "set_path", "get_path");
 }

+ 2 - 0
servers/navigation/navigation_path_query_result_2d.h

@@ -45,6 +45,8 @@ protected:
 public:
 	void set_path(const Vector<Vector2> &p_path);
 	const Vector<Vector2> &get_path() const;
+
+	void reset();
 };
 
 #endif // NAVIGATION_PATH_QUERY_RESULT_2D_H

+ 6 - 0
servers/navigation/navigation_path_query_result_3d.cpp

@@ -38,9 +38,15 @@ const Vector<Vector3> &NavigationPathQueryResult3D::get_path() const {
 	return path;
 }
 
+void NavigationPathQueryResult3D::reset() {
+	path.clear();
+}
+
 void NavigationPathQueryResult3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_path", "path"), &NavigationPathQueryResult3D::set_path);
 	ClassDB::bind_method(D_METHOD("get_path"), &NavigationPathQueryResult3D::get_path);
 
+	ClassDB::bind_method(D_METHOD("reset"), &NavigationPathQueryResult3D::reset);
+
 	ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "path"), "set_path", "get_path");
 }

+ 2 - 0
servers/navigation/navigation_path_query_result_3d.h

@@ -45,6 +45,8 @@ protected:
 public:
 	void set_path(const Vector<Vector3> &p_path);
 	const Vector<Vector3> &get_path() const;
+
+	void reset();
 };
 
 #endif // NAVIGATION_PATH_QUERY_RESULT_3D_H