Skip to content

Commit dda7016

Browse files
committed
Merge pull request #108843 from Chaosus/astar_nbor_filter2
Add a way to filter neighbor points to AStar2D/3D
2 parents f7ced47 + 610712a commit dda7016

File tree

4 files changed

+79
-0
lines changed

4 files changed

+79
-0
lines changed

core/math/a_star.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,13 @@ bool AStar3D::_solve(Point *begin_point, Point *end_point, bool p_allow_partial_
349349
continue;
350350
}
351351

352+
if (neighbor_filter_enabled) {
353+
bool filtered;
354+
if (GDVIRTUAL_CALL(_filter_neighbor, p->id, e->id, filtered) && filtered) {
355+
continue;
356+
}
357+
}
358+
352359
real_t tentative_g_score = p->g_score + _compute_cost(p->id, e->id) * e->weight_scale;
353360

354361
bool new_point = false;
@@ -524,6 +531,14 @@ Vector<int64_t> AStar3D::get_id_path(int64_t p_from_id, int64_t p_to_id, bool p_
524531
return path;
525532
}
526533

534+
bool AStar3D::is_neighbor_filter_enabled() const {
535+
return neighbor_filter_enabled;
536+
}
537+
538+
void AStar3D::set_neighbor_filter_enabled(bool p_enabled) {
539+
neighbor_filter_enabled = p_enabled;
540+
}
541+
527542
void AStar3D::set_point_disabled(int64_t p_id, bool p_disabled) {
528543
Point **p_entry = points.getptr(p_id);
529544
ERR_FAIL_COND_MSG(!p_entry, vformat("Can't set if point is disabled. Point with id: %d doesn't exist.", p_id));
@@ -555,6 +570,9 @@ void AStar3D::_bind_methods() {
555570
ClassDB::bind_method(D_METHOD("set_point_disabled", "id", "disabled"), &AStar3D::set_point_disabled, DEFVAL(true));
556571
ClassDB::bind_method(D_METHOD("is_point_disabled", "id"), &AStar3D::is_point_disabled);
557572

573+
ClassDB::bind_method(D_METHOD("set_neighbor_filter_enabled", "enabled"), &AStar3D::set_neighbor_filter_enabled);
574+
ClassDB::bind_method(D_METHOD("is_neighbor_filter_enabled"), &AStar3D::is_neighbor_filter_enabled);
575+
558576
ClassDB::bind_method(D_METHOD("connect_points", "id", "to_id", "bidirectional"), &AStar3D::connect_points, DEFVAL(true));
559577
ClassDB::bind_method(D_METHOD("disconnect_points", "id", "to_id", "bidirectional"), &AStar3D::disconnect_points, DEFVAL(true));
560578
ClassDB::bind_method(D_METHOD("are_points_connected", "id", "to_id", "bidirectional"), &AStar3D::are_points_connected, DEFVAL(true));
@@ -570,8 +588,11 @@ void AStar3D::_bind_methods() {
570588
ClassDB::bind_method(D_METHOD("get_point_path", "from_id", "to_id", "allow_partial_path"), &AStar3D::get_point_path, DEFVAL(false));
571589
ClassDB::bind_method(D_METHOD("get_id_path", "from_id", "to_id", "allow_partial_path"), &AStar3D::get_id_path, DEFVAL(false));
572590

591+
GDVIRTUAL_BIND(_filter_neighbor, "from_id", "neighbor_id")
573592
GDVIRTUAL_BIND(_estimate_cost, "from_id", "end_id")
574593
GDVIRTUAL_BIND(_compute_cost, "from_id", "to_id")
594+
595+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "neighbor_filter_enabled"), "set_neighbor_filter_enabled", "is_neighbor_filter_enabled");
575596
}
576597

577598
AStar3D::~AStar3D() {
@@ -621,6 +642,14 @@ PackedInt64Array AStar2D::get_point_ids() {
621642
return astar.get_point_ids();
622643
}
623644

645+
bool AStar2D::is_neighbor_filter_enabled() const {
646+
return astar.neighbor_filter_enabled;
647+
}
648+
649+
void AStar2D::set_neighbor_filter_enabled(bool p_enabled) {
650+
astar.neighbor_filter_enabled = p_enabled;
651+
}
652+
624653
void AStar2D::set_point_disabled(int64_t p_id, bool p_disabled) {
625654
astar.set_point_disabled(p_id, p_disabled);
626655
}
@@ -854,6 +883,13 @@ bool AStar2D::_solve(AStar3D::Point *begin_point, AStar3D::Point *end_point, boo
854883
continue;
855884
}
856885

886+
if (astar.neighbor_filter_enabled) {
887+
bool filtered;
888+
if (GDVIRTUAL_CALL(_filter_neighbor, p->id, e->id, filtered) && filtered) {
889+
continue;
890+
}
891+
}
892+
857893
real_t tentative_g_score = p->g_score + _compute_cost(p->id, e->id) * e->weight_scale;
858894

859895
bool new_point = false;
@@ -895,6 +931,9 @@ void AStar2D::_bind_methods() {
895931
ClassDB::bind_method(D_METHOD("get_point_connections", "id"), &AStar2D::get_point_connections);
896932
ClassDB::bind_method(D_METHOD("get_point_ids"), &AStar2D::get_point_ids);
897933

934+
ClassDB::bind_method(D_METHOD("set_neighbor_filter_enabled", "enabled"), &AStar2D::set_neighbor_filter_enabled);
935+
ClassDB::bind_method(D_METHOD("is_neighbor_filter_enabled"), &AStar2D::is_neighbor_filter_enabled);
936+
898937
ClassDB::bind_method(D_METHOD("set_point_disabled", "id", "disabled"), &AStar2D::set_point_disabled, DEFVAL(true));
899938
ClassDB::bind_method(D_METHOD("is_point_disabled", "id"), &AStar2D::is_point_disabled);
900939

@@ -913,6 +952,9 @@ void AStar2D::_bind_methods() {
913952
ClassDB::bind_method(D_METHOD("get_point_path", "from_id", "to_id", "allow_partial_path"), &AStar2D::get_point_path, DEFVAL(false));
914953
ClassDB::bind_method(D_METHOD("get_id_path", "from_id", "to_id", "allow_partial_path"), &AStar2D::get_id_path, DEFVAL(false));
915954

955+
GDVIRTUAL_BIND(_filter_neighbor, "from_id", "neighbor_id")
916956
GDVIRTUAL_BIND(_estimate_cost, "from_id", "end_id")
917957
GDVIRTUAL_BIND(_compute_cost, "from_id", "to_id")
958+
959+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "neighbor_filter_enabled"), "set_neighbor_filter_enabled", "is_neighbor_filter_enabled");
918960
}

