summaryrefslogtreecommitdiff
path: root/scene/2d
diff options
context:
space:
mode:
Diffstat (limited to 'scene/2d')
-rw-r--r--scene/2d/navigation_agent_2d.cpp71
-rw-r--r--scene/2d/navigation_agent_2d.h19
-rw-r--r--scene/2d/tile_map.cpp1
3 files changed, 82 insertions, 9 deletions
diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp
index 67c32dffb4..62afe0d89b 100644
--- a/scene/2d/navigation_agent_2d.cpp
+++ b/scene/2d/navigation_agent_2d.cpp
@@ -70,6 +70,9 @@ void NavigationAgent2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_navigation_layer_value", "layer_number", "value"), &NavigationAgent2D::set_navigation_layer_value);
ClassDB::bind_method(D_METHOD("get_navigation_layer_value", "layer_number"), &NavigationAgent2D::get_navigation_layer_value);
+ ClassDB::bind_method(D_METHOD("set_path_metadata_flags", "flags"), &NavigationAgent2D::set_path_metadata_flags);
+ ClassDB::bind_method(D_METHOD("get_path_metadata_flags"), &NavigationAgent2D::get_path_metadata_flags);
+
ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationAgent2D::set_navigation_map);
ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationAgent2D::get_navigation_map);
@@ -79,6 +82,7 @@ void NavigationAgent2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_next_location"), &NavigationAgent2D::get_next_location);
ClassDB::bind_method(D_METHOD("distance_to_target"), &NavigationAgent2D::distance_to_target);
ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &NavigationAgent2D::set_velocity);
+ ClassDB::bind_method(D_METHOD("get_current_navigation_result"), &NavigationAgent2D::get_current_navigation_result);
ClassDB::bind_method(D_METHOD("get_current_navigation_path"), &NavigationAgent2D::get_current_navigation_path);
ClassDB::bind_method(D_METHOD("get_current_navigation_path_index"), &NavigationAgent2D::get_current_navigation_path_index);
ClassDB::bind_method(D_METHOD("is_target_reached"), &NavigationAgent2D::is_target_reached);
@@ -94,6 +98,7 @@ void NavigationAgent2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "target_desired_distance", PROPERTY_HINT_RANGE, "0.1,100,0.01,suffix:px"), "set_target_desired_distance", "get_target_desired_distance");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,100,1,suffix:px"), "set_path_max_distance", "get_path_max_distance");
ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "path_metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_path_metadata_flags", "get_path_metadata_flags");
ADD_GROUP("Avoidance", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled");
@@ -105,6 +110,8 @@ void NavigationAgent2D::_bind_methods() {
ADD_SIGNAL(MethodInfo("path_changed"));
ADD_SIGNAL(MethodInfo("target_reached"));
+ ADD_SIGNAL(MethodInfo("waypoint_reached", PropertyInfo(Variant::DICTIONARY, "details")));
+ ADD_SIGNAL(MethodInfo("link_reached", PropertyInfo(Variant::DICTIONARY, "details")));
ADD_SIGNAL(MethodInfo("navigation_finished"));
ADD_SIGNAL(MethodInfo("velocity_computed", PropertyInfo(Variant::VECTOR2, "safe_velocity")));
}
@@ -161,7 +168,7 @@ void NavigationAgent2D::_notification(int p_what) {
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
- if (agent_parent) {
+ if (agent_parent && target_position_submitted) {
if (avoidance_enabled) {
// agent_position on NavigationServer is avoidance only and has nothing to do with pathfinding
// no point in flooding NavigationServer queue with agent position updates that get send to the void if avoidance is not used
@@ -256,6 +263,14 @@ bool NavigationAgent2D::get_navigation_layer_value(int p_layer_number) const {
return get_navigation_layers() & (1 << (p_layer_number - 1));
}
+void NavigationAgent2D::set_path_metadata_flags(BitField<NavigationPathQueryParameters2D::PathMetadataFlags> p_path_metadata_flags) {
+ if (path_metadata_flags == p_path_metadata_flags) {
+ return;
+ }
+
+ path_metadata_flags = p_path_metadata_flags;
+}
+
void NavigationAgent2D::set_navigation_map(RID p_navigation_map) {
map_override = p_navigation_map;
NavigationServer2D::get_singleton()->agent_set_map(agent, map_override);
@@ -314,6 +329,7 @@ real_t NavigationAgent2D::get_path_max_distance() {
void NavigationAgent2D::set_target_location(Vector2 p_location) {
target_location = p_location;
+ target_position_submitted = true;
_request_repath();
}
@@ -333,10 +349,6 @@ Vector2 NavigationAgent2D::get_next_location() {
}
}
-const Vector<Vector2> &NavigationAgent2D::get_current_navigation_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);
@@ -402,6 +414,9 @@ void NavigationAgent2D::update_navigation() {
if (!agent_parent->is_inside_tree()) {
return;
}
+ if (!target_position_submitted) {
+ return;
+ }
if (update_frame_id == Engine::get_singleton()->get_physics_frames()) {
return;
}
@@ -436,6 +451,7 @@ void NavigationAgent2D::update_navigation() {
navigation_query->set_start_position(origin);
navigation_query->set_target_position(target_location);
navigation_query->set_navigation_layers(navigation_layers);
+ navigation_query->set_metadata_flags(path_metadata_flags);
if (map_override.is_valid()) {
navigation_query->set_map(map_override);
@@ -457,12 +473,57 @@ void NavigationAgent2D::update_navigation() {
if (navigation_finished == false) {
// Advances to the next far away location.
const Vector<Vector2> &navigation_path = navigation_result->get_path();
+ const Vector<int32_t> &navigation_path_types = navigation_result->get_path_types();
+ const TypedArray<RID> &navigation_path_rids = navigation_result->get_path_rids();
+ const Vector<int64_t> &navigation_path_owners = navigation_result->get_path_owner_ids();
+
while (origin.distance_to(navigation_path[navigation_path_index]) < path_desired_distance) {
+ Dictionary details;
+
+ const Vector2 waypoint = navigation_path[navigation_path_index];
+ details[SNAME("location")] = waypoint;
+
+ int waypoint_type = -1;
+ if (path_metadata_flags.has_flag(NavigationPathQueryParameters2D::PathMetadataFlags::PATH_METADATA_INCLUDE_TYPES)) {
+ const NavigationPathQueryResult2D::PathSegmentType type = NavigationPathQueryResult2D::PathSegmentType(navigation_path_types[navigation_path_index]);
+
+ details[SNAME("type")] = type;
+ waypoint_type = type;
+ }
+
+ if (path_metadata_flags.has_flag(NavigationPathQueryParameters2D::PathMetadataFlags::PATH_METADATA_INCLUDE_RIDS)) {
+ details[SNAME("rid")] = navigation_path_rids[navigation_path_index];
+ }
+
+ if (path_metadata_flags.has_flag(NavigationPathQueryParameters2D::PathMetadataFlags::PATH_METADATA_INCLUDE_OWNERS)) {
+ const ObjectID waypoint_owner_id = ObjectID(navigation_path_owners[navigation_path_index]);
+
+ // Get a reference to the owning object.
+ Object *owner = nullptr;
+ if (waypoint_owner_id.is_valid()) {
+ owner = ObjectDB::get_instance(waypoint_owner_id);
+ }
+
+ details[SNAME("owner")] = owner;
+ }
+
+ // Emit a signal for the waypoint
+ emit_signal(SNAME("waypoint_reached"), details);
+
+ // Emit a signal if we've reached a navigation link
+ if (waypoint_type == NavigationPathQueryResult2D::PATH_SEGMENT_TYPE_LINK) {
+ emit_signal(SNAME("link_reached"), details);
+ }
+
+ // Move to the next waypoint on the list
navigation_path_index += 1;
+
+ // Check to see if we've finished our route
if (navigation_path_index == navigation_path.size()) {
_check_distance_to_target();
navigation_path_index -= 1;
navigation_finished = true;
+ target_position_submitted = false;
emit_signal(SNAME("navigation_finished"));
break;
}
diff --git a/scene/2d/navigation_agent_2d.h b/scene/2d/navigation_agent_2d.h
index 2c77bdc8db..439192cce7 100644
--- a/scene/2d/navigation_agent_2d.h
+++ b/scene/2d/navigation_agent_2d.h
@@ -32,10 +32,10 @@
#define NAVIGATION_AGENT_2D_H
#include "scene/main/node.h"
+#include "servers/navigation/navigation_path_query_parameters_2d.h"
+#include "servers/navigation/navigation_path_query_result_2d.h"
class Node2D;
-class NavigationPathQueryParameters2D;
-class NavigationPathQueryResult2D;
class NavigationAgent2D : public Node {
GDCLASS(NavigationAgent2D, Node);
@@ -48,6 +48,7 @@ class NavigationAgent2D : public Node {
bool avoidance_enabled = false;
uint32_t navigation_layers = 1;
+ BitField<NavigationPathQueryParameters2D::PathMetadataFlags> path_metadata_flags = NavigationPathQueryParameters2D::PathMetadataFlags::PATH_METADATA_INCLUDE_ALL;
real_t path_desired_distance = 1.0;
real_t target_desired_distance = 1.0;
@@ -60,6 +61,7 @@ class NavigationAgent2D : public Node {
real_t path_max_distance = 3.0;
Vector2 target_location;
+ bool target_position_submitted = false;
Ref<NavigationPathQueryParameters2D> navigation_query;
Ref<NavigationPathQueryResult2D> navigation_result;
int navigation_path_index = 0;
@@ -95,6 +97,11 @@ public:
void set_navigation_layer_value(int p_layer_number, bool p_value);
bool get_navigation_layer_value(int p_layer_number) const;
+ void set_path_metadata_flags(BitField<NavigationPathQueryParameters2D::PathMetadataFlags> p_flags);
+ BitField<NavigationPathQueryParameters2D::PathMetadataFlags> get_path_metadata_flags() const {
+ return path_metadata_flags;
+ }
+
void set_navigation_map(RID p_navigation_map);
RID get_navigation_map() const;
@@ -141,8 +148,12 @@ public:
Vector2 get_next_location();
- const Vector<Vector2> &get_current_navigation_path() const;
-
+ Ref<NavigationPathQueryResult2D> get_current_navigation_result() const {
+ return navigation_result;
+ }
+ const Vector<Vector2> &get_current_navigation_path() const {
+ return navigation_result->get_path();
+ }
int get_current_navigation_path_index() const {
return navigation_path_index;
}
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 6ab13c9aa7..3136752a2e 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -1739,6 +1739,7 @@ void TileMap::_navigation_update_dirty_quadrants(SelfList<TileMapQuadrant>::List
NavigationServer2D::get_singleton()->region_set_owner_id(region, get_instance_id());
NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map());
NavigationServer2D::get_singleton()->region_set_transform(region, tilemap_xform * tile_transform);
+ NavigationServer2D::get_singleton()->region_set_navigation_layers(region, tile_set->get_navigation_layer_layers(layer_index));
NavigationServer2D::get_singleton()->region_set_navigation_polygon(region, navigation_polygon);
q.navigation_regions[E_cell].write[layer_index] = region;
}