You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2026-01-05 19:31:35 +00:00
Fix AStars to return empty path for disabled from point
This commit is contained in:
@@ -306,11 +306,17 @@ Vector3 AStar3D::get_closest_position_in_segment(const Vector3 &p_point) const {
|
||||
return closest_point;
|
||||
}
|
||||
|
||||
bool AStar3D::_solve(Point *begin_point, Point *end_point, bool p_allow_partial_path) {
|
||||
bool AStar3D::_solve(Point *p_begin_point, Point *p_end_point, bool p_allow_partial_path) {
|
||||
last_closest_point = nullptr;
|
||||
pass++;
|
||||
|
||||
if (!end_point->enabled && !p_allow_partial_path) {
|
||||
if (!p_begin_point->enabled) {
|
||||
return false;
|
||||
}
|
||||
if (p_begin_point == p_end_point) {
|
||||
return true;
|
||||
}
|
||||
if (!p_end_point->enabled && !p_allow_partial_path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -319,11 +325,11 @@ bool AStar3D::_solve(Point *begin_point, Point *end_point, bool p_allow_partial_
|
||||
LocalVector<Point *> open_list;
|
||||
SortArray<Point *, SortPoints> sorter;
|
||||
|
||||
begin_point->g_score = 0;
|
||||
begin_point->f_score = _estimate_cost(begin_point->id, end_point->id);
|
||||
begin_point->abs_g_score = 0;
|
||||
begin_point->abs_f_score = _estimate_cost(begin_point->id, end_point->id);
|
||||
open_list.push_back(begin_point);
|
||||
p_begin_point->g_score = 0;
|
||||
p_begin_point->f_score = _estimate_cost(p_begin_point->id, p_end_point->id);
|
||||
p_begin_point->abs_g_score = 0;
|
||||
p_begin_point->abs_f_score = _estimate_cost(p_begin_point->id, p_end_point->id);
|
||||
open_list.push_back(p_begin_point);
|
||||
|
||||
while (!open_list.is_empty()) {
|
||||
Point *p = open_list[0]; // The currently processed point.
|
||||
@@ -333,7 +339,7 @@ bool AStar3D::_solve(Point *begin_point, Point *end_point, bool p_allow_partial_
|
||||
last_closest_point = p;
|
||||
}
|
||||
|
||||
if (p == end_point) {
|
||||
if (p == p_end_point) {
|
||||
found_route = true;
|
||||
break;
|
||||
}
|
||||
@@ -370,7 +376,7 @@ bool AStar3D::_solve(Point *begin_point, Point *end_point, bool p_allow_partial_
|
||||
|
||||
e->prev_point = p;
|
||||
e->g_score = tentative_g_score;
|
||||
e->f_score = e->g_score + _estimate_cost(e->id, end_point->id);
|
||||
e->f_score = e->g_score + _estimate_cost(e->id, p_end_point->id);
|
||||
e->abs_g_score = tentative_g_score;
|
||||
e->abs_f_score = e->f_score - e->g_score;
|
||||
|
||||
@@ -428,12 +434,6 @@ Vector<Vector3> AStar3D::get_point_path(int64_t p_from_id, int64_t p_to_id, bool
|
||||
ERR_FAIL_COND_V_MSG(!b_entry, Vector<Vector3>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_to_id));
|
||||
Point *b = *b_entry;
|
||||
|
||||
if (a == b) {
|
||||
Vector<Vector3> ret;
|
||||
ret.push_back(a->pos);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Point *begin_point = a;
|
||||
Point *end_point = b;
|
||||
|
||||
@@ -482,16 +482,6 @@ Vector<int64_t> AStar3D::get_id_path(int64_t p_from_id, int64_t p_to_id, bool p_
|
||||
ERR_FAIL_COND_V_MSG(!b_entry, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_to_id));
|
||||
Point *b = *b_entry;
|
||||
|
||||
if (a == b) {
|
||||
Vector<int64_t> ret;
|
||||
ret.push_back(a->id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!a->enabled) {
|
||||
return Vector<int64_t>();
|
||||
}
|
||||
|
||||
Point *begin_point = a;
|
||||
Point *end_point = b;
|
||||
|
||||
@@ -738,11 +728,6 @@ Vector<Vector2> AStar2D::get_point_path(int64_t p_from_id, int64_t p_to_id, bool
|
||||
ERR_FAIL_COND_V_MSG(!b_entry, Vector<Vector2>(), vformat("Can't get point path. Point with id: %d doesn't exist.", p_to_id));
|
||||
AStar3D::Point *b = *b_entry;
|
||||
|
||||
if (a == b) {
|
||||
Vector<Vector2> ret = { Vector2(a->pos.x, a->pos.y) };
|
||||
return ret;
|
||||
}
|
||||
|
||||
AStar3D::Point *begin_point = a;
|
||||
AStar3D::Point *end_point = b;
|
||||
|
||||
@@ -791,16 +776,6 @@ Vector<int64_t> AStar2D::get_id_path(int64_t p_from_id, int64_t p_to_id, bool p_
|
||||
ERR_FAIL_COND_V_MSG(!to_entry, Vector<int64_t>(), vformat("Can't get id path. Point with id: %d doesn't exist.", p_to_id));
|
||||
AStar3D::Point *b = *to_entry;
|
||||
|
||||
if (a == b) {
|
||||
Vector<int64_t> ret;
|
||||
ret.push_back(a->id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!a->enabled) {
|
||||
return Vector<int64_t>();
|
||||
}
|
||||
|
||||
AStar3D::Point *begin_point = a;
|
||||
AStar3D::Point *end_point = b;
|
||||
|
||||
@@ -840,11 +815,17 @@ Vector<int64_t> AStar2D::get_id_path(int64_t p_from_id, int64_t p_to_id, bool p_
|
||||
return path;
|
||||
}
|
||||
|
||||
bool AStar2D::_solve(AStar3D::Point *begin_point, AStar3D::Point *end_point, bool p_allow_partial_path) {
|
||||
bool AStar2D::_solve(AStar3D::Point *p_begin_point, AStar3D::Point *p_end_point, bool p_allow_partial_path) {
|
||||
astar.last_closest_point = nullptr;
|
||||
astar.pass++;
|
||||
|
||||
if (!end_point->enabled && !p_allow_partial_path) {
|
||||
if (!p_begin_point->enabled) {
|
||||
return false;
|
||||
}
|
||||
if (p_begin_point == p_end_point) {
|
||||
return true;
|
||||
}
|
||||
if (!p_end_point->enabled && !p_allow_partial_path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -853,11 +834,11 @@ bool AStar2D::_solve(AStar3D::Point *begin_point, AStar3D::Point *end_point, boo
|
||||
LocalVector<AStar3D::Point *> open_list;
|
||||
SortArray<AStar3D::Point *, AStar3D::SortPoints> sorter;
|
||||
|
||||
begin_point->g_score = 0;
|
||||
begin_point->f_score = _estimate_cost(begin_point->id, end_point->id);
|
||||
begin_point->abs_g_score = 0;
|
||||
begin_point->abs_f_score = _estimate_cost(begin_point->id, end_point->id);
|
||||
open_list.push_back(begin_point);
|
||||
p_begin_point->g_score = 0;
|
||||
p_begin_point->f_score = _estimate_cost(p_begin_point->id, p_end_point->id);
|
||||
p_begin_point->abs_g_score = 0;
|
||||
p_begin_point->abs_f_score = _estimate_cost(p_begin_point->id, p_end_point->id);
|
||||
open_list.push_back(p_begin_point);
|
||||
|
||||
while (!open_list.is_empty()) {
|
||||
AStar3D::Point *p = open_list[0]; // The currently processed point.
|
||||
@@ -867,7 +848,7 @@ bool AStar2D::_solve(AStar3D::Point *begin_point, AStar3D::Point *end_point, boo
|
||||
astar.last_closest_point = p;
|
||||
}
|
||||
|
||||
if (p == end_point) {
|
||||
if (p == p_end_point) {
|
||||
found_route = true;
|
||||
break;
|
||||
}
|
||||
@@ -904,7 +885,7 @@ bool AStar2D::_solve(AStar3D::Point *begin_point, AStar3D::Point *end_point, boo
|
||||
|
||||
e->prev_point = p;
|
||||
e->g_score = tentative_g_score;
|
||||
e->f_score = e->g_score + _estimate_cost(e->id, end_point->id);
|
||||
e->f_score = e->g_score + _estimate_cost(e->id, p_end_point->id);
|
||||
e->abs_g_score = tentative_g_score;
|
||||
e->abs_f_score = e->f_score - e->g_score;
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ class AStar3D : public RefCounted {
|
||||
Point *last_closest_point = nullptr;
|
||||
bool neighbor_filter_enabled = false;
|
||||
|
||||
bool _solve(Point *begin_point, Point *end_point, bool p_allow_partial_path);
|
||||
bool _solve(Point *p_begin_point, Point *p_end_point, bool p_allow_partial_path);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
@@ -172,7 +172,7 @@ class AStar2D : public RefCounted {
|
||||
GDCLASS(AStar2D, RefCounted);
|
||||
AStar3D astar;
|
||||
|
||||
bool _solve(AStar3D::Point *begin_point, AStar3D::Point *end_point, bool p_allow_partial_path);
|
||||
bool _solve(AStar3D::Point *p_begin_point, AStar3D::Point *p_end_point, bool p_allow_partial_path);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
@@ -495,6 +495,12 @@ bool AStarGrid2D::_solve(Point *p_begin_point, Point *p_end_point, bool p_allow_
|
||||
last_closest_point = nullptr;
|
||||
pass++;
|
||||
|
||||
if (_get_solid_unchecked(p_begin_point->id)) {
|
||||
return false;
|
||||
}
|
||||
if (p_begin_point == p_end_point) {
|
||||
return true;
|
||||
}
|
||||
if (_get_solid_unchecked(p_end_point->id) && !p_allow_partial_path) {
|
||||
return false;
|
||||
}
|
||||
@@ -636,17 +642,8 @@ Vector<Vector2> AStarGrid2D::get_point_path(const Vector2i &p_from_id, const Vec
|
||||
ERR_FAIL_COND_V_MSG(!is_in_boundsv(p_from_id), Vector<Vector2>(), vformat("Can't get id path. Point %s out of bounds %s.", p_from_id, region));
|
||||
ERR_FAIL_COND_V_MSG(!is_in_boundsv(p_to_id), Vector<Vector2>(), vformat("Can't get id path. Point %s out of bounds %s.", p_to_id, region));
|
||||
|
||||
Point *a = _get_point(p_from_id.x, p_from_id.y);
|
||||
Point *b = _get_point(p_to_id.x, p_to_id.y);
|
||||
|
||||
if (a == b) {
|
||||
Vector<Vector2> ret;
|
||||
ret.push_back(a->pos);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Point *begin_point = a;
|
||||
Point *end_point = b;
|
||||
Point *begin_point = _get_point(p_from_id.x, p_from_id.y);
|
||||
Point *end_point = _get_point(p_to_id.x, p_to_id.y);
|
||||
|
||||
bool found_route = _solve(begin_point, end_point, p_allow_partial_path);
|
||||
if (!found_route) {
|
||||
@@ -689,17 +686,8 @@ TypedArray<Vector2i> AStarGrid2D::get_id_path(const Vector2i &p_from_id, const V
|
||||
ERR_FAIL_COND_V_MSG(!is_in_boundsv(p_from_id), TypedArray<Vector2i>(), vformat("Can't get id path. Point %s out of bounds %s.", p_from_id, region));
|
||||
ERR_FAIL_COND_V_MSG(!is_in_boundsv(p_to_id), TypedArray<Vector2i>(), vformat("Can't get id path. Point %s out of bounds %s.", p_to_id, region));
|
||||
|
||||
Point *a = _get_point(p_from_id.x, p_from_id.y);
|
||||
Point *b = _get_point(p_to_id.x, p_to_id.y);
|
||||
|
||||
if (a == b) {
|
||||
TypedArray<Vector2i> ret;
|
||||
ret.push_back(a->id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Point *begin_point = a;
|
||||
Point *end_point = b;
|
||||
Point *begin_point = _get_point(p_from_id.x, p_from_id.y);
|
||||
Point *end_point = _get_point(p_to_id.x, p_to_id.y);
|
||||
|
||||
bool found_route = _solve(begin_point, end_point, p_allow_partial_path);
|
||||
if (!found_route) {
|
||||
|
||||
@@ -152,7 +152,8 @@
|
||||
<param index="2" name="allow_partial_path" type="bool" default="false" />
|
||||
<description>
|
||||
Returns an array with the IDs of the points that form the path found by AStar2D between the given points. The array is ordered from the starting point to the ending point of the path.
|
||||
If there is no valid path to the target, and [param allow_partial_path] is [code]true[/code], returns a path to the point closest to the target that can be reached.
|
||||
If [param from_id] point is disabled, returns an empty array (even if [code]from_id == to_id[/code]).
|
||||
If [param from_id] point is not disabled, there is no valid path to the target, and [param allow_partial_path] is [code]true[/code], returns a path to the point closest to the target that can be reached.
|
||||
[b]Note:[/b] When [param allow_partial_path] is [code]true[/code] and [param to_id] is disabled the search may take an unusually long time to finish.
|
||||
[codeblocks]
|
||||
[gdscript]
|
||||
@@ -244,7 +245,8 @@
|
||||
<param index="2" name="allow_partial_path" type="bool" default="false" />
|
||||
<description>
|
||||
Returns an array with the points that are in the path found by AStar2D between the given points. The array is ordered from the starting point to the ending point of the path.
|
||||
If there is no valid path to the target, and [param allow_partial_path] is [code]true[/code], returns a path to the point closest to the target that can be reached.
|
||||
If [param from_id] point is disabled, returns an empty array (even if [code]from_id == to_id[/code]).
|
||||
If [param from_id] point is not disabled, there is no valid path to the target, and [param allow_partial_path] is [code]true[/code], returns a path to the point closest to the target that can be reached.
|
||||
[b]Note:[/b] This method is not thread-safe; it can only be used from a single [Thread] at a given time. Consider using [Mutex] to ensure exclusive access to one thread to avoid race conditions.
|
||||
Additionally, when [param allow_partial_path] is [code]true[/code] and [param to_id] is disabled the search may take an unusually long time to finish.
|
||||
</description>
|
||||
|
||||
@@ -193,7 +193,8 @@
|
||||
<param index="2" name="allow_partial_path" type="bool" default="false" />
|
||||
<description>
|
||||
Returns an array with the IDs of the points that form the path found by AStar3D between the given points. The array is ordered from the starting point to the ending point of the path.
|
||||
If there is no valid path to the target, and [param allow_partial_path] is [code]true[/code], returns a path to the point closest to the target that can be reached.
|
||||
If [param from_id] point is disabled, returns an empty array (even if [code]from_id == to_id[/code]).
|
||||
If [param from_id] point is not disabled, there is no valid path to the target, and [param allow_partial_path] is [code]true[/code], returns a path to the point closest to the target that can be reached.
|
||||
[b]Note:[/b] When [param allow_partial_path] is [code]true[/code] and [param to_id] is disabled the search may take an unusually long time to finish.
|
||||
[codeblocks]
|
||||
[gdscript]
|
||||
@@ -283,7 +284,8 @@
|
||||
<param index="2" name="allow_partial_path" type="bool" default="false" />
|
||||
<description>
|
||||
Returns an array with the points that are in the path found by AStar3D between the given points. The array is ordered from the starting point to the ending point of the path.
|
||||
If there is no valid path to the target, and [param allow_partial_path] is [code]true[/code], returns a path to the point closest to the target that can be reached.
|
||||
If [param from_id] point is disabled, returns an empty array (even if [code]from_id == to_id[/code]).
|
||||
If [param from_id] point is not disabled, there is no valid path to the target, and [param allow_partial_path] is [code]true[/code], returns a path to the point closest to the target that can be reached.
|
||||
[b]Note:[/b] This method is not thread-safe; it can only be used from a single [Thread] at a given time. Consider using [Mutex] to ensure exclusive access to one thread to avoid race conditions.
|
||||
Additionally, when [param allow_partial_path] is [code]true[/code] and [param to_id] is disabled the search may take an unusually long time to finish.
|
||||
</description>
|
||||
|
||||
@@ -79,7 +79,8 @@
|
||||
<param index="2" name="allow_partial_path" type="bool" default="false" />
|
||||
<description>
|
||||
Returns an array with the IDs of the points that form the path found by AStar2D between the given points. The array is ordered from the starting point to the ending point of the path.
|
||||
If there is no valid path to the target, and [param allow_partial_path] is [code]true[/code], returns a path to the point closest to the target that can be reached.
|
||||
If [param from_id] point is disabled, returns an empty array (even if [code]from_id == to_id[/code]).
|
||||
If [param from_id] point is not disabled, there is no valid path to the target, and [param allow_partial_path] is [code]true[/code], returns a path to the point closest to the target that can be reached.
|
||||
[b]Note:[/b] When [param allow_partial_path] is [code]true[/code] and [param to_id] is solid the search may take an unusually long time to finish.
|
||||
</description>
|
||||
</method>
|
||||
@@ -97,7 +98,8 @@
|
||||
<param index="2" name="allow_partial_path" type="bool" default="false" />
|
||||
<description>
|
||||
Returns an array with the points that are in the path found by [AStarGrid2D] between the given points. The array is ordered from the starting point to the ending point of the path.
|
||||
If there is no valid path to the target, and [param allow_partial_path] is [code]true[/code], returns a path to the point closest to the target that can be reached.
|
||||
If [param from_id] point is disabled, returns an empty array (even if [code]from_id == to_id[/code]).
|
||||
If [param from_id] point is not disabled, there is no valid path to the target, and [param allow_partial_path] is [code]true[/code], returns a path to the point closest to the target that can be reached.
|
||||
[b]Note:[/b] This method is not thread-safe; it can only be used from a single [Thread] at a given time. Consider using [Mutex] to ensure exclusive access to one thread to avoid race conditions.
|
||||
Additionally, when [param allow_partial_path] is [code]true[/code] and [param to_id] is solid the search may take an unusually long time to finish.
|
||||
</description>
|
||||
|
||||
@@ -209,6 +209,28 @@ TEST_CASE("[AStar3D] Add/Remove") {
|
||||
CHECK_FALSE(a.are_points_connected(0, j, true));
|
||||
}
|
||||
}
|
||||
// It's been great work, cheers. \(^ ^)/
|
||||
}
|
||||
|
||||
TEST_CASE("[AStar3D] Path from disabled point is empty") {
|
||||
AStar3D a;
|
||||
Vector3 p1(0, 0, 0);
|
||||
Vector3 p2(0, 1, 0);
|
||||
a.add_point(1, p1);
|
||||
a.add_point(2, p2);
|
||||
a.connect_points(1, 2);
|
||||
|
||||
CHECK_EQ(a.get_id_path(1, 1), Vector<int64_t>{ 1 });
|
||||
CHECK_EQ(a.get_id_path(1, 2), Vector<int64_t>{ 1, 2 });
|
||||
|
||||
CHECK_EQ(a.get_point_path(1, 1), Vector<Vector3>{ p1 });
|
||||
CHECK_EQ(a.get_point_path(1, 2), Vector<Vector3>{ p1, p2 });
|
||||
|
||||
a.set_point_disabled(1, true);
|
||||
|
||||
CHECK(a.get_id_path(1, 1).is_empty());
|
||||
CHECK(a.get_id_path(1, 2).is_empty());
|
||||
|
||||
CHECK(a.get_point_path(1, 1).is_empty());
|
||||
CHECK(a.get_point_path(1, 2).is_empty());
|
||||
}
|
||||
} // namespace TestAStar
|
||||
|
||||
Reference in New Issue
Block a user