Merge pull request #113988 from kleonc/astar_path_from_disabled_point_is_empty

Fix `AStar`s to return empty path for disabled from point
This commit is contained in:
Rémi Verschelde
2026-01-01 16:46:26 +01:00
7 changed files with 77 additions and 80 deletions

View File

@@ -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;

View File

@@ -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();

View File

@@ -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) {