From 69fad39cf5437b45bac2039d864605b2b63b9950 Mon Sep 17 00:00:00 2001
From: smix8 <52464204+smix8@users.noreply.github.com>
Date: Thu, 6 Jul 2023 23:01:19 +0200
Subject: [PATCH] Add NavigationServer API to enable regions and links

Adds NavigationServer API to enable regions and links.
---
 doc/classes/NavigationServer2D.xml            | 30 +++++++++++++++++++
 doc/classes/NavigationServer3D.xml            | 30 +++++++++++++++++++
 .../navigation/godot_navigation_server.cpp    | 28 +++++++++++++++++
 modules/navigation/godot_navigation_server.h  |  5 ++++
 modules/navigation/nav_link.cpp               | 10 +++++++
 modules/navigation/nav_link.h                 |  4 +++
 modules/navigation/nav_map.cpp                |  6 ++++
 modules/navigation/nav_region.cpp             | 10 +++++++
 modules/navigation/nav_region.h               |  4 +++
 scene/2d/navigation_link_2d.cpp               | 10 +------
 scene/2d/navigation_region_2d.cpp             | 10 +------
 scene/3d/navigation_link_3d.cpp               | 10 +------
 scene/3d/navigation_region_3d.cpp             | 10 +------
 servers/navigation_server_2d.cpp              |  8 +++++
 servers/navigation_server_2d.h                |  6 ++++
 servers/navigation_server_3d.cpp              |  4 +++
 servers/navigation_server_3d.h                |  6 ++++
 servers/navigation_server_3d_dummy.h          |  4 +++
 18 files changed, 159 insertions(+), 36 deletions(-)

diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index 7f0e29676b7..32215316d13 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -207,6 +207,13 @@
 				Create a new link between two positions on a map.
 			</description>
 		</method>
+		<method name="link_get_enabled" qualifiers="const">
+			<return type="bool" />
+			<param index="0" name="link" type="RID" />
+			<description>
+				Returns [code]true[/code] if the specified [param link] is enabled.
+			</description>
+		</method>
 		<method name="link_get_end_position" qualifiers="const">
 			<return type="Vector2" />
 			<param index="0" name="link" type="RID" />
@@ -271,6 +278,14 @@
 				Sets whether this [param link] can be travelled in both directions.
 			</description>
 		</method>
+		<method name="link_set_enabled">
+			<return type="void" />
+			<param index="0" name="link" type="RID" />
+			<param index="1" name="enabled" type="bool" />
+			<description>
+				If [param enabled] is [code]true[/code] the specified [param link] will contribute to its current navigation map.
+			</description>
+		</method>
 		<method name="link_set_end_position">
 			<return type="void" />
 			<param index="0" name="link" type="RID" />
@@ -601,6 +616,13 @@
 				Returns how many connections this [param region] has with other regions in the map.
 			</description>
 		</method>
+		<method name="region_get_enabled" qualifiers="const">
+			<return type="bool" />
+			<param index="0" name="region" type="RID" />
+			<description>
+				Returns [code]true[/code] if the specified [param region] is enabled.
+			</description>
+		</method>
 		<method name="region_get_enter_cost" qualifiers="const">
 			<return type="float" />
 			<param index="0" name="region" type="RID" />
@@ -653,6 +675,14 @@
 				[b]Note:[/b] If navigation meshes from different navigation regions overlap (which should be avoided in general) the result might not be what is expected.
 			</description>
 		</method>
+		<method name="region_set_enabled">
+			<return type="void" />
+			<param index="0" name="region" type="RID" />
+			<param index="1" name="enabled" type="bool" />
+			<description>
+				If [param enabled] is [code]true[/code] the specified [param region] will contribute to its current navigation map.
+			</description>
+		</method>
 		<method name="region_set_enter_cost">
 			<return type="void" />
 			<param index="0" name="region" type="RID" />
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index e4f9a1627fc..ebde6fdf7b4 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -248,6 +248,13 @@
 				Create a new link between two positions on a map.
 			</description>
 		</method>
+		<method name="link_get_enabled" qualifiers="const">
+			<return type="bool" />
+			<param index="0" name="link" type="RID" />
+			<description>
+				Returns [code]true[/code] if the specified [param link] is enabled.
+			</description>
+		</method>
 		<method name="link_get_end_position" qualifiers="const">
 			<return type="Vector3" />
 			<param index="0" name="link" type="RID" />
