Merge pull request #95456 from smix8/navlink_mapchange

Add NavigationLink function to change navigation map
This commit is contained in:
Rémi Verschelde 2024-08-16 14:34:49 +02:00
commit a917a2b2f9
No known key found for this signature in database
GPG Key ID: C3336907360768E1
6 changed files with 216 additions and 71 deletions

View File

@ -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. 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> </description>
</method> </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"> <method name="get_rid" qualifiers="const">
<return type="RID" /> <return type="RID" />
<description> <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. 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> </description>
</method> </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> </methods>
<members> <members>
<member name="bidirectional" type="bool" setter="set_bidirectional" getter="is_bidirectional" default="true"> <member name="bidirectional" type="bool" setter="set_bidirectional" getter="is_bidirectional" default="true">

View File

@ -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. 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> </description>
</method> </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"> <method name="get_rid" qualifiers="const">
<return type="RID" /> <return type="RID" />
<description> <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. 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> </description>
</method> </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> </methods>
<members> <members>
<member name="bidirectional" type="bool" setter="set_bidirectional" getter="is_bidirectional" default="true"> <member name="bidirectional" type="bool" setter="set_bidirectional" getter="is_bidirectional" default="true">

View File

@ -41,6 +41,9 @@ void NavigationLink2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink2D::set_enabled); 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("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("set_bidirectional", "bidirectional"), &NavigationLink2D::set_bidirectional);
ClassDB::bind_method(D_METHOD("is_bidirectional"), &NavigationLink2D::is_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) { void NavigationLink2D::_notification(int p_what) {
switch (p_what) { switch (p_what) {
case NOTIFICATION_ENTER_TREE: { case NOTIFICATION_ENTER_TREE: {
if (enabled) { _link_enter_navigation_map();
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));
} break; } break;
case NOTIFICATION_TRANSFORM_CHANGED: { case NOTIFICATION_TRANSFORM_CHANGED: {
@ -120,36 +118,15 @@ void NavigationLink2D::_notification(int p_what) {
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
set_physics_process_internal(false); set_physics_process_internal(false);
if (is_inside_tree()) { _link_update_transform();
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();
}
}
} break; } break;
case NOTIFICATION_EXIT_TREE: { case NOTIFICATION_EXIT_TREE: {
NavigationServer2D::get_singleton()->link_set_map(link, RID()); _link_exit_navigation_map();
} break; } break;
case NOTIFICATION_DRAW: { case NOTIFICATION_DRAW: {
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled())) { _update_debug_mesh();
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 #endif // DEBUG_ENABLED
} break; } break;
} }
@ -188,15 +165,32 @@ void NavigationLink2D::set_enabled(bool p_enabled) {
enabled = p_enabled; enabled = p_enabled;
NavigationServer3D::get_singleton()->link_set_enabled(link, enabled); NavigationServer2D::get_singleton()->link_set_enabled(link, enabled);
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
queue_redraw(); queue_redraw();
}
#endif // DEBUG_ENABLED #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) { void NavigationLink2D::set_bidirectional(bool p_bidirectional) {
if (bidirectional == p_bidirectional) { if (bidirectional == p_bidirectional) {
return; return;
@ -255,9 +249,7 @@ void NavigationLink2D::set_start_position(Vector2 p_position) {
update_configuration_warnings(); update_configuration_warnings();
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
queue_redraw(); queue_redraw();
}
#endif // DEBUG_ENABLED #endif // DEBUG_ENABLED
} }
@ -277,9 +269,7 @@ void NavigationLink2D::set_end_position(Vector2 p_position) {
update_configuration_warnings(); update_configuration_warnings();
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
queue_redraw(); queue_redraw();
}
#endif // DEBUG_ENABLED #endif // DEBUG_ENABLED
} }
@ -347,6 +337,69 @@ PackedStringArray NavigationLink2D::get_configuration_warnings() const {
return warnings; 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() { NavigationLink2D::NavigationLink2D() {
link = NavigationServer2D::get_singleton()->link_create(); link = NavigationServer2D::get_singleton()->link_create();

View File

@ -38,6 +38,7 @@ class NavigationLink2D : public Node2D {
bool enabled = true; bool enabled = true;
RID link; RID link;
RID map_override;
bool bidirectional = true; bool bidirectional = true;
uint32_t navigation_layers = 1; uint32_t navigation_layers = 1;
Vector2 end_position; Vector2 end_position;
@ -47,6 +48,10 @@ class NavigationLink2D : public Node2D {
Transform2D current_global_transform; Transform2D current_global_transform;
#ifdef DEBUG_ENABLED
void _update_debug_mesh();
#endif // DEBUG_ENABLED
protected: protected:
static void _bind_methods(); static void _bind_methods();
void _notification(int p_what); void _notification(int p_what);
@ -66,6 +71,9 @@ public:
void set_enabled(bool p_enabled); void set_enabled(bool p_enabled);
bool is_enabled() const { return 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); void set_bidirectional(bool p_bidirectional);
bool is_bidirectional() const { return bidirectional; } bool is_bidirectional() const { return bidirectional; }
@ -97,6 +105,11 @@ public:
NavigationLink2D(); NavigationLink2D();
~NavigationLink2D(); ~NavigationLink2D();
private:
void _link_enter_navigation_map();
void _link_exit_navigation_map();
void _link_update_transform();
}; };
#endif // NAVIGATION_LINK_2D_H #endif // NAVIGATION_LINK_2D_H

View File

@ -152,6 +152,9 @@ void NavigationLink3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationLink3D::set_enabled); 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("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("set_bidirectional", "bidirectional"), &NavigationLink3D::set_bidirectional);
ClassDB::bind_method(D_METHOD("is_bidirectional"), &NavigationLink3D::is_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) { void NavigationLink3D::_notification(int p_what) {
switch (p_what) { switch (p_what) {
case NOTIFICATION_ENTER_TREE: { case NOTIFICATION_ENTER_TREE: {
if (enabled) { _link_enter_navigation_map();
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
} break; } break;
case NOTIFICATION_TRANSFORM_CHANGED: { case NOTIFICATION_TRANSFORM_CHANGED: {
@ -235,30 +229,11 @@ void NavigationLink3D::_notification(int p_what) {
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
set_physics_process_internal(false); set_physics_process_internal(false);
if (is_inside_tree()) { _link_update_transform();
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
}
}
} break; } break;
case NOTIFICATION_EXIT_TREE: { case NOTIFICATION_EXIT_TREE: {
NavigationServer3D::get_singleton()->link_set_map(link, RID()); _link_exit_navigation_map();
#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
} break; } break;
} }
} }
@ -320,6 +295,25 @@ void NavigationLink3D::set_enabled(bool p_enabled) {
update_gizmos(); 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) { void NavigationLink3D::set_bidirectional(bool p_bidirectional) {
if (bidirectional == p_bidirectional) { if (bidirectional == p_bidirectional) {
return; return;
@ -467,3 +461,53 @@ PackedStringArray NavigationLink3D::get_configuration_warnings() const {
return warnings; 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
}
}

View File

@ -38,6 +38,7 @@ class NavigationLink3D : public Node3D {
bool enabled = true; bool enabled = true;
RID link; RID link;
RID map_override;
bool bidirectional = true; bool bidirectional = true;
uint32_t navigation_layers = 1; uint32_t navigation_layers = 1;
Vector3 end_position; Vector3 end_position;
@ -72,6 +73,9 @@ public:
void set_enabled(bool p_enabled); void set_enabled(bool p_enabled);
bool is_enabled() const { return 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); void set_bidirectional(bool p_bidirectional);
bool is_bidirectional() const { return bidirectional; } bool is_bidirectional() const { return bidirectional; }
@ -100,6 +104,11 @@ public:
real_t get_travel_cost() const { return travel_cost; } real_t get_travel_cost() const { return travel_cost; }
PackedStringArray get_configuration_warnings() const override; 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 #endif // NAVIGATION_LINK_3D_H