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 NavigationRegion function to change navigation map #77191

Merged
merged 1 commit into from
Jul 12, 2023
Merged
Show file tree
Hide file tree
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/NavigationRegion2D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,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 region.
</description>
</method>
<method name="get_region_rid" qualifiers="const">
<return type="RID" />
<description>
Expand All @@ -52,6 +58,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 region should use. By default the region 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="avoidance_layers" type="int" setter="set_avoidance_layers" getter="get_avoidance_layers" default="1">
Expand Down
13 changes: 13 additions & 0 deletions doc/classes/NavigationRegion3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,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 region.
</description>
</method>
<method name="get_region_rid" qualifiers="const">
<return type="RID" />
<description>
Expand All @@ -44,6 +50,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 region should use. By default the region 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="enabled" type="bool" setter="set_enabled" getter="is_enabled" default="true">
Expand Down
132 changes: 98 additions & 34 deletions scene/2d/navigation_region_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ void NavigationRegion2D::set_enabled(bool p_enabled) {
}

if (!enabled) {
NavigationServer2D::get_singleton()->region_set_map(region, RID());
_region_enter_navigation_map();
} else {
NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map());
_region_exit_navigation_map();
}

#ifdef DEBUG_ENABLED
Expand Down Expand Up @@ -161,48 +161,19 @@ bool NavigationRegion2D::_edit_is_selected_on_click(const Point2 &p_point, doubl
void NavigationRegion2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
if (enabled) {
NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map());
for (uint32_t i = 0; i < constrain_avoidance_obstacles.size(); i++) {
if (constrain_avoidance_obstacles[i].is_valid()) {
NavigationServer2D::get_singleton()->obstacle_set_map(constrain_avoidance_obstacles[i], get_world_2d()->get_navigation_map());
NavigationServer2D::get_singleton()->obstacle_set_position(constrain_avoidance_obstacles[i], get_global_position());
}
}
}
current_global_transform = get_global_transform();
NavigationServer2D::get_singleton()->region_set_transform(region, current_global_transform);
_region_enter_navigation_map();
} break;

case NOTIFICATION_TRANSFORM_CHANGED: {
set_physics_process_internal(true);
} break;

case NOTIFICATION_EXIT_TREE: {
NavigationServer2D::get_singleton()->region_set_map(region, RID());
for (uint32_t i = 0; i < constrain_avoidance_obstacles.size(); i++) {
if (constrain_avoidance_obstacles[i].is_valid()) {
NavigationServer2D::get_singleton()->obstacle_set_map(constrain_avoidance_obstacles[i], RID());
}
}
_region_exit_navigation_map();
} break;

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()->region_set_transform(region, current_global_transform);
queue_redraw();

for (uint32_t i = 0; i < constrain_avoidance_obstacles.size(); i++) {
if (constrain_avoidance_obstacles[i].is_valid()) {
NavigationServer2D::get_singleton()->obstacle_set_position(constrain_avoidance_obstacles[i], get_global_position());
}
}
}
}
} break;

case NOTIFICATION_DRAW: {
Expand Down Expand Up @@ -240,6 +211,30 @@ Ref<NavigationPolygon> NavigationRegion2D::get_navigation_polygon() const {
return navigation_polygon;
}

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

map_override = p_navigation_map;

NavigationServer2D::get_singleton()->region_set_map(region, map_override);
for (uint32_t i = 0; i < constrain_avoidance_obstacles.size(); i++) {
if (constrain_avoidance_obstacles[i].is_valid()) {
NavigationServer2D::get_singleton()->obstacle_set_map(constrain_avoidance_obstacles[i], map_override);
}
}
}

