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 NavigationLink function to change navigation map #95456

Merged
merged 1 commit into from
Aug 16, 2024
Merged
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
13 changes: 13 additions & 0 deletions doc/classes/NavigationLink2D.xml
Original file line number Diff line number Diff line change
@@ -29,6 +29,12 @@
Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [param layer_number] between 1 and 32.
</description>
</method>
<method name="get_navigation_map" qualifiers="const">
<return type="RID" />
<description>
Returns the current navigation map [RID] used by this link.
</description>
</method>
<method name="get_rid" qualifiers="const">
<return type="RID" />
<description>
@@ -57,6 +63,13 @@
Based on [param value], enables or disables the specified layer in the [member navigation_layers] bitmask, given a [param layer_number] between 1 and 32.
</description>
</method>
<method name="set_navigation_map">
<return type="void" />
<param index="0" name="navigation_map" type="RID" />
<description>
Sets the [RID] of the navigation map this link should use. By default the link will automatically join the [World2D] default navigation map so this function is only required to override the default map.
</description>
</method>
</methods>
<members>
<member name="bidirectional" type="bool" setter="set_bidirectional" getter="is_bidirectional" default="true">
13 changes: 13 additions & 0 deletions doc/classes/NavigationLink3D.xml
Original file line number Diff line number Diff line change
@@ -29,6 +29,12 @@
Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [param layer_number] between 1 and 32.
</description>
</method>
<method name="get_navigation_map" qualifiers="const">
<return type="RID" />
<description>
Returns the current navigation map [RID] used by this link.
</description>
</method>
<method name="get_rid" qualifiers="const">
<return type="RID" />
<description>
@@ -57,6 +63,13 @@
Based on [param value], enables or disables the specified layer in the [member navigation_layers] bitmask, given a [param layer_number] between 1 and 32.
</description>
</method>
<method name="set_navigation_map">
<return type="void" />
<param index="0" name="navigation_map" type="RID" />
<description>
Sets the [RID] of the navigation map this link should use. By default the link will automatically join the [World3D] default navigation map so this function is only required to override the default map.
</description>
</method>
</methods>
<members>
<member name="bidirectional" type="bool" setter="set_bidirectional" getter="is_bidirectional" default="true">
133 changes: 93 additions & 40 deletions scene/2d/navigation_link_2d.cpp
Original file line number Diff line number Diff line change
@@ -41,6 +41,9 @@ void NavigationLink2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink2D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink2D::is_enabled);

ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationLink2D::set_navigation_map);
ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationLink2D::get_navigation_map);

ClassDB::bind_method(D_METHOD("set_bidirectional", "bidirectional"), &NavigationLink2D::set_bidirectional);
ClassDB::bind_method(D_METHOD("is_bidirectional"), &NavigationLink2D::is_bidirectional);

@@ -106,12 +109,7 @@ bool NavigationLink2D::_get(const StringName &p_name, Variant &r_ret) const {
void NavigationLink2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
if (enabled) {
NavigationServer2D::get_singleton()->link_set_map(link, get_world_2d()->get_navigation_map());
}
current_global_transform = get_global_transform();
NavigationServer2D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position));
NavigationServer2D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position));
_link_enter_navigation_map();
} break;

case NOTIFICATION_TRANSFORM_CHANGED: {
@@ -120,36 +118,15 @@ void NavigationLink2D::_notification(int p_what) {

case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
set_physics_process_internal(false);
if (is_inside_tree()) {
Transform2D new_global_transform = get_global_transform();
if (current_global_transform != new_global_transform) {
current_global_transform = new_global_transform;
NavigationServer2D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position));
NavigationServer2D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position));
queue_redraw();
}
}
_link_update_transform();
} break;

case NOTIFICATION_EXIT_TREE: {
NavigationServer2D::get_singleton()->link_set_map(link, RID());
_link_exit_navigation_map();
} break;
case NOTIFICATION_DRAW: {
#ifdef DEBUG_ENABLED
if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled())) {
Color color;
if (enabled) {
color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_color();
} else {
color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_disabled_color();
}

real_t radius = NavigationServer2D::get_singleton()->map_get_link_connection_radius(get_world_2d()->get_navigation_map());

draw_line(get_start_position(), get_end_position(), color);
draw_arc(get_start_position(), radius, 0, Math_TAU, 10, color);
draw_arc(get_end_position(), radius, 0, Math_TAU, 10, color);
}
_update_debug_mesh();
#endif // DEBUG_ENABLED
} break;
}
@@ -188,15 +165,32 @@ void NavigationLink2D::set_enabled(bool p_enabled) {

enabled = p_enabled;

NavigationServer3D::get_singleton()->link_set_enabled(link, enabled);
NavigationServer2D::get_singleton()->link_set_enabled(link, enabled);

#ifdef DEBUG_ENABLED
if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
queue_redraw();
}
queue_redraw();
#endif // DEBUG_ENABLED
}