@@ -312,6 +319,14 @@
 				Sets whether this [param link] can be travelled in both directions.
 			</description>
 		</method>
+		<method name="link_set_enabled">
+			<return type="void" />
+			<param index="0" name="link" type="RID" />
+			<param index="1" name="enabled" type="bool" />
+			<description>
+				If [param enabled] is [code]true[/code] the specified [param link] will contribute to its current navigation map.
+			</description>
+		</method>
 		<method name="link_set_end_position">
 			<return type="void" />
 			<param index="0" name="link" type="RID" />
@@ -734,6 +749,13 @@
 				Returns how many connections this [param region] has with other regions in the map.
 			</description>
 		</method>
+		<method name="region_get_enabled" qualifiers="const">
+			<return type="bool" />
+			<param index="0" name="region" type="RID" />
+			<description>
+				Returns [code]true[/code] if the specified [param region] is enabled.
+			</description>
+		</method>
 		<method name="region_get_enter_cost" qualifiers="const">
 			<return type="float" />
 			<param index="0" name="region" type="RID" />
@@ -786,6 +808,14 @@
 				[b]Note:[/b] If navigation meshes from different navigation regions overlap (which should be avoided in general) the result might not be what is expected.
 			</description>
 		</method>
+		<method name="region_set_enabled">
+			<return type="void" />
+			<param index="0" name="region" type="RID" />
+			<param index="1" name="enabled" type="bool" />
+			<description>
+				If [param enabled] is [code]true[/code] the specified [param region] will contribute to its current navigation map.
+			</description>
+		</method>
 		<method name="region_set_enter_cost">
 			<return type="void" />
 			<param index="0" name="region" type="RID" />
diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index b73c5ca3e20..29fa73aa85f 100644
--- a/modules/navigation/godot_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -340,6 +340,20 @@ RID GodotNavigationServer::region_create() {
 	return rid;
 }
 
