Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add path query region filters #102766

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/classes/NavigationPathQueryParameters2D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
<link title="Using NavigationPathQueryObjects">$DOCS_URL/tutorials/navigation/navigation_using_navigationpathqueryobjects.html</link>
</tutorials>
<members>
<member name="excluded_regions" type="RID[]" setter="set_excluded_regions" getter="get_excluded_regions" default="[]">
The list of region [RID]s that will be excluded from the path query. Use [method NavigationRegion2D.get_rid] to get the [RID] associated with a [NavigationRegion2D] node.
[b]Note:[/b] The returned array is copied and any changes to it will not update the original property value. To update the value you need to modify the returned array, and then set it to the property again.
</member>
<member name="included_regions" type="RID[]" setter="set_included_regions" getter="get_included_regions" default="[]">
The list of region [RID]s that will be included by the path query. Use [method NavigationRegion2D.get_rid] to get the [RID] associated with a [NavigationRegion2D] node. If left empty all regions are included. If a region ends up being both included and excluded at the same time it will be excluded.
[b]Note:[/b] The returned array is copied and any changes to it will not update the original property value. To update the value you need to modify the returned array, and then set it to the property again.
</member>
<member name="map" type="RID" setter="set_map" getter="get_map" default="RID()">
The navigation map [RID] used in the path query.
</member>
Expand Down
8 changes: 8 additions & 0 deletions doc/classes/NavigationPathQueryParameters3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
<link title="Using NavigationPathQueryObjects">$DOCS_URL/tutorials/navigation/navigation_using_navigationpathqueryobjects.html</link>
</tutorials>
<members>
<member name="excluded_regions" type="RID[]" setter="set_excluded_regions" getter="get_excluded_regions" default="[]">
The list of region [RID]s that will be excluded from the path query. Use [method NavigationRegion3D.get_rid] to get the [RID] associated with a [NavigationRegion3D] node.
[b]Note:[/b] The returned array is copied and any changes to it will not update the original property value. To update the value you need to modify the returned array, and then set it to the property again.
</member>
<member name="included_regions" type="RID[]" setter="set_included_regions" getter="get_included_regions" default="[]">
The list of region [RID]s that will be included by the path query. Use [method NavigationRegion3D.get_rid] to get the [RID] associated with a [NavigationRegion3D] node. If left empty all regions are included. If a region ends up being both included and excluded at the same time it will be excluded.
[b]Note:[/b] The returned array is copied and any changes to it will not update the original property value. To update the value you need to modify the returned array, and then set it to the property again.
</member>
<member name="map" type="RID" setter="set_map" getter="get_map" default="RID()">
The navigation map [RID] used in the path query.
</member>
Expand Down
2 changes: 2 additions & 0 deletions modules/navigation/2d/godot_navigation_server_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,8 @@ void GodotNavigationServer2D::query_path(const Ref<NavigationPathQueryParameters
query_parameters->set_metadata_flags((int64_t)p_query_parameters->get_metadata_flags());
query_parameters->set_simplify_path(p_query_parameters->get_simplify_path());
query_parameters->set_simplify_epsilon(p_query_parameters->get_simplify_epsilon());
query_parameters->set_excluded_regions(p_query_parameters->get_excluded_regions());
query_parameters->set_included_regions(p_query_parameters->get_included_regions());

Ref<NavigationPathQueryResult3D> query_result;
query_result.instantiate();
Expand Down
4 changes: 4 additions & 0 deletions modules/navigation/3d/nav_base_iteration_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#ifndef NAV_BASE_ITERATION_3D_H
#define NAV_BASE_ITERATION_3D_H

#include "../nav_utils.h"

#include "servers/navigation/navigation_utilities.h"

struct NavBaseIteration {
Expand All @@ -43,6 +45,7 @@ struct NavBaseIteration {
ObjectID owner_object_id;
RID owner_rid;
bool owner_use_edge_connections = false;
LocalVector<gd::Polygon> navmesh_polygons;

bool get_enabled() const { return enabled; }
NavigationUtilities::PathSegmentType get_type() const { return owner_type; }
Expand All @@ -52,6 +55,7 @@ struct NavBaseIteration {
real_t get_enter_cost() const { return enter_cost; }
real_t get_travel_cost() const { return travel_cost; }
bool get_use_edge_connections() const { return owner_use_edge_connections; }
const LocalVector<gd::Polygon> &get_navmesh_polygons() const { return navmesh_polygons; }
};

#endif // NAV_BASE_ITERATION_3D_H
65 changes: 65 additions & 0 deletions modules/navigation/3d/nav_mesh_queries_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,29 @@ void NavMeshQueries3D::map_query_path(NavMap *map, const Ref<NavigationPathQuery
query_task.navigation_layers = p_query_parameters->get_navigation_layers();
query_task.callback = p_callback;

const TypedArray<RID> &_excluded_regions = p_query_parameters->get_excluded_regions();
const TypedArray<RID> &_included_regions = p_query_parameters->get_included_regions();

uint32_t _excluded_region_count = _excluded_regions.size();
uint32_t _included_region_count = _included_regions.size();

query_task.exclude_regions = _excluded_region_count > 0;
query_task.include_regions = _included_region_count > 0;

if (query_task.exclude_regions) {
query_task.excluded_regions.resize(_excluded_region_count);
for (uint32_t i = 0; i < _excluded_region_count; i++) {
query_task.excluded_regions[i] = _excluded_regions[i];
}
}

if (query_task.include_regions) {
query_task.included_regions.resize(_included_region_count);
for (uint32_t i = 0; i < _included_region_count; i++) {
query_task.included_regions[i] = _included_regions[i];
}
}

switch (p_query_parameters->get_pathfinding_algorithm()) {
case NavigationPathQueryParameters3D::PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR: {
query_task.pathfinding_algorithm = PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR;
Expand Down Expand Up @@ -217,6 +240,13 @@ void NavMeshQueries3D::_query_task_find_start_end_positions(NavMeshPathQueryTask
continue;
}

if (p_query_task.exclude_regions && p_query_task.excluded_regions.has(region.get_self())) {
continue;
}
if (p_query_task.include_regions && !p_query_task.included_regions.has(region.get_self())) {
continue;
}

// Find the initial poly and the end poly on this map.
for (const gd::Polygon &p : region.get_navmesh_polygons()) {
// Only consider the polygon if it in a region with compatible layers.
Expand Down Expand Up @@ -295,6 +325,41 @@ void NavMeshQueries3D::_query_task_build_path_corridor(NavMeshPathQueryTask3D &p

// Only consider the connection to another polygon if this polygon is in a region with compatible layers.
const NavBaseIteration *owner = connection.polygon->owner;
bool skip_connection = false;
if (p_query_task.exclude_regions || p_query_task.include_regions) {
switch (owner->get_type()) {
case NavigationUtilities::PathSegmentType::PATH_SEGMENT_TYPE_REGION: {
if (p_query_task.exclude_regions && p_query_task.excluded_regions.has(owner->get_self())) {
skip_connection = true;
} else if (p_query_task.include_regions && !p_query_task.included_regions.has(owner->get_self())) {
skip_connection = true;
}
} break;
case NavigationUtilities::PathSegmentType::PATH_SEGMENT_TYPE_LINK: {
const LocalVector<gd::Polygon> &link_polygons = owner->get_navmesh_polygons();
if (link_polygons.size() != 2) {
// Whatever this is, it is not a valid connected link.
skip_connection = true;
} else {
const RID link_start_region = link_polygons[0].owner->get_self();
const RID link_end_region = link_polygons[1].owner->get_self();
if (p_query_task.exclude_regions && (p_query_task.excluded_regions.has(link_start_region) || p_query_task.excluded_regions.has(link_end_region))) {
// At least one region of the link is excluded so skip.
skip_connection = true;
}
if (p_query_task.include_regions && (!p_query_task.included_regions.has(link_start_region) || !p_query_task.excluded_regions.has(link_end_region))) {
// Not both regions of the link are included so skip.
skip_connection = true;
}
}
} break;
}
}

if (skip_connection) {
continue;
}

if ((p_navigation_layers & owner->get_navigation_layers()) != 0) {
Vector3 pathway[2] = { connection.pathway_start, connection.pathway_end };
const Vector3 new_entry = Geometry3D::get_closest_point_to_segment(least_cost_poly.entry, pathway);
Expand Down
4 changes: 4 additions & 0 deletions modules/navigation/3d/nav_mesh_queries_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ class NavMeshQueries3D {
PathPostProcessing path_postprocessing = PathPostProcessing::PATH_POSTPROCESSING_CORRIDORFUNNEL;
bool simplify_path = false;
real_t simplify_epsilon = 0.0;
bool exclude_regions = false;
bool include_regions = false;
LocalVector<RID> excluded_regions;
Copy link
Contributor

@kiroxas kiroxas Feb 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there really a way to have both of those active at the same time (include and exclude) ? Seems like we either exclude region or include region, but doing both at the same time seems ... odd ? Seems like the use case is either I want evrything except those (exclude list) or only search inside those (include list), but having both active at the same time seems error prone ? Maybe there is some case I'm not thinking of though. If this is the case, then all could be simplified, as we only need one local vector and all those previous if could become switch cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will just happen with users that both lists are used and some RID slips in both lists. That is how it always goes with users when both include and exclude options are available so better account for it.

LocalVector<RID> included_regions;

// Path building.
Vector3 begin_position;
Expand Down
2 changes: 0 additions & 2 deletions modules/navigation/3d/nav_region_iteration_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,10 @@

struct NavRegionIteration : NavBaseIteration {
Transform3D transform;
LocalVector<gd::Polygon> navmesh_polygons;
real_t surface_area = 0.0;
AABB bounds;

const Transform3D &get_transform() const { return transform; }
const LocalVector<gd::Polygon> &get_navmesh_polygons() const { return navmesh_polygons; }
real_t get_surface_area() const { return surface_area; }
AABB get_bounds() const { return bounds; }
};
Expand Down
1 change: 0 additions & 1 deletion modules/navigation/nav_link.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ struct NavLinkIteration : NavBaseIteration {
bool bidirectional = true;
Vector3 start_position;
Vector3 end_position;
LocalVector<gd::Polygon> navmesh_polygons;

Vector3 get_start_position() const { return start_position; }
Vector3 get_end_position() const { return end_position; }
Expand Down
40 changes: 40 additions & 0 deletions servers/navigation/navigation_path_query_parameters_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,38 @@ real_t NavigationPathQueryParameters2D::get_simplify_epsilon() const {
return simplify_epsilon;
}

void NavigationPathQueryParameters2D::set_included_regions(const TypedArray<RID> &p_regions) {
_included_regions.resize(p_regions.size());
for (uint32_t i = 0; i < _included_regions.size(); i++) {
_included_regions[i] = p_regions[i];
}
}

TypedArray<RID> NavigationPathQueryParameters2D::get_included_regions() const {
TypedArray<RID> r_regions;
smix8 marked this conversation as resolved.
Show resolved Hide resolved
r_regions.resize(_included_regions.size());
for (uint32_t i = 0; i < _included_regions.size(); i++) {
r_regions[i] = _included_regions[i];
}
return r_regions;
}

void NavigationPathQueryParameters2D::set_excluded_regions(const TypedArray<RID> &p_regions) {
_excluded_regions.resize(p_regions.size());
for (uint32_t i = 0; i < _excluded_regions.size(); i++) {
_excluded_regions[i] = p_regions[i];
}
}

TypedArray<RID> NavigationPathQueryParameters2D::get_excluded_regions() const {
TypedArray<RID> r_regions;
r_regions.resize(_excluded_regions.size());
for (uint32_t i = 0; i < _excluded_regions.size(); i++) {
r_regions[i] = _excluded_regions[i];
}
return r_regions;
}

void NavigationPathQueryParameters2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pathfinding_algorithm", "pathfinding_algorithm"), &NavigationPathQueryParameters2D::set_pathfinding_algorithm);
ClassDB::bind_method(D_METHOD("get_pathfinding_algorithm"), &NavigationPathQueryParameters2D::get_pathfinding_algorithm);
Expand Down Expand Up @@ -130,6 +162,12 @@ void NavigationPathQueryParameters2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_simplify_epsilon", "epsilon"), &NavigationPathQueryParameters2D::set_simplify_epsilon);
ClassDB::bind_method(D_METHOD("get_simplify_epsilon"), &NavigationPathQueryParameters2D::get_simplify_epsilon);

ClassDB::bind_method(D_METHOD("set_included_regions", "regions"), &NavigationPathQueryParameters2D::set_included_regions);
ClassDB::bind_method(D_METHOD("get_included_regions"), &NavigationPathQueryParameters2D::get_included_regions);

ClassDB::bind_method(D_METHOD("set_excluded_regions", "regions"), &NavigationPathQueryParameters2D::set_excluded_regions);
ClassDB::bind_method(D_METHOD("get_excluded_regions"), &NavigationPathQueryParameters2D::get_excluded_regions);

ADD_PROPERTY(PropertyInfo(Variant::RID, "map"), "set_map", "get_map");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "start_position"), "set_start_position", "get_start_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "target_position"), "set_target_position", "get_target_position");
Expand All @@ -139,6 +177,8 @@ void NavigationPathQueryParameters2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_metadata_flags", "get_metadata_flags");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "simplify_path"), "set_simplify_path", "get_simplify_path");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "simplify_epsilon"), "set_simplify_epsilon", "get_simplify_epsilon");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "excluded_regions", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_excluded_regions", "get_excluded_regions");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "included_regions", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_included_regions", "get_included_regions");

BIND_ENUM_CONSTANT(PATHFINDING_ALGORITHM_ASTAR);

Expand Down
8 changes: 8 additions & 0 deletions servers/navigation/navigation_path_query_parameters_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ class NavigationPathQueryParameters2D : public RefCounted {
BitField<PathMetadataFlags> metadata_flags = PATH_METADATA_INCLUDE_ALL;
bool simplify_path = false;
real_t simplify_epsilon = 0.0;
LocalVector<RID> _excluded_regions;
LocalVector<RID> _included_regions;

public:
void set_pathfinding_algorithm(const PathfindingAlgorithm p_pathfinding_algorithm);
Expand Down Expand Up @@ -97,6 +99,12 @@ class NavigationPathQueryParameters2D : public RefCounted {

void set_simplify_epsilon(real_t p_epsilon);
real_t get_simplify_epsilon() const;

void set_excluded_regions(const TypedArray<RID> &p_regions);
TypedArray<RID> get_excluded_regions() const;

void set_included_regions(const TypedArray<RID> &p_regions);
TypedArray<RID> get_included_regions() const;
};

VARIANT_ENUM_CAST(NavigationPathQueryParameters2D::PathfindingAlgorithm);
Expand Down
40 changes: 40 additions & 0 deletions servers/navigation/navigation_path_query_parameters_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,38 @@ real_t NavigationPathQueryParameters3D::get_simplify_epsilon() const {
return simplify_epsilon;
}

void NavigationPathQueryParameters3D::set_included_regions(const TypedArray<RID> &p_regions) {
_included_regions.resize(p_regions.size());
for (uint32_t i = 0; i < _included_regions.size(); i++) {
_included_regions[i] = p_regions[i];
}
}

TypedArray<RID> NavigationPathQueryParameters3D::get_included_regions() const {
TypedArray<RID> r_regions;
r_regions.resize(_included_regions.size());
for (uint32_t i = 0; i < _included_regions.size(); i++) {
r_regions[i] = _included_regions[i];
}
return r_regions;
}

void NavigationPathQueryParameters3D::set_excluded_regions(const TypedArray<RID> &p_regions) {
_excluded_regions.resize(p_regions.size());
for (uint32_t i = 0; i < _excluded_regions.size(); i++) {
_excluded_regions[i] = p_regions[i];
}
}

TypedArray<RID> NavigationPathQueryParameters3D::get_excluded_regions() const {
TypedArray<RID> r_regions;
r_regions.resize(_excluded_regions.size());
for (uint32_t i = 0; i < _excluded_regions.size(); i++) {
r_regions[i] = _excluded_regions[i];
}
return r_regions;
}

void NavigationPathQueryParameters3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pathfinding_algorithm", "pathfinding_algorithm"), &NavigationPathQueryParameters3D::set_pathfinding_algorithm);
ClassDB::bind_method(D_METHOD("get_pathfinding_algorithm"), &NavigationPathQueryParameters3D::get_pathfinding_algorithm);
Expand Down Expand Up @@ -130,6 +162,12 @@ void NavigationPathQueryParameters3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_simplify_epsilon", "epsilon"), &NavigationPathQueryParameters3D::set_simplify_epsilon);
ClassDB::bind_method(D_METHOD("get_simplify_epsilon"), &NavigationPathQueryParameters3D::get_simplify_epsilon);

ClassDB::bind_method(D_METHOD("set_included_regions", "regions"), &NavigationPathQueryParameters3D::set_included_regions);
ClassDB::bind_method(D_METHOD("get_included_regions"), &NavigationPathQueryParameters3D::get_included_regions);

ClassDB::bind_method(D_METHOD("set_excluded_regions", "regions"), &NavigationPathQueryParameters3D::set_excluded_regions);
ClassDB::bind_method(D_METHOD("get_excluded_regions"), &NavigationPathQueryParameters3D::get_excluded_regions);

ADD_PROPERTY(PropertyInfo(Variant::RID, "map"), "set_map", "get_map");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "start_position"), "set_start_position", "get_start_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position"), "set_target_position", "get_target_position");
Expand All @@ -139,6 +177,8 @@ void NavigationPathQueryParameters3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "metadata_flags", PROPERTY_HINT_FLAGS, "Include Types,Include RIDs,Include Owners"), "set_metadata_flags", "get_metadata_flags");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "simplify_path"), "set_simplify_path", "get_simplify_path");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "simplify_epsilon"), "set_simplify_epsilon", "get_simplify_epsilon");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "excluded_regions", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_excluded_regions", "get_excluded_regions");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "included_regions", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_included_regions", "get_included_regions");

BIND_ENUM_CONSTANT(PATHFINDING_ALGORITHM_ASTAR);

Expand Down
8 changes: 8 additions & 0 deletions servers/navigation/navigation_path_query_parameters_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ class NavigationPathQueryParameters3D : public RefCounted {
BitField<PathMetadataFlags> metadata_flags = PATH_METADATA_INCLUDE_ALL;
bool simplify_path = false;
real_t simplify_epsilon = 0.0;
LocalVector<RID> _excluded_regions;
LocalVector<RID> _included_regions;

public:
void set_pathfinding_algorithm(const PathfindingAlgorithm p_pathfinding_algorithm);
Expand Down Expand Up @@ -97,6 +99,12 @@ class NavigationPathQueryParameters3D : public RefCounted {

void set_simplify_epsilon(real_t p_epsilon);
real_t get_simplify_epsilon() const;

void set_excluded_regions(const TypedArray<RID> &p_regions);
TypedArray<RID> get_excluded_regions() const;

void set_included_regions(const TypedArray<RID> &p_regions);
TypedArray<RID> get_included_regions() const;
};

VARIANT_ENUM_CAST(NavigationPathQueryParameters3D::PathfindingAlgorithm);
Expand Down
Loading