void NavigationLink2D::set_navigation_map(RID p_navigation_map) {
if (map_override == p_navigation_map) {
return;
}

map_override = p_navigation_map;

NavigationServer2D::get_singleton()->link_set_map(link, map_override);
}

RID NavigationLink2D::get_navigation_map() const {
if (map_override.is_valid()) {
return map_override;
} else if (is_inside_tree()) {
return get_world_2d()->get_navigation_map();
}
return RID();
}

void NavigationLink2D::set_bidirectional(bool p_bidirectional) {
if (bidirectional == p_bidirectional) {
return;
@@ -255,9 +249,7 @@ void NavigationLink2D::set_start_position(Vector2 p_position) {
update_configuration_warnings();

#ifdef DEBUG_ENABLED
if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
queue_redraw();
}
queue_redraw();
#endif // DEBUG_ENABLED
}

@@ -277,9 +269,7 @@ void NavigationLink2D::set_end_position(Vector2 p_position) {
update_configuration_warnings();

#ifdef DEBUG_ENABLED
if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
queue_redraw();
}
queue_redraw();
#endif // DEBUG_ENABLED
}

@@ -347,6 +337,69 @@ PackedStringArray NavigationLink2D::get_configuration_warnings() const {
return warnings;
}

void NavigationLink2D::_link_enter_navigation_map() {
if (!is_inside_tree()) {
return;
}

if (map_override.is_valid()) {
NavigationServer2D::get_singleton()->link_set_map(link, map_override);
} else {
NavigationServer2D::get_singleton()->link_set_map(link, get_world_2d()->get_navigation_map());
}

current_global_transform = get_global_transform();

NavigationServer2D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position));
NavigationServer2D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position));
NavigationServer2D::get_singleton()->link_set_enabled(link, enabled);

queue_redraw();
}

void NavigationLink2D::_link_exit_navigation_map() {
NavigationServer2D::get_singleton()->link_set_map(link, RID());
}

void NavigationLink2D::_link_update_transform() {
if (!is_inside_tree()) {
return;
}

Transform2D new_global_transform = get_global_transform();
if (current_global_transform != new_global_transform) {
current_global_transform = new_global_transform;
NavigationServer2D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position));
NavigationServer2D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position));
queue_redraw();
}
}

#ifdef DEBUG_ENABLED
void NavigationLink2D::_update_debug_mesh() {
if (!is_inside_tree()) {
return;
}

if (!Engine::get_singleton()->is_editor_hint() && !NavigationServer2D::get_singleton()->get_debug_enabled()) {
return;
}

Color color;
if (enabled) {
color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_color();
} else {
color = NavigationServer2D::get_singleton()->get_debug_navigation_link_connection_disabled_color();
}

real_t radius = NavigationServer2D::get_singleton()->map_get_link_connection_radius(get_world_2d()->get_navigation_map());

draw_line(get_start_position(), get_end_position(), color);
draw_arc(get_start_position(), radius, 0, Math_TAU, 10, color);
draw_arc(get_end_position(), radius, 0, Math_TAU, 10, color);
}
#endif // DEBUG_ENABLED

NavigationLink2D::NavigationLink2D() {
link = NavigationServer2D::get_singleton()->link_create();

13 changes: 13 additions & 0 deletions scene/2d/navigation_link_2d.h
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@ class NavigationLink2D : public Node2D {

bool enabled = true;
RID link;
RID map_override;
bool bidirectional = true;
uint32_t navigation_layers = 1;
Vector2 end_position;
@@ -47,6 +48,10 @@ class NavigationLink2D : public Node2D {

Transform2D current_global_transform;

#ifdef DEBUG_ENABLED
void _update_debug_mesh();
#endif // DEBUG_ENABLED

protected:
static void _bind_methods();
void _notification(int p_what);
@@ -66,6 +71,9 @@ class NavigationLink2D : public Node2D {
void set_enabled(bool p_enabled);
bool is_enabled() const { return enabled; }

void set_navigation_map(RID p_navigation_map);
RID get_navigation_map() const;

void set_bidirectional(bool p_bidirectional);
bool is_bidirectional() const { return bidirectional; }

@@ -97,6 +105,11 @@ class NavigationLink2D : public Node2D {

NavigationLink2D();
~NavigationLink2D();

private:
void _link_enter_navigation_map();
void _link_exit_navigation_map();
void _link_update_transform();
};

#endif // NAVIGATION_LINK_2D_H
106 changes: 75 additions & 31 deletions scene/3d/navigation_link_3d.cpp
Original file line number Diff line number Diff line change
@@ -152,6 +152,9 @@ void NavigationLink3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink3D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationLink3D::is_enabled);

ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationLink3D::set_navigation_map);
ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationLink3D::get_navigation_map);

ClassDB::bind_method(D_METHOD("set_bidirectional", "bidirectional"), &NavigationLink3D::set_bidirectional);
ClassDB::bind_method(D_METHOD("is_bidirectional"), &NavigationLink3D::is_bidirectional);

@@ -217,16 +220,7 @@ bool NavigationLink3D::_get(const StringName &p_name, Variant &r_ret) const {
void NavigationLink3D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
if (enabled) {
NavigationServer3D::get_singleton()->link_set_map(link, get_world_3d()->get_navigation_map());
}
current_global_transform = get_global_transform();
NavigationServer3D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position));
NavigationServer3D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position));