core/math/a_star.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ class AStar3D : public RefCounted {
113113
AHashMap<int64_t, Point *> points;
114114
HashSet<Segment, Segment> segments;
115115
Point *last_closest_point = nullptr;
116+
bool neighbor_filter_enabled = false;
116117

117118
bool _solve(Point *begin_point, Point *end_point, bool p_allow_partial_path);
118119

@@ -122,6 +123,7 @@ class AStar3D : public RefCounted {
122123
virtual real_t _estimate_cost(int64_t p_from_id, int64_t p_end_id);
123124
virtual real_t _compute_cost(int64_t p_from_id, int64_t p_to_id);
124125

126+
GDVIRTUAL2RC(bool, _filter_neighbor, int64_t, int64_t)
125127
GDVIRTUAL2RC(real_t, _estimate_cost, int64_t, int64_t)
126128
GDVIRTUAL2RC(real_t, _compute_cost, int64_t, int64_t)
127129

@@ -144,6 +146,9 @@ class AStar3D : public RefCounted {
144146
Vector<int64_t> get_point_connections(int64_t p_id);
145147
PackedInt64Array get_point_ids();
146148

149+
bool is_neighbor_filter_enabled() const;
150+
void set_neighbor_filter_enabled(bool p_enabled);
151+
147152
void set_point_disabled(int64_t p_id, bool p_disabled = true);
148153
bool is_point_disabled(int64_t p_id) const;
149154

@@ -178,6 +183,7 @@ class AStar2D : public RefCounted {
178183
virtual real_t _estimate_cost(int64_t p_from_id, int64_t p_end_id);
179184
virtual real_t _compute_cost(int64_t p_from_id, int64_t p_to_id);
180185

186+
GDVIRTUAL2RC(bool, _filter_neighbor, int64_t, int64_t)
181187
GDVIRTUAL2RC(real_t, _estimate_cost, int64_t, int64_t)
182188
GDVIRTUAL2RC(real_t, _compute_cost, int64_t, int64_t)
183189

@@ -200,6 +206,9 @@ class AStar2D : public RefCounted {
200206
Vector<int64_t> get_point_connections(int64_t p_id);
201207
PackedInt64Array get_point_ids();
202208

209+
bool is_neighbor_filter_enabled() const;
210+
void set_neighbor_filter_enabled(bool p_enabled);
211+
203212
void set_point_disabled(int64_t p_id, bool p_disabled = true);
204213
bool is_point_disabled(int64_t p_id) const;
205214

doc/classes/AStar2D.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@
2929
Note that this function is hidden in the default [AStar2D] class.
3030
</description>
3131
</method>
32+
<method name="_filter_neighbor" qualifiers="virtual const">
33+
<return type="bool" />
34+
<param index="0" name="from_id" type="int" />
35+
<param index="1" name="neighbor_id" type="int" />
36+
<description>
37+
Called when neighboring enters processing and if [member neighbor_filter_enabled] is [code]true[/code]. If [code]true[/code] is returned the point will not be processed.
38+
Note that this function is hidden in the default [AStar2D] class.
39+
</description>
40+
</method>
3241
<method name="add_point">
3342
<return type="void" />
3443
<param index="0" name="id" type="int" />
@@ -307,4 +316,9 @@
307316
</description>
308317
</method>
309318
</methods>
319+
<members>
320+
<member name="neighbor_filter_enabled" type="bool" setter="set_neighbor_filter_enabled" getter="is_neighbor_filter_enabled" default="false">
321+
If [code]true[/code] enables the filtering of neighbors via [method _filter_neighbor].
322+
</member>
323+
</members>
310324
</class>

doc/classes/AStar3D.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@
7070
Note that this function is hidden in the default [AStar3D] class.
7171
</description>
7272
</method>
73+
<method name="_filter_neighbor" qualifiers="virtual const">
74+
<return type="bool" />
75+
<param index="0" name="from_id" type="int" />
76+
<param index="1" name="neighbor_id" type="int" />
77+
<description>
78+
Called when neighboring point enters processing and if [member neighbor_filter_enabled] is [code]true[/code]. If [code]true[/code] is returned the point will not be processed.
79+
Note that this function is hidden in the default [AStar3D] class.
80+
</description>
81+
</method>
7382
<method name="add_point">
7483
<return type="void" />
7584
<param index="0" name="id" type="int" />
@@ -346,4 +355,9 @@
346355
</description>
347356
</method>
348357
</methods>
358+
<members>
359+
<member name="neighbor_filter_enabled" type="bool" setter="set_neighbor_filter_enabled" getter="is_neighbor_filter_enabled" default="false">
360+
If [code]true[/code] enables the filtering of neighbors via [method _filter_neighbor].
361+
</member>
362+
</members>
349363
</class>

0 commit comments

Comments
 (0)