Skip to content

Commit 75e141f

Browse files
author
Pawel Miniszewski
committed
Allow filtering navmesh queries by links
(cherry picked from commit a5b9aeb)
1 parent f110f15 commit 75e141f

10 files changed

Lines changed: 214 additions & 28 deletions

doc/classes/NavigationPathQueryParameters2D.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,18 @@
1010
<link title="Using NavigationPathQueryObjects">$DOCS_URL/tutorials/navigation/navigation_using_navigationpathqueryobjects.html</link>
1111
</tutorials>
1212
<members>
13+
<member name="excluded_links" type="RID[]" setter="set_excluded_links" getter="get_excluded_links" default="[]">
14+
The list of link [RID]s that will be excluded from the path query. Use [method NavigationLink2D.get_rid] to get the [RID] associated with a [NavigationLink2D] node. Excluded links are skipped during pathfinding so the resulting path will not traverse them.
15+
[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.
16+
</member>
1317
<member name="excluded_regions" type="RID[]" setter="set_excluded_regions" getter="get_excluded_regions" default="[]">
1418
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.
1519
[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.
1620
</member>
21+
<member name="included_links" type="RID[]" setter="set_included_links" getter="get_included_links" default="[]">
22+
The list of link [RID]s that will be included by the path query. Use [method NavigationLink2D.get_rid] to get the [RID] associated with a [NavigationLink2D] node. If left empty all links are included. If a link ends up being both included and excluded at the same time it will be excluded.
23+
[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.
24+
</member>
1725
<member name="included_regions" type="RID[]" setter="set_included_regions" getter="get_included_regions" default="[]">
1826
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.
1927
[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.

doc/classes/NavigationPathQueryParameters3D.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,18 @@
1010
<link title="Using NavigationPathQueryObjects">$DOCS_URL/tutorials/navigation/navigation_using_navigationpathqueryobjects.html</link>
1111
</tutorials>
1212
<members>
13+
<member name="excluded_links" type="RID[]" setter="set_excluded_links" getter="get_excluded_links" default="[]">
14+
The list of link [RID]s that will be excluded from the path query. Use [method NavigationLink3D.get_rid] to get the [RID] associated with a [NavigationLink3D] node. Excluded links are skipped during pathfinding so the resulting path will not traverse them.
15+
[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.
16+
</member>
1317
<member name="excluded_regions" type="RID[]" setter="set_excluded_regions" getter="get_excluded_regions" default="[]">
1418
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.
1519
[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.
1620
</member>
21+
<member name="included_links" type="RID[]" setter="set_included_links" getter="get_included_links" default="[]">
22+
The list of link [RID]s that will be included by the path query. Use [method NavigationLink3D.get_rid] to get the [RID] associated with a [NavigationLink3D] node. If left empty all links are included. If a link ends up being both included and excluded at the same time it will be excluded.
23+
[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.
24+
</member>
1725
<member name="included_regions" type="RID[]" setter="set_included_regions" getter="get_included_regions" default="[]">
1826
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.
1927
[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.

modules/navigation_2d/2d/nav_mesh_queries_2d.cpp

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,29 @@ void NavMeshQueries2D::map_query_path(NavMap2D *p_map, const Ref<NavigationPathQ
181181
}
182182
}
183183

184+
const TypedArray<RID> &_excluded_links = p_query_parameters->get_excluded_links();
185+
const TypedArray<RID> &_included_links = p_query_parameters->get_included_links();
186+
187+
uint32_t _excluded_link_count = _excluded_links.size();
188+
uint32_t _included_link_count = _included_links.size();
189+
190+
query_task.exclude_links = _excluded_link_count > 0;
191+
query_task.include_links = _included_link_count > 0;
192+
193+
if (query_task.exclude_links) {
194+
query_task.excluded_links.resize(_excluded_link_count);
195+
for (uint32_t i = 0; i < _excluded_link_count; i++) {
196+
query_task.excluded_links[i] = _excluded_links[i];
197+
}
198+
}
199+
200+
if (query_task.include_links) {
201+
query_task.included_links.resize(_included_link_count);
202+
for (uint32_t i = 0; i < _included_link_count; i++) {
203+
query_task.included_links[i] = _included_links[i];
204+
}
205+
}
206+
184207
switch (p_query_parameters->get_pathfinding_algorithm()) {
185208
case NavigationPathQueryParameters2D::PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR: {
186209
query_task.pathfinding_algorithm = PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR;
@@ -1153,7 +1176,7 @@ bool NavMeshQueries2D::_query_task_is_connection_owner_usable(const NavMeshPathQ
11531176
return owner_usable;
11541177
}
11551178

1156-
if (p_query_task.exclude_regions || p_query_task.include_regions) {
1179+
if (p_query_task.exclude_regions || p_query_task.include_regions || p_query_task.exclude_links || p_query_task.include_links) {
11571180
switch (p_owner->get_type()) {
11581181
case NavigationEnums2D::PathSegmentType::PATH_SEGMENT_TYPE_REGION: {
11591182
if (p_query_task.exclude_regions && p_query_task.excluded_regions.has(p_owner->get_self())) {
@@ -1165,22 +1188,31 @@ bool NavMeshQueries2D::_query_task_is_connection_owner_usable(const NavMeshPathQ
11651188
}
11661189
} break;
11671190
case NavigationEnums2D::PathSegmentType::PATH_SEGMENT_TYPE_LINK: {
1168-
const LocalVector<Polygon> &link_polygons = p_owner->get_navmesh_polygons();
1169-
if (link_polygons.size() != 2) {
1170-
// Not usable. Whatever this is, it is not a valid connected link.
1171-
owner_usable = false;
1172-
} else {
1173-
const RID link_start_region = link_polygons[0].owner->get_self();
1174-
const RID link_end_region = link_polygons[1].owner->get_self();
1175-
if (p_query_task.exclude_regions && (p_query_task.excluded_regions.has(link_start_region) || p_query_task.excluded_regions.has(link_end_region))) {
1176-
// Not usable. Exclude region filter is active and at least one region of the link is excluded.
1177-
owner_usable = false;
1178-
}
1179-
if (p_query_task.include_regions && (!p_query_task.included_regions.has(link_start_region) || !p_query_task.excluded_regions.has(link_end_region))) {
1180-
// Not usable. Include region filter is active and not both regions of the links are included.
1191+
if (p_query_task.exclude_regions || p_query_task.include_regions) {
1192+
const LocalVector<Polygon> &link_polygons = p_owner->get_navmesh_polygons();
1193+
if (link_polygons.size() != 2) {
1194+
// Not usable. Whatever this is, it is not a valid connected link.
11811195
owner_usable = false;
1196+
} else {
1197+
const RID link_start_region = link_polygons[0].owner->get_self();
1198+
const RID link_end_region = link_polygons[1].owner->get_self();
1199+
if (p_query_task.exclude_regions && (p_query_task.excluded_regions.has(link_start_region) || p_query_task.excluded_regions.has(link_end_region))) {
1200+
// Not usable. Exclude region filter is active and at least one region of the link is excluded.
1201+
owner_usable = false;
1202+
}
1203+
if (p_query_task.include_regions && (!p_query_task.included_regions.has(link_start_region) || !p_query_task.included_regions.has(link_end_region))) {
1204+
// Not usable. Include region filter is active and not both regions of the links are included.
1205+
owner_usable = false;
1206+
}
11821207
}
11831208
}
1209+
if (owner_usable && p_query_task.exclude_links && p_query_task.excluded_links.has(p_owner->get_self())) {
1210+
// Not usable. Exclude link filter is active and this link is excluded.
1211+
owner_usable = false;
1212+
} else if (owner_usable && p_query_task.include_links && !p_query_task.included_links.has(p_owner->get_self())) {
1213+
// Not usable. Include link filter is active and this link is not included.
1214+
owner_usable = false;
1215+
}
11841216
} break;
11851217
}
11861218
}

modules/navigation_2d/2d/nav_mesh_queries_2d.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ class NavMeshQueries2D {
7979
LocalVector<RID> excluded_regions;
8080
LocalVector<RID> included_regions;
8181

82+
bool exclude_links = false;
83+
bool include_links = false;
84+
LocalVector<RID> excluded_links;
85+
LocalVector<RID> included_links;
86+
8287
float path_return_max_length = 0.0;
8388
float path_return_max_radius = 0.0;
8489
int path_search_max_polygons = NavigationDefaults2D::path_search_max_polygons;

modules/navigation_3d/3d/nav_mesh_queries_3d.cpp

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,29 @@ void NavMeshQueries3D::map_query_path(NavMap3D *map, const Ref<NavigationPathQue
181181
}
182182
}
183183

184+
const TypedArray<RID> &_excluded_links = p_query_parameters->get_excluded_links();
185+
const TypedArray<RID> &_included_links = p_query_parameters->get_included_links();
186+
187+
uint32_t _excluded_link_count = _excluded_links.size();
188+
uint32_t _included_link_count = _included_links.size();
189+
190+
query_task.exclude_links = _excluded_link_count > 0;
191+
query_task.include_links = _included_link_count > 0;
192+
193+
if (query_task.exclude_links) {
194+
query_task.excluded_links.resize(_excluded_link_count);
195+
for (uint32_t i = 0; i < _excluded_link_count; i++) {
196+
query_task.excluded_links[i] = _excluded_links[i];
197+
}
198+
}
199+
200+
if (query_task.include_links) {
201+
query_task.included_links.resize(_included_link_count);
202+
for (uint32_t i = 0; i < _included_link_count; i++) {
203+
query_task.included_links[i] = _included_links[i];
204+
}
205+
}
206+
184207
switch (p_query_parameters->get_pathfinding_algorithm()) {
185208
case NavigationPathQueryParameters3D::PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR: {
186209
query_task.pathfinding_algorithm = PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR;
@@ -1294,7 +1317,7 @@ bool NavMeshQueries3D::_query_task_is_connection_owner_usable(const NavMeshPathQ
12941317
return owner_usable;
12951318
}
12961319

1297-
if (p_query_task.exclude_regions || p_query_task.include_regions) {
1320+
if (p_query_task.exclude_regions || p_query_task.include_regions || p_query_task.exclude_links || p_query_task.include_links) {
12981321
switch (p_owner->get_type()) {
12991322
case NavigationEnums3D::PathSegmentType::PATH_SEGMENT_TYPE_REGION: {
13001323
if (p_query_task.exclude_regions && p_query_task.excluded_regions.has(p_owner->get_self())) {
@@ -1306,22 +1329,31 @@ bool NavMeshQueries3D::_query_task_is_connection_owner_usable(const NavMeshPathQ
13061329
}
13071330
} break;
13081331
case NavigationEnums3D::PathSegmentType::PATH_SEGMENT_TYPE_LINK: {
1309-
const LocalVector<Polygon> &link_polygons = p_owner->get_navmesh_polygons();
1310-
if (link_polygons.size() != 2) {
1311-
// Not usable. Whatever this is, it is not a valid connected link.
1312-
owner_usable = false;
1313-
} else {
1314-
const RID link_start_region = link_polygons[0].owner->get_self();
1315-
const RID link_end_region = link_polygons[1].owner->get_self();
1316-
if (p_query_task.exclude_regions && (p_query_task.excluded_regions.has(link_start_region) || p_query_task.excluded_regions.has(link_end_region))) {
1317-
// Not usable. Exclude region filter is active and at least one region of the link is excluded.
1318-
owner_usable = false;
1319-
}
1320-
if (p_query_task.include_regions && (!p_query_task.included_regions.has(link_start_region) || !p_query_task.excluded_regions.has(link_end_region))) {
1321-
// Not usable. Include region filter is active and not both regions of the links are included.
1332+
if (p_query_task.exclude_regions || p_query_task.include_regions) {
1333+
const LocalVector<Polygon> &link_polygons = p_owner->get_navmesh_polygons();
1334+
if (link_polygons.size() != 2) {
1335+
// Not usable. Whatever this is, it is not a valid connected link.
13221336
owner_usable = false;
1337+
} else {
1338+
const RID link_start_region = link_polygons[0].owner->get_self();
1339+
const RID link_end_region = link_polygons[1].owner->get_self();
1340+
if (p_query_task.exclude_regions && (p_query_task.excluded_regions.has(link_start_region) || p_query_task.excluded_regions.has(link_end_region))) {
1341+
// Not usable. Exclude region filter is active and at least one region of the link is excluded.
1342+
owner_usable = false;
1343+
}
1344+
if (p_query_task.include_regions && (!p_query_task.included_regions.has(link_start_region) || !p_query_task.included_regions.has(link_end_region))) {
1345+
// Not usable. Include region filter is active and not both regions of the links are included.
1346+
owner_usable = false;
1347+
}
13231348
}
13241349
}
1350+
if (owner_usable && p_query_task.exclude_links && p_query_task.excluded_links.has(p_owner->get_self())) {
1351+
// Not usable. Exclude link filter is active and this link is excluded.
1352+
owner_usable = false;
1353+
} else if (owner_usable && p_query_task.include_links && !p_query_task.included_links.has(p_owner->get_self())) {
1354+
// Not usable. Include link filter is active and this link is not included.
1355+
owner_usable = false;
1356+
}
13251357
} break;
13261358
}
13271359
}

modules/navigation_3d/3d/nav_mesh_queries_3d.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ class NavMeshQueries3D {
7979
LocalVector<RID> excluded_regions;
8080
LocalVector<RID> included_regions;
8181

82+
bool exclude_links = false;
83+
bool include_links = false;
84+
LocalVector<RID> excluded_links;
85+
LocalVector<RID> included_links;
86+
8287
float path_return_max_length = 0.0;
8388
float path_return_max_radius = 0.0;
8489
int path_search_max_polygons = NavigationDefaults3D::path_search_max_polygons;

servers/navigation_2d/navigation_path_query_parameters_2d.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,38 @@ TypedArray<RID> NavigationPathQueryParameters2D::get_excluded_regions() const {
136136
return r_regions;
137137
}
138138

139+
void NavigationPathQueryParameters2D::set_included_links(const TypedArray<RID> &p_links) {
140+
_included_links.resize(p_links.size());
141+
for (uint32_t i = 0; i < _included_links.size(); i++) {
142+
_included_links[i] = p_links[i];
143+
}
144+
}
145+
146+
TypedArray<RID> NavigationPathQueryParameters2D::get_included_links() const {
147+
TypedArray<RID> r_links;
148+
r_links.resize(_included_links.size());
149+
for (uint32_t i = 0; i < _included_links.size(); i++) {
150+
r_links[i] = _included_links[i];
151+
}
152+
return r_links;
153+
}
154+
155+
void NavigationPathQueryParameters2D::set_excluded_links(const TypedArray<RID> &p_links) {
156+
_excluded_links.resize(p_links.size());
157+
for (uint32_t i = 0; i < _excluded_links.size(); i++) {
158+
_excluded_links[i] = p_links[i];
159+
}
160+
}
161+
162+
TypedArray<RID> NavigationPathQueryParameters2D::get_excluded_links() const {
163+
TypedArray<RID> r_links;
164+
r_links.resize(_excluded_links.size());
165+
for (uint32_t i = 0; i < _excluded_links.size(); i++) {
166+
r_links[i] = _excluded_links[i];
167+
}
168+
return r_links;
169+
}
170+
139171
void NavigationPathQueryParameters2D::set_path_return_max_length(float p_length) {
140172
path_return_max_length = MAX(0.0, p_length);
141173
}
@@ -202,6 +234,12 @@ void NavigationPathQueryParameters2D::_bind_methods() {
202234
ClassDB::bind_method(D_METHOD("set_excluded_regions", "regions"), &NavigationPathQueryParameters2D::set_excluded_regions);
203235
ClassDB::bind_method(D_METHOD("get_excluded_regions"), &NavigationPathQueryParameters2D::get_excluded_regions);
204236

237+
ClassDB::bind_method(D_METHOD("set_included_links", "links"), &NavigationPathQueryParameters2D::set_included_links);
238+
ClassDB::bind_method(D_METHOD("get_included_links"), &NavigationPathQueryParameters2D::get_included_links);
239+
240+
ClassDB::bind_method(D_METHOD("set_excluded_links", "links"), &NavigationPathQueryParameters2D::set_excluded_links);
241+
ClassDB::bind_method(D_METHOD("get_excluded_links"), &NavigationPathQueryParameters2D::get_excluded_links);
242+
205243
ClassDB::bind_method(D_METHOD("set_path_return_max_length", "length"), &NavigationPathQueryParameters2D::set_path_return_max_length);
206244
ClassDB::bind_method(D_METHOD("get_path_return_max_length"), &NavigationPathQueryParameters2D::get_path_return_max_length);
207245

@@ -225,6 +263,8 @@ void NavigationPathQueryParameters2D::_bind_methods() {
225263
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "simplify_epsilon"), "set_simplify_epsilon", "get_simplify_epsilon");
226264
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "excluded_regions", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_excluded_regions", "get_excluded_regions");
227265
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "included_regions", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_included_regions", "get_included_regions");
266+
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "excluded_links", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_excluded_links", "get_excluded_links");
267+
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "included_links", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_included_links", "get_included_links");
228268
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_return_max_length"), "set_path_return_max_length", "get_path_return_max_length");
229269
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_return_max_radius"), "set_path_return_max_radius", "get_path_return_max_radius");
230270
ADD_PROPERTY(PropertyInfo(Variant::INT, "path_search_max_polygons"), "set_path_search_max_polygons", "get_path_search_max_polygons");

servers/navigation_2d/navigation_path_query_parameters_2d.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ class NavigationPathQueryParameters2D : public RefCounted {
7171

7272
LocalVector<RID> _excluded_regions;
7373
LocalVector<RID> _included_regions;
74+
LocalVector<RID> _excluded_links;
75+
LocalVector<RID> _included_links;
7476

7577
float path_return_max_length = 0.0;
7678
float path_return_max_radius = 0.0;
@@ -111,6 +113,12 @@ class NavigationPathQueryParameters2D : public RefCounted {
111113
void set_included_regions(const TypedArray<RID> &p_regions);
112114
TypedArray<RID> get_included_regions() const;
113115

116+
void set_excluded_links(const TypedArray<RID> &p_links);
117+
TypedArray<RID> get_excluded_links() const;
118+
119+
void set_included_links(const TypedArray<RID> &p_links);
120+
TypedArray<RID> get_included_links() const;
121+
114122
void set_path_return_max_length(float p_length);
115123
float get_path_return_max_length() const;
116124

0 commit comments

Comments
 (0)