#ifdef DEBUG_ENABLED
_update_debug_mesh();
#endif // DEBUG_ENABLED
_link_enter_navigation_map();
} break;

case NOTIFICATION_TRANSFORM_CHANGED: {
@@ -235,30 +229,11 @@ void NavigationLink3D::_notification(int p_what) {

case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
set_physics_process_internal(false);
if (is_inside_tree()) {
Transform3D new_global_transform = get_global_transform();
if (current_global_transform != new_global_transform) {
current_global_transform = new_global_transform;
NavigationServer3D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position));
NavigationServer3D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position));
#ifdef DEBUG_ENABLED
if (debug_instance.is_valid()) {
RS::get_singleton()->instance_set_transform(debug_instance, current_global_transform);
}
#endif // DEBUG_ENABLED
}
}
_link_update_transform();
} break;

case NOTIFICATION_EXIT_TREE: {
NavigationServer3D::get_singleton()->link_set_map(link, RID());

#ifdef DEBUG_ENABLED
if (debug_instance.is_valid()) {
RS::get_singleton()->instance_set_scenario(debug_instance, RID());
RS::get_singleton()->instance_set_visible(debug_instance, false);
}
#endif // DEBUG_ENABLED
_link_exit_navigation_map();
} break;
}
}
@@ -320,6 +295,25 @@ void NavigationLink3D::set_enabled(bool p_enabled) {
update_gizmos();
}

void NavigationLink3D::set_navigation_map(RID p_navigation_map) {
if (map_override == p_navigation_map) {
return;
}

map_override = p_navigation_map;

NavigationServer3D::get_singleton()->link_set_map(link, map_override);
}

RID NavigationLink3D::get_navigation_map() const {
if (map_override.is_valid()) {
return map_override;
} else if (is_inside_tree()) {
return get_world_3d()->get_navigation_map();
}
return RID();
}

void NavigationLink3D::set_bidirectional(bool p_bidirectional) {
if (bidirectional == p_bidirectional) {
return;
@@ -467,3 +461,53 @@ PackedStringArray NavigationLink3D::get_configuration_warnings() const {

return warnings;
}

void NavigationLink3D::_link_enter_navigation_map() {
if (!is_inside_tree()) {
return;
}

if (map_override.is_valid()) {
NavigationServer3D::get_singleton()->link_set_map(link, map_override);
} else {
NavigationServer3D::get_singleton()->link_set_map(link, get_world_3d()->get_navigation_map());
}

current_global_transform = get_global_transform();
NavigationServer3D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position));
NavigationServer3D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position));
NavigationServer3D::get_singleton()->link_set_enabled(link, enabled);

#ifdef DEBUG_ENABLED
if (NavigationServer3D::get_singleton()->get_debug_navigation_enabled()) {
_update_debug_mesh();
}
#endif // DEBUG_ENABLED
}

void NavigationLink3D::_link_exit_navigation_map() {
NavigationServer3D::get_singleton()->link_set_map(link, RID());
#ifdef DEBUG_ENABLED
if (debug_instance.is_valid()) {
RS::get_singleton()->instance_set_visible(debug_instance, false);
}
#endif // DEBUG_ENABLED
}

void NavigationLink3D::_link_update_transform() {
if (!is_inside_tree()) {
return;
}

Transform3D new_global_transform = get_global_transform();
if (current_global_transform != new_global_transform) {
current_global_transform = new_global_transform;
NavigationServer3D::get_singleton()->link_set_start_position(link, current_global_transform.xform(start_position));
NavigationServer3D::get_singleton()->link_set_end_position(link, current_global_transform.xform(end_position));
#ifdef DEBUG_ENABLED
if (NavigationServer3D::get_singleton()->get_debug_navigation_enabled()) {
_update_debug_mesh();
}
#endif // DEBUG_ENABLED
}
}
9 changes: 9 additions & 0 deletions scene/3d/navigation_link_3d.h
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@ class NavigationLink3D : public Node3D {

bool enabled = true;
RID link;
RID map_override;
bool bidirectional = true;
uint32_t navigation_layers = 1;
Vector3 end_position;
@@ -72,6 +73,9 @@ class NavigationLink3D : public Node3D {
void set_enabled(bool p_enabled);
bool is_enabled() const { return enabled; }

void set_navigation_map(RID p_navigation_map);
RID get_navigation_map() const;

void set_bidirectional(bool p_bidirectional);
bool is_bidirectional() const { return bidirectional; }

@@ -100,6 +104,11 @@ class NavigationLink3D : public Node3D {
real_t get_travel_cost() const { return travel_cost; }

PackedStringArray get_configuration_warnings() const override;

private:
void _link_enter_navigation_map();
void _link_exit_navigation_map();
void _link_update_transform();
};

#endif // NAVIGATION_LINK_3D_H