RID NavigationRegion2D::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 NavigationRegion2D::_navigation_polygon_changed() {
if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint())) {
queue_redraw();
Expand Down Expand Up @@ -277,6 +272,9 @@ void NavigationRegion2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_enabled", "enabled"), &NavigationRegion2D::set_enabled);
ClassDB::bind_method(D_METHOD("is_enabled"), &NavigationRegion2D::is_enabled);

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

ClassDB::bind_method(D_METHOD("set_use_edge_connections", "enabled"), &NavigationRegion2D::set_use_edge_connections);
ClassDB::bind_method(D_METHOD("get_use_edge_connections"), &NavigationRegion2D::get_use_edge_connections);

Expand Down Expand Up @@ -416,7 +414,11 @@ void NavigationRegion2D::_update_avoidance_constrain() {
NavigationServer2D::get_singleton()->obstacle_set_vertices(obstacle_rid, new_obstacle_outline);
NavigationServer2D::get_singleton()->obstacle_set_avoidance_layers(obstacle_rid, avoidance_layers);
if (is_inside_tree()) {
NavigationServer2D::get_singleton()->obstacle_set_map(obstacle_rid, get_world_2d()->get_navigation_map());
if (map_override.is_valid()) {
NavigationServer2D::get_singleton()->obstacle_set_map(obstacle_rid, map_override);
} else {
NavigationServer2D::get_singleton()->obstacle_set_map(obstacle_rid, get_world_2d()->get_navigation_map());
}
NavigationServer2D::get_singleton()->obstacle_set_position(obstacle_rid, get_global_position());
}
}
Expand Down Expand Up @@ -472,6 +474,68 @@ bool NavigationRegion2D::get_avoidance_layer_value(int p_layer_number) const {
return get_avoidance_layers() & (1 << (p_layer_number - 1));
}

void NavigationRegion2D::_region_enter_navigation_map() {
if (!is_inside_tree()) {
return;
}

if (enabled) {
if (map_override.is_valid()) {
NavigationServer2D::get_singleton()->region_set_map(region, map_override);
for (uint32_t i = 0; i < constrain_avoidance_obstacles.size(); i++) {
if (constrain_avoidance_obstacles[i].is_valid()) {
NavigationServer2D::get_singleton()->obstacle_set_map(constrain_avoidance_obstacles[i], map_override);
}
}
} else {
NavigationServer2D::get_singleton()->region_set_map(region, get_world_2d()->get_navigation_map());
for (uint32_t i = 0; i < constrain_avoidance_obstacles.size(); i++) {
if (constrain_avoidance_obstacles[i].is_valid()) {
NavigationServer2D::get_singleton()->obstacle_set_map(constrain_avoidance_obstacles[i], get_world_2d()->get_navigation_map());
}
}
}
}

current_global_transform = get_global_transform();
NavigationServer2D::get_singleton()->region_set_transform(region, current_global_transform);
for (uint32_t i = 0; i < constrain_avoidance_obstacles.size(); i++) {
if (constrain_avoidance_obstacles[i].is_valid()) {
NavigationServer2D::get_singleton()->obstacle_set_position(constrain_avoidance_obstacles[i], get_global_position());
}
}

queue_redraw();
}

void NavigationRegion2D::_region_exit_navigation_map() {
NavigationServer2D::get_singleton()->region_set_map(region, RID());
for (uint32_t i = 0; i < constrain_avoidance_obstacles.size(); i++) {
if (constrain_avoidance_obstacles[i].is_valid()) {
NavigationServer2D::get_singleton()->obstacle_set_map(constrain_avoidance_obstacles[i], RID());
}
}
}

void NavigationRegion2D::_region_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()->region_set_transform(region, current_global_transform);
for (uint32_t i = 0; i < constrain_avoidance_obstacles.size(); i++) {
if (constrain_avoidance_obstacles[i].is_valid()) {
NavigationServer2D::get_singleton()->obstacle_set_position(constrain_avoidance_obstacles[i], get_global_position());
}
}
}

queue_redraw();
}

#ifdef DEBUG_ENABLED
void NavigationRegion2D::_update_debug_mesh() {
Vector<Vector2> navigation_polygon_vertices = navigation_polygon->get_vertices();
Expand Down
7 changes: 7 additions & 0 deletions scene/2d/navigation_region_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class NavigationRegion2D : public Node2D {
bool use_edge_connections = true;

RID region;
RID map_override;
uint32_t navigation_layers = 1;
real_t enter_cost = 0.0;
real_t travel_cost = 1.0;
Expand Down Expand Up @@ -79,6 +80,9 @@ class NavigationRegion2D : public Node2D {
void set_enabled(bool p_enabled);
bool is_enabled() const;

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

void set_use_edge_connections(bool p_enabled);
bool get_use_edge_connections() const;

Expand Down Expand Up @@ -115,6 +119,9 @@ class NavigationRegion2D : public Node2D {

private:
void _update_avoidance_constrain();
void _region_enter_navigation_map();
void _region_exit_navigation_map();
void _region_update_transform();
};

#endif // NAVIGATION_REGION_2D_H
Loading