+COMMAND_2(region_set_enabled, RID, p_region, bool, p_enabled) {
+	NavRegion *region = region_owner.get_or_null(p_region);
+	ERR_FAIL_COND(region == nullptr);
+
+	region->set_enabled(p_enabled);
+}
+
+bool GodotNavigationServer::region_get_enabled(RID p_region) const {
+	const NavRegion *region = region_owner.get_or_null(p_region);
+	ERR_FAIL_COND_V(region == nullptr, false);
+
+	return region->get_enabled();
+}
+
 COMMAND_2(region_set_use_edge_connections, RID, p_region, bool, p_enabled) {
 	NavRegion *region = region_owner.get_or_null(p_region);
 	ERR_FAIL_COND(region == nullptr);
@@ -512,6 +526,20 @@ RID GodotNavigationServer::link_get_map(const RID p_link) const {
 	return RID();
 }
 
+COMMAND_2(link_set_enabled, RID, p_link, bool, p_enabled) {
+	NavLink *link = link_owner.get_or_null(p_link);
+	ERR_FAIL_COND(link == nullptr);
+
+	link->set_enabled(p_enabled);
+}
+
+bool GodotNavigationServer::link_get_enabled(RID p_link) const {
+	const NavLink *link = link_owner.get_or_null(p_link);
+	ERR_FAIL_COND_V(link == nullptr, false);
+
+	return link->get_enabled();
+}
+
 COMMAND_2(link_set_bidirectional, RID, p_link, bool, p_bidirectional) {
 	NavLink *link = link_owner.get_or_null(p_link);
 	ERR_FAIL_COND(link == nullptr);
diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h
index 95aa88194ea..0b3789102cf 100644
--- a/modules/navigation/godot_navigation_server.h
+++ b/modules/navigation/godot_navigation_server.h
@@ -135,6 +135,9 @@ public:
 
 	virtual RID region_create() override;
 
+	COMMAND_2(region_set_enabled, RID, p_region, bool, p_enabled);
+	virtual bool region_get_enabled(RID p_region) const override;
+
 	COMMAND_2(region_set_use_edge_connections, RID, p_region, bool, p_enabled);
 	virtual bool region_get_use_edge_connections(RID p_region) const override;
 
@@ -164,6 +167,8 @@ public:
 	virtual RID link_create() override;
 	COMMAND_2(link_set_map, RID, p_link, RID, p_map);
 	virtual RID link_get_map(RID p_link) const override;
+	COMMAND_2(link_set_enabled, RID, p_link, bool, p_enabled);
+	virtual bool link_get_enabled(RID p_link) const override;
 	COMMAND_2(link_set_bidirectional, RID, p_link, bool, p_bidirectional);
 	virtual bool link_is_bidirectional(RID p_link) const override;
 	COMMAND_2(link_set_navigation_layers, RID, p_link, uint32_t, p_navigation_layers);
diff --git a/modules/navigation/nav_link.cpp b/modules/navigation/nav_link.cpp
index d712987a467..c693cc91c8e 100644
--- a/modules/navigation/nav_link.cpp
+++ b/modules/navigation/nav_link.cpp
@@ -49,6 +49,16 @@ void NavLink::set_map(NavMap *p_map) {
 	}
 }
 
+void NavLink::set_enabled(bool p_enabled) {
+	if (enabled == p_enabled) {
+		return;
+	}
+	enabled = p_enabled;
+
+	// TODO: This should not require a full rebuild as the link has not really changed.
+	link_dirty = true;
+};
+
 void NavLink::set_bidirectional(bool p_bidirectional) {
 	if (bidirectional == p_bidirectional) {
 		return;
diff --git a/modules/navigation/nav_link.h b/modules/navigation/nav_link.h
index 0b8ad4db693..a7609831db2 100644
--- a/modules/navigation/nav_link.h
+++ b/modules/navigation/nav_link.h
@@ -39,6 +39,7 @@ class NavLink : public NavBase {
 	bool bidirectional = true;
 	Vector3 start_position;
 	Vector3 end_position;
+	bool enabled = true;
 
 	bool link_dirty = true;
 
@@ -52,6 +53,9 @@ public:
 		return map;
 	}
 
+	void set_enabled(bool p_enabled);
+	bool get_enabled() const { return enabled; }
+
 	void set_bidirectional(bool p_bidirectional);
 	bool is_bidirectional() const {
 		return bidirectional;
diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp
index 3a1d4126187..745c227fe54 100644
--- a/modules/navigation/nav_map.cpp
+++ b/modules/navigation/nav_map.cpp
@@ -804,6 +804,9 @@ void NavMap::sync() {
 		// Resize the polygon count.
 		int count = 0;
 		for (const NavRegion *region : regions) {
+			if (!region->get_enabled()) {
+				continue;
+			}
 			count += region->get_polygons().size();
 		}
 		polygons.resize(count);
@@ -811,6 +814,9 @@ void NavMap::sync() {
 		// Copy all region polygons in the map.
 		count = 0;
 		for (const NavRegion *region : regions) {
+			if (!region->get_enabled()) {
+				continue;
+			}
 			const LocalVector<gd::Polygon> &polygons_source = region->get_polygons();
 			for (uint32_t n = 0; n < polygons_source.size(); n++) {
 				polygons[count + n] = polygons_source[n];
diff --git a/modules/navigation/nav_region.cpp b/modules/navigation/nav_region.cpp
index 9c0ce3e71ea..4e7964ed76c 100644
--- a/modules/navigation/nav_region.cpp
+++ b/modules/navigation/nav_region.cpp
@@ -51,6 +51,16 @@ void NavRegion::set_map(NavMap *p_map) {
 	}
 }
 
+void NavRegion::set_enabled(bool p_enabled) {
+	if (enabled == p_enabled) {
+		return;
+	}
+	enabled = p_enabled;
+
+	// TODO: This should not require a full rebuild as the region has not really changed.
+	polygons_dirty = true;
+};
+
 void NavRegion::set_use_edge_connections(bool p_enabled) {
 	if (use_edge_connections != p_enabled) {
 		use_edge_connections = p_enabled;
diff --git a/modules/navigation/nav_region.h b/modules/navigation/nav_region.h
index 0c3c1b56b6c..6a8ebe53362 100644
--- a/modules/navigation/nav_region.h
+++ b/modules/navigation/nav_region.h
@@ -41,6 +41,7 @@ class NavRegion : public NavBase {
 	Transform3D transform;
 	Ref<NavigationMesh> mesh;
 	Vector<gd::Edge::Connection> connections;
+	bool enabled = true;
 
 	bool use_edge_connections = true;
 
@@ -58,6 +59,9 @@ public:
 		polygons_dirty = true;
 	}
 
+	void set_enabled(bool p_enabled);
+	bool get_enabled() const { return enabled; }
+
 	void set_map(NavMap *p_map);
 	NavMap *get_map() const {
 		return map;
diff --git a/scene/2d/navigation_link_2d.cpp b/scene/2d/navigation_link_2d.cpp
index 3664040e7be..95798b68564 100644
--- a/scene/2d/navigation_link_2d.cpp
+++ b/scene/2d/navigation_link_2d.cpp
@@ -182,15 +182,7 @@ void NavigationLink2D::set_enabled(bool p_enabled) {
 
 	enabled = p_enabled;
 
-	if (!is_inside_tree()) {
-		return;
-	}
-
-	if (!enabled) {
-		NavigationServer2D::get_singleton()->link_set_map(link, RID());
-	} else {
-		NavigationServer2D::get_singleton()->link_set_map(link, get_world_2d()->get_navigation_map());
-	}
+	NavigationServer3D::get_singleton()->link_set_enabled(link, enabled);
 
 #ifdef DEBUG_ENABLED
 	if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_enabled()) {
diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp
index fa037135924..670a2c641c5 100644
--- a/scene/2d/navigation_region_2d.cpp
+++ b/scene/2d/navigation_region_2d.cpp
@@ -42,15 +42,7 @@ void NavigationRegion2D::set_enabled(bool p_enabled) {
 
 	enabled = p_enabled;
 
-	if (!is_inside_tree()) {
-		return;
-	}
-
-	if (!enabled) {
-		_region_enter_navigation_map();
-	} else {
-		_region_exit_navigation_map();
-	}
+	NavigationServer2D::get_singleton()->region_set_enabled(region, enabled);
 
 #ifdef DEBUG_ENABLED
 	if (Engine::get_singleton()->is_editor_hint() || NavigationServer2D::get_singleton()->get_debug_navigation_enabled()) {
diff --git a/scene/3d/navigation_link_3d.cpp b/scene/3d/navigation_link_3d.cpp
index 2263d38d6ce..70416ca93b6 100644
--- a/scene/3d/navigation_link_3d.cpp
+++ b/scene/3d/navigation_link_3d.cpp
@@ -291,15 +291,7 @@ void NavigationLink3D::set_enabled(bool p_enabled) {
 
 	enabled = p_enabled;
 
-	if (!is_inside_tree()) {
-		return;
-	}
-
-	if (enabled) {
-		NavigationServer3D::get_singleton()->link_set_map(link, get_world_3d()->get_navigation_map());
-	} else {
-		NavigationServer3D::get_singleton()->link_set_map(link, RID());
-	}
+	NavigationServer3D::get_singleton()->link_set_enabled(link, enabled);
 
 #ifdef DEBUG_ENABLED
 	if (debug_instance.is_valid() && debug_mesh.is_valid()) {
diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp
index 3f1cfae99d6..8d66f7ebebb 100644
--- a/scene/3d/navigation_region_3d.cpp
+++ b/scene/3d/navigation_region_3d.cpp
@@ -40,15 +40,7 @@ void NavigationRegion3D::set_enabled(bool p_enabled) {
 
 	enabled = p_enabled;
 
-	if (!is_inside_tree()) {
-		return;
-	}
-
-	if (!enabled) {
-		_region_enter_navigation_map();
-	} else {
-		_region_exit_navigation_map();
-	}
+	NavigationServer3D::get_singleton()->region_set_enabled(region, enabled);
 
 #ifdef DEBUG_ENABLED
 	if (debug_instance.is_valid()) {
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index e906db2acff..cd92d9dd2f3 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -391,6 +391,8 @@ void NavigationServer2D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("query_path", "parameters", "result"), &NavigationServer2D::query_path);
 
 	ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer2D::region_create);
+	ClassDB::bind_method(D_METHOD("region_set_enabled", "region", "enabled"), &NavigationServer2D::region_set_enabled);
+	ClassDB::bind_method(D_METHOD("region_get_enabled", "region"), &NavigationServer2D::region_get_enabled);
 	ClassDB::bind_method(D_METHOD("region_set_use_edge_connections", "region", "enabled"), &NavigationServer2D::region_set_use_edge_connections);
 	ClassDB::bind_method(D_METHOD("region_get_use_edge_connections", "region"), &NavigationServer2D::region_get_use_edge_connections);
 	ClassDB::bind_method(D_METHOD("region_set_enter_cost", "region", "enter_cost"), &NavigationServer2D::region_set_enter_cost);
@@ -413,6 +415,8 @@ void NavigationServer2D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("link_create"), &NavigationServer2D::link_create);
 	ClassDB::bind_method(D_METHOD("link_set_map", "link", "map"), &NavigationServer2D::link_set_map);
 	ClassDB::bind_method(D_METHOD("link_get_map", "link"), &NavigationServer2D::link_get_map);
+	ClassDB::bind_method(D_METHOD("link_set_enabled", "link", "enabled"), &NavigationServer2D::link_set_enabled);
+	ClassDB::bind_method(D_METHOD("link_get_enabled", "link"), &NavigationServer2D::link_get_enabled);
 	ClassDB::bind_method(D_METHOD("link_set_bidirectional", "link", "bidirectional"), &NavigationServer2D::link_set_bidirectional);
 	ClassDB::bind_method(D_METHOD("link_is_bidirectional", "link"), &NavigationServer2D::link_is_bidirectional);
 	ClassDB::bind_method(D_METHOD("link_set_navigation_layers", "link", "navigation_layers"), &NavigationServer2D::link_set_navigation_layers);
@@ -536,6 +540,8 @@ RID FORWARD_2_C(map_get_closest_point_owner, RID, p_map, const Vector2 &, p_poin
 
 RID FORWARD_0(region_create);
 
+void FORWARD_2(region_set_enabled, RID, p_region, bool, p_enabled, rid_to_rid, bool_to_bool);
+bool FORWARD_1_C(region_get_enabled, RID, p_region, rid_to_rid);
 void FORWARD_2(region_set_use_edge_connections, RID, p_region, bool, p_enabled, rid_to_rid, bool_to_bool);
 bool FORWARD_1_C(region_get_use_edge_connections, RID, p_region, rid_to_rid);
 
@@ -564,6 +570,8 @@ RID FORWARD_0(link_create);
 
 void FORWARD_2(link_set_map, RID, p_link, RID, p_map, rid_to_rid, rid_to_rid);
 RID FORWARD_1_C(link_get_map, RID, p_link, rid_to_rid);
+void FORWARD_2(link_set_enabled, RID, p_link, bool, p_enabled, rid_to_rid, bool_to_bool);
+bool FORWARD_1_C(link_get_enabled, RID, p_link, rid_to_rid);
 void FORWARD_2(link_set_bidirectional, RID, p_link, bool, p_bidirectional, rid_to_rid, bool_to_bool);
 bool FORWARD_1_C(link_is_bidirectional, RID, p_link, rid_to_rid);
 void FORWARD_2(link_set_navigation_layers, RID, p_link, uint32_t, p_navigation_layers, rid_to_rid, uint32_to_uint32);
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index b9b1e2a75e9..c78edaf8788 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -101,6 +101,9 @@ public:
 	/// Creates a new region.
 	virtual RID region_create();
 
+	virtual void region_set_enabled(RID p_region, bool p_enabled);
+	virtual bool region_get_enabled(RID p_region) const;
+
 	virtual void region_set_use_edge_connections(RID p_region, bool p_enabled);
 	virtual bool region_get_use_edge_connections(RID p_region) const;
 
@@ -144,6 +147,9 @@ public:
 	virtual void link_set_map(RID p_link, RID p_map);
 	virtual RID link_get_map(RID p_link) const;
 
+	virtual void link_set_enabled(RID p_link, bool p_enabled);
+	virtual bool link_get_enabled(RID p_link) const;
+
 	/// Set whether this link travels in both directions.
 	virtual void link_set_bidirectional(RID p_link, bool p_bidirectional);
 	virtual bool link_is_bidirectional(RID p_link) const;
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index 89d45b19299..04facdb8d95 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -67,6 +67,8 @@ void NavigationServer3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("query_path", "parameters", "result"), &NavigationServer3D::query_path);
 
 	ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer3D::region_create);
+	ClassDB::bind_method(D_METHOD("region_set_enabled", "region", "enabled"), &NavigationServer3D::region_set_enabled);
+	ClassDB::bind_method(D_METHOD("region_get_enabled", "region"), &NavigationServer3D::region_get_enabled);
 	ClassDB::bind_method(D_METHOD("region_set_use_edge_connections", "region", "enabled"), &NavigationServer3D::region_set_use_edge_connections);
 	ClassDB::bind_method(D_METHOD("region_get_use_edge_connections", "region"), &NavigationServer3D::region_get_use_edge_connections);
 	ClassDB::bind_method(D_METHOD("region_set_enter_cost", "region", "enter_cost"), &NavigationServer3D::region_set_enter_cost);
@@ -92,6 +94,8 @@ void NavigationServer3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("link_create"), &NavigationServer3D::link_create);
 	ClassDB::bind_method(D_METHOD("link_set_map", "link", "map"), &NavigationServer3D::link_set_map);
 	ClassDB::bind_method(D_METHOD("link_get_map", "link"), &NavigationServer3D::link_get_map);
+	ClassDB::bind_method(D_METHOD("link_set_enabled", "link", "enabled"), &NavigationServer3D::link_set_enabled);
+	ClassDB::bind_method(D_METHOD("link_get_enabled", "link"), &NavigationServer3D::link_get_enabled);
 	ClassDB::bind_method(D_METHOD("link_set_bidirectional", "link", "bidirectional"), &NavigationServer3D::link_set_bidirectional);
 	ClassDB::bind_method(D_METHOD("link_is_bidirectional", "link"), &NavigationServer3D::link_is_bidirectional);
 	ClassDB::bind_method(D_METHOD("link_set_navigation_layers", "link", "navigation_layers"), &NavigationServer3D::link_set_navigation_layers);
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index 0764690b813..391730e18f5 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -117,6 +117,9 @@ public:
 	/// Creates a new region.
 	virtual RID region_create() = 0;
 
+	virtual void region_set_enabled(RID p_region, bool p_enabled) = 0;
+	virtual bool region_get_enabled(RID p_region) const = 0;
+
 	virtual void region_set_use_edge_connections(RID p_region, bool p_enabled) = 0;
 	virtual bool region_get_use_edge_connections(RID p_region) const = 0;
 
@@ -165,6 +168,9 @@ public:
 	virtual void link_set_map(RID p_link, RID p_map) = 0;
 	virtual RID link_get_map(RID p_link) const = 0;
 
+	virtual void link_set_enabled(RID p_link, bool p_enabled) = 0;
+	virtual bool link_get_enabled(RID p_link) const = 0;
+
 	/// Set whether this link travels in both directions.
 	virtual void link_set_bidirectional(RID p_link, bool p_bidirectional) = 0;
 	virtual bool link_is_bidirectional(RID p_link) const = 0;
diff --git a/servers/navigation_server_3d_dummy.h b/servers/navigation_server_3d_dummy.h
index 4a2e9f74393..b2d452f67a0 100644
--- a/servers/navigation_server_3d_dummy.h
+++ b/servers/navigation_server_3d_dummy.h
@@ -64,6 +64,8 @@ public:
 	TypedArray<RID> map_get_obstacles(RID p_map) const override { return TypedArray<RID>(); }
 	void map_force_update(RID p_map) override {}
 	RID region_create() override { return RID(); }
+	void region_set_enabled(RID p_region, bool p_enabled) override {}
+	bool region_get_enabled(RID p_region) const override { return false; }
 	void region_set_use_edge_connections(RID p_region, bool p_enabled) override {}
 	bool region_get_use_edge_connections(RID p_region) const override { return false; }
 	void region_set_enter_cost(RID p_region, real_t p_enter_cost) override {}
@@ -88,6 +90,8 @@ public:
 	RID link_create() override { return RID(); }
 	void link_set_map(RID p_link, RID p_map) override {}
 	RID link_get_map(RID p_link) const override { return RID(); }
+	void link_set_enabled(RID p_link, bool p_enabled) override {}
+	bool link_get_enabled(RID p_link) const override { return false; }
 	void link_set_bidirectional(RID p_link, bool p_bidirectional) override {}
 	bool link_is_bidirectional(RID p_link) const override { return false; }
 	void link_set_navigation_layers(RID p_link, uint32_t p_navigation_layers) override {}