From 58593d1bb706410bbdbd265ed8b698eb95b7b61f Mon Sep 17 00:00:00 2001
From: smix8 <52464204+smix8@users.noreply.github.com>
Date: Thu, 18 Apr 2024 22:47:28 +0200
Subject: [PATCH] Add navigation source geometry parser callbacks
Adds navigation source geometry parser callbacks so that externals can hook their own geometry into the navigation mesh baking process.
---
doc/classes/NavigationServer2D.xml | 17 ++++++
doc/classes/NavigationServer3D.xml | 17 ++++++
.../2d/godot_navigation_server_2d.cpp | 28 ++++++++-
.../2d/godot_navigation_server_2d.h | 3 +
.../navigation/2d/nav_mesh_generator_2d.cpp | 60 +++++++++++++++++++
modules/navigation/2d/nav_mesh_generator_2d.h | 15 +++++
.../3d/godot_navigation_server_3d.cpp | 22 +++++++
.../3d/godot_navigation_server_3d.h | 3 +
.../navigation/3d/nav_mesh_generator_3d.cpp | 60 +++++++++++++++++++
modules/navigation/3d/nav_mesh_generator_3d.h | 15 +++++
servers/navigation_server_2d.cpp | 3 +
servers/navigation_server_2d.h | 3 +
servers/navigation_server_2d_dummy.h | 3 +
servers/navigation_server_3d.cpp | 3 +
servers/navigation_server_3d.h | 3 +
servers/navigation_server_3d_dummy.h | 3 +
16 files changed, 257 insertions(+), 1 deletion(-)
diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index a6f6abccbd7..a0d03d7a012 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -956,6 +956,23 @@
Path simplification can be helpful to mitigate various path following issues that can arise with certain agent types and script behaviors. E.g. "steering" agents or avoidance in "open fields".
+
+
+
+ Creates a new source geometry parser. If a [Callable] is set for the parser with [method source_geometry_parser_set_callback] the callback will be called for every single node that gets parsed whenever [method parse_source_geometry_data] is used.
+
+
+
+
+
+
+
+ Sets the [param callback] [Callable] for the specific source geometry [param parser]. The [Callable] will receive a call with the following parameters:
+ - [code]navigation_mesh[/code] - The [NavigationPolygon] reference used to define the parse settings. Do NOT edit or add directly to the navigation mesh.
+ - [code]source_geometry_data[/code] - The [NavigationMeshSourceGeometryData2D] reference. Add custom source geometry for navigation mesh baking to this object.
+ - [code]node[/code] - The [Node] that is parsed.
+
+
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index 6fcf033544f..ff3e6fd8a64 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -1103,6 +1103,23 @@
Path simplification can be helpful to mitigate various path following issues that can arise with certain agent types and script behaviors. E.g. "steering" agents or avoidance in "open fields".
+
+
+
+ Creates a new source geometry parser. If a [Callable] is set for the parser with [method source_geometry_parser_set_callback] the callback will be called for every single node that gets parsed whenever [method parse_source_geometry_data] is used.
+
+
+
+
+
+
+
+ Sets the [param callback] [Callable] for the specific source geometry [param parser]. The [Callable] will receive a call with the following parameters:
+ - [code]navigation_mesh[/code] - The [NavigationMesh] reference used to define the parse settings. Do NOT edit or add directly to the navigation mesh.
+ - [code]source_geometry_data[/code] - The [NavigationMeshSourceGeometryData3D] reference. Add custom source geometry for navigation mesh baking to this object.
+ - [code]node[/code] - The [Node] that is parsed.
+
+
diff --git a/modules/navigation/2d/godot_navigation_server_2d.cpp b/modules/navigation/2d/godot_navigation_server_2d.cpp
index 5eefbe42280..bf69adc14c9 100644
--- a/modules/navigation/2d/godot_navigation_server_2d.cpp
+++ b/modules/navigation/2d/godot_navigation_server_2d.cpp
@@ -389,7 +389,16 @@ bool FORWARD_1_C(agent_is_map_changed, RID, p_agent, rid_to_rid);
void FORWARD_2(agent_set_paused, RID, p_agent, bool, p_paused, rid_to_rid, bool_to_bool);
bool FORWARD_1_C(agent_get_paused, RID, p_agent, rid_to_rid);
-void FORWARD_1(free, RID, p_object, rid_to_rid);
+void GodotNavigationServer2D::free(RID p_object) {
+#ifdef CLIPPER2_ENABLED
+ if (navmesh_generator_2d && navmesh_generator_2d->owns(p_object)) {
+ navmesh_generator_2d->free(p_object);
+ return;
+ }
+#endif // CLIPPER2_ENABLED
+ NavigationServer3D::get_singleton()->free(p_object);
+}
+
void FORWARD_2(agent_set_avoidance_callback, RID, p_agent, Callable, p_callback, rid_to_rid, callable_to_callable);
bool GodotNavigationServer2D::agent_has_avoidance_callback(RID p_agent) const {
return NavigationServer3D::get_singleton()->agent_has_avoidance_callback(p_agent);
@@ -453,3 +462,20 @@ void GodotNavigationServer2D::query_path(const Refset_path_rids(_query_result.path_rids);
p_query_result->set_path_owner_ids(_query_result.path_owner_ids);
}
+
+RID GodotNavigationServer2D::source_geometry_parser_create() {
+#ifdef CLIPPER2_ENABLED
+ if (navmesh_generator_2d) {
+ return navmesh_generator_2d->source_geometry_parser_create();
+ }
+#endif // CLIPPER2_ENABLED
+ return RID();
+}
+
+void GodotNavigationServer2D::source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) {
+#ifdef CLIPPER2_ENABLED
+ if (navmesh_generator_2d) {
+ navmesh_generator_2d->source_geometry_parser_set_callback(p_parser, p_callback);
+ }
+#endif // CLIPPER2_ENABLED
+}
diff --git a/modules/navigation/2d/godot_navigation_server_2d.h b/modules/navigation/2d/godot_navigation_server_2d.h
index ba375afd33d..ea77fa5e6ec 100644
--- a/modules/navigation/2d/godot_navigation_server_2d.h
+++ b/modules/navigation/2d/godot_navigation_server_2d.h
@@ -253,6 +253,9 @@ public:
virtual void bake_from_source_geometry_data_async(const Ref &p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback = Callable()) override;
virtual bool is_baking_navigation_polygon(Ref p_navigation_polygon) const override;
+ virtual RID source_geometry_parser_create() override;
+ virtual void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) override;
+
virtual Vector simplify_path(const Vector &p_path, real_t p_epsilon) override;
};
diff --git a/modules/navigation/2d/nav_mesh_generator_2d.cpp b/modules/navigation/2d/nav_mesh_generator_2d.cpp
index 90002595246..13399b858ed 100644
--- a/modules/navigation/2d/nav_mesh_generator_2d.cpp
+++ b/modules/navigation/2d/nav_mesh_generator_2d.cpp
@@ -53,11 +53,14 @@
NavMeshGenerator2D *NavMeshGenerator2D::singleton = nullptr;
Mutex NavMeshGenerator2D::baking_navmesh_mutex;
Mutex NavMeshGenerator2D::generator_task_mutex;
+RWLock NavMeshGenerator2D::generator_rid_rwlock;
bool NavMeshGenerator2D::use_threads = true;
bool NavMeshGenerator2D::baking_use_multiple_threads = true;
bool NavMeshGenerator2D::baking_use_high_priority_threads = true;
HashSet[> NavMeshGenerator2D::baking_navmeshes;
HashMap NavMeshGenerator2D::generator_tasks;
+RID_Owner NavMeshGenerator2D::generator_parser_owner;
+LocalVector NavMeshGenerator2D::generator_parsers;
NavMeshGenerator2D *NavMeshGenerator2D::get_singleton() {
return singleton;
@@ -126,6 +129,13 @@ void NavMeshGenerator2D::cleanup() {
}
generator_tasks.clear();
+ generator_rid_rwlock.write_lock();
+ for (NavMeshGeometryParser2D *parser : generator_parsers) {
+ generator_parser_owner.free(parser->self);
+ }
+ generator_parsers.clear();
+ generator_rid_rwlock.write_unlock();
+
generator_task_mutex.unlock();
baking_navmesh_mutex.unlock();
}
@@ -236,6 +246,15 @@ void NavMeshGenerator2D::generator_parse_geometry_node(Ref p_
generator_parse_tilemap_node(p_navigation_mesh, p_source_geometry_data, p_node);
generator_parse_navigationobstacle_node(p_navigation_mesh, p_source_geometry_data, p_node);
+ generator_rid_rwlock.read_lock();
+ for (const NavMeshGeometryParser2D *parser : generator_parsers) {
+ if (!parser->callback.is_valid()) {
+ continue;
+ }
+ parser->callback.call(p_navigation_mesh, p_source_geometry_data, p_node);
+ }
+ generator_rid_rwlock.read_unlock();
+
if (p_recurse_children) {
for (int i = 0; i < p_node->get_child_count(); i++) {
generator_parse_geometry_node(p_navigation_mesh, p_source_geometry_data, p_node->get_child(i), p_recurse_children);
@@ -813,6 +832,47 @@ bool NavMeshGenerator2D::generator_emit_callback(const Callable &p_callback) {
return ce.error == Callable::CallError::CALL_OK;
}
+RID NavMeshGenerator2D::source_geometry_parser_create() {
+ RWLockWrite write_lock(generator_rid_rwlock);
+
+ RID rid = generator_parser_owner.make_rid();
+
+ NavMeshGeometryParser2D *parser = generator_parser_owner.get_or_null(rid);
+ parser->self = rid;
+
+ generator_parsers.push_back(parser);
+
+ return rid;
+}
+
+void NavMeshGenerator2D::source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) {
+ RWLockWrite write_lock(generator_rid_rwlock);
+
+ NavMeshGeometryParser2D *parser = generator_parser_owner.get_or_null(p_parser);
+ ERR_FAIL_NULL(parser);
+
+ parser->callback = p_callback;
+}
+
+bool NavMeshGenerator2D::owns(RID p_object) {
+ RWLockRead read_lock(generator_rid_rwlock);
+ return generator_parser_owner.owns(p_object);
+}
+
+void NavMeshGenerator2D::free(RID p_object) {
+ RWLockWrite write_lock(generator_rid_rwlock);
+
+ if (generator_parser_owner.owns(p_object)) {
+ NavMeshGeometryParser2D *parser = generator_parser_owner.get_or_null(p_object);
+
+ generator_parsers.erase(parser);
+
+ generator_parser_owner.free(p_object);
+ } else {
+ ERR_PRINT("Attempted to free a NavMeshGenerator2D RID that did not exist (or was already freed).");
+ }
+}
+
void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref p_navigation_mesh, Ref p_source_geometry_data) {
if (p_navigation_mesh.is_null() || p_source_geometry_data.is_null()) {
return;
diff --git a/modules/navigation/2d/nav_mesh_generator_2d.h b/modules/navigation/2d/nav_mesh_generator_2d.h
index 2567a170ef6..235a84d5487 100644
--- a/modules/navigation/2d/nav_mesh_generator_2d.h
+++ b/modules/navigation/2d/nav_mesh_generator_2d.h
@@ -35,6 +35,7 @@
#include "core/object/class_db.h"
#include "core/object/worker_thread_pool.h"
+#include "core/templates/rid_owner.h"
class Node;
class NavigationPolygon;
@@ -46,6 +47,14 @@ class NavMeshGenerator2D : public Object {
static Mutex baking_navmesh_mutex;
static Mutex generator_task_mutex;
+ static RWLock generator_rid_rwlock;
+ struct NavMeshGeometryParser2D {
+ RID self;
+ Callable callback;
+ };
+ static RID_Owner generator_parser_owner;
+ static LocalVector generator_parsers;
+
static bool use_threads;
static bool baking_use_multiple_threads;
static bool baking_use_high_priority_threads;
@@ -97,6 +106,12 @@ public:
static void bake_from_source_geometry_data_async(Ref p_navigation_mesh, Ref p_source_geometry_data, const Callable &p_callback = Callable());
static bool is_baking(Ref p_navigation_polygon);
+ static RID source_geometry_parser_create();
+ static void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback);
+
+ static bool owns(RID p_object);
+ static void free(RID p_object);
+
NavMeshGenerator2D();
~NavMeshGenerator2D();
};
diff --git a/modules/navigation/3d/godot_navigation_server_3d.cpp b/modules/navigation/3d/godot_navigation_server_3d.cpp
index 301b4aa8f38..61a128e0047 100644
--- a/modules/navigation/3d/godot_navigation_server_3d.cpp
+++ b/modules/navigation/3d/godot_navigation_server_3d.cpp
@@ -1202,6 +1202,11 @@ COMMAND_1(free, RID, p_object) {
} else if (obstacle_owner.owns(p_object)) {
internal_free_obstacle(p_object);
+#ifndef _3D_DISABLED
+ } else if (navmesh_generator_3d && navmesh_generator_3d->owns(p_object)) {
+ navmesh_generator_3d->free(p_object);
+#endif // _3D_DISABLED
+
} else {
ERR_PRINT("Attempted to free a NavigationServer RID that did not exist (or was already freed).");
}
@@ -1428,6 +1433,23 @@ PathQueryResult GodotNavigationServer3D::_query_path(const PathQueryParameters &
return r_query_result;
}
+RID GodotNavigationServer3D::source_geometry_parser_create() {
+#ifndef _3D_DISABLED
+ if (navmesh_generator_3d) {
+ return navmesh_generator_3d->source_geometry_parser_create();
+ }
+#endif // _3D_DISABLED
+ return RID();
+}
+
+void GodotNavigationServer3D::source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) {
+#ifndef _3D_DISABLED
+ if (navmesh_generator_3d) {
+ navmesh_generator_3d->source_geometry_parser_set_callback(p_parser, p_callback);
+ }
+#endif // _3D_DISABLED
+}
+
Vector GodotNavigationServer3D::simplify_path(const Vector &p_path, real_t p_epsilon) {
if (p_path.size() <= 2) {
return p_path;
diff --git a/modules/navigation/3d/godot_navigation_server_3d.h b/modules/navigation/3d/godot_navigation_server_3d.h
index 89839ff459b..5ba7ed1088e 100644
--- a/modules/navigation/3d/godot_navigation_server_3d.h
+++ b/modules/navigation/3d/godot_navigation_server_3d.h
@@ -264,6 +264,9 @@ public:
virtual void bake_from_source_geometry_data_async(const Ref &p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback = Callable()) override;
virtual bool is_baking_navigation_mesh(Ref p_navigation_mesh) const override;
+ virtual RID source_geometry_parser_create() override;
+ virtual void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) override;
+
virtual Vector simplify_path(const Vector &p_path, real_t p_epsilon) override;
private:
diff --git a/modules/navigation/3d/nav_mesh_generator_3d.cpp b/modules/navigation/3d/nav_mesh_generator_3d.cpp
index b1b3cbed5de..cc3bbdbf01e 100644
--- a/modules/navigation/3d/nav_mesh_generator_3d.cpp
+++ b/modules/navigation/3d/nav_mesh_generator_3d.cpp
@@ -66,11 +66,14 @@
NavMeshGenerator3D *NavMeshGenerator3D::singleton = nullptr;
Mutex NavMeshGenerator3D::baking_navmesh_mutex;
Mutex NavMeshGenerator3D::generator_task_mutex;
+RWLock NavMeshGenerator3D::generator_rid_rwlock;
bool NavMeshGenerator3D::use_threads = true;
bool NavMeshGenerator3D::baking_use_multiple_threads = true;
bool NavMeshGenerator3D::baking_use_high_priority_threads = true;
HashSet][> NavMeshGenerator3D::baking_navmeshes;
HashMap NavMeshGenerator3D::generator_tasks;
+RID_Owner NavMeshGenerator3D::generator_parser_owner;
+LocalVector NavMeshGenerator3D::generator_parsers;
NavMeshGenerator3D *NavMeshGenerator3D::get_singleton() {
return singleton;
@@ -139,6 +142,13 @@ void NavMeshGenerator3D::cleanup() {
}
generator_tasks.clear();
+ generator_rid_rwlock.write_lock();
+ for (NavMeshGeometryParser3D *parser : generator_parsers) {
+ generator_parser_owner.free(parser->self);
+ }
+ generator_parsers.clear();
+ generator_rid_rwlock.write_unlock();
+
generator_task_mutex.unlock();
baking_navmesh_mutex.unlock();
}
@@ -254,6 +264,15 @@ void NavMeshGenerator3D::generator_parse_geometry_node(const Ref
#endif
generator_parse_navigationobstacle_node(p_navigation_mesh, p_source_geometry_data, p_node);
+ generator_rid_rwlock.read_lock();
+ for (const NavMeshGeometryParser3D *parser : generator_parsers) {
+ if (!parser->callback.is_valid()) {
+ continue;
+ }
+ parser->callback.call(p_navigation_mesh, p_source_geometry_data, p_node);
+ }
+ generator_rid_rwlock.read_unlock();
+
if (p_recurse_children) {
for (int i = 0; i < p_node->get_child_count(); i++) {
generator_parse_geometry_node(p_navigation_mesh, p_source_geometry_data, p_node->get_child(i), p_recurse_children);
@@ -920,4 +939,45 @@ bool NavMeshGenerator3D::generator_emit_callback(const Callable &p_callback) {
return ce.error == Callable::CallError::CALL_OK;
}
+RID NavMeshGenerator3D::source_geometry_parser_create() {
+ RWLockWrite write_lock(generator_rid_rwlock);
+
+ RID rid = generator_parser_owner.make_rid();
+
+ NavMeshGeometryParser3D *parser = generator_parser_owner.get_or_null(rid);
+ parser->self = rid;
+
+ generator_parsers.push_back(parser);
+
+ return rid;
+}
+
+void NavMeshGenerator3D::source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) {
+ RWLockWrite write_lock(generator_rid_rwlock);
+
+ NavMeshGeometryParser3D *parser = generator_parser_owner.get_or_null(p_parser);
+ ERR_FAIL_NULL(parser);
+
+ parser->callback = p_callback;
+}
+
+bool NavMeshGenerator3D::owns(RID p_object) {
+ RWLockRead read_lock(generator_rid_rwlock);
+ return generator_parser_owner.owns(p_object);
+}
+
+void NavMeshGenerator3D::free(RID p_object) {
+ RWLockWrite write_lock(generator_rid_rwlock);
+
+ if (generator_parser_owner.owns(p_object)) {
+ NavMeshGeometryParser3D *parser = generator_parser_owner.get_or_null(p_object);
+
+ generator_parsers.erase(parser);
+
+ generator_parser_owner.free(p_object);
+ } else {
+ ERR_PRINT("Attempted to free a NavMeshGenerator3D RID that did not exist (or was already freed).");
+ }
+}
+
#endif // _3D_DISABLED
diff --git a/modules/navigation/3d/nav_mesh_generator_3d.h b/modules/navigation/3d/nav_mesh_generator_3d.h
index 9c9b3bdefef..b46a1736e01 100644
--- a/modules/navigation/3d/nav_mesh_generator_3d.h
+++ b/modules/navigation/3d/nav_mesh_generator_3d.h
@@ -35,6 +35,7 @@
#include "core/object/class_db.h"
#include "core/object/worker_thread_pool.h"
+#include "core/templates/rid_owner.h"
#include "modules/modules_enabled.gen.h" // For csg, gridmap.
class Node;
@@ -47,6 +48,14 @@ class NavMeshGenerator3D : public Object {
static Mutex baking_navmesh_mutex;
static Mutex generator_task_mutex;
+ static RWLock generator_rid_rwlock;
+ struct NavMeshGeometryParser3D {
+ RID self;
+ Callable callback;
+ };
+ static RID_Owner generator_parser_owner;
+ static LocalVector generator_parsers;
+
static bool use_threads;
static bool baking_use_multiple_threads;
static bool baking_use_high_priority_threads;
@@ -102,6 +111,12 @@ public:
static void bake_from_source_geometry_data_async(Ref p_navigation_mesh, Ref p_source_geometry_data, const Callable &p_callback = Callable());
static bool is_baking(Ref p_navigation_mesh);
+ static RID source_geometry_parser_create();
+ static void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback);
+
+ static bool owns(RID p_object);
+ static void free(RID p_object);
+
NavMeshGenerator3D();
~NavMeshGenerator3D();
};
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index 625ae8abde1..c5ce82265b7 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -165,6 +165,9 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("bake_from_source_geometry_data_async", "navigation_polygon", "source_geometry_data", "callback"), &NavigationServer2D::bake_from_source_geometry_data_async, DEFVAL(Callable()));
ClassDB::bind_method(D_METHOD("is_baking_navigation_polygon", "navigation_polygon"), &NavigationServer2D::is_baking_navigation_polygon);
+ ClassDB::bind_method(D_METHOD("source_geometry_parser_create"), &NavigationServer2D::source_geometry_parser_create);
+ ClassDB::bind_method(D_METHOD("source_geometry_parser_set_callback", "parser", "callback"), &NavigationServer2D::source_geometry_parser_set_callback);
+
ClassDB::bind_method(D_METHOD("simplify_path", "path", "epsilon"), &NavigationServer2D::simplify_path);
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer2D::free);
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index 39d4c19064e..a8d9678a6f0 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -306,6 +306,9 @@ public:
virtual void bake_from_source_geometry_data_async(const Ref &p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback = Callable()) = 0;
virtual bool is_baking_navigation_polygon(Ref p_navigation_polygon) const = 0;
+ virtual RID source_geometry_parser_create() = 0;
+ virtual void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) = 0;
+
virtual Vector simplify_path(const Vector &p_path, real_t p_epsilon) = 0;
NavigationServer2D();
diff --git a/servers/navigation_server_2d_dummy.h b/servers/navigation_server_2d_dummy.h
index 5d4cfbf91b1..465cfcca988 100644
--- a/servers/navigation_server_2d_dummy.h
+++ b/servers/navigation_server_2d_dummy.h
@@ -170,6 +170,9 @@ public:
void bake_from_source_geometry_data_async(const Ref &p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback = Callable()) override {}
bool is_baking_navigation_polygon(Ref p_navigation_polygon) const override { return false; }
+ RID source_geometry_parser_create() override { return RID(); }
+ void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) override {}
+
Vector simplify_path(const Vector &p_path, real_t p_epsilon) override { return Vector(); }
void set_debug_enabled(bool p_enabled) {}
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index fda26aacc1a..b21c6b60f0c 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -188,6 +188,9 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_baking_navigation_mesh", "navigation_mesh"), &NavigationServer3D::is_baking_navigation_mesh);
#endif // _3D_DISABLED
+ ClassDB::bind_method(D_METHOD("source_geometry_parser_create"), &NavigationServer3D::source_geometry_parser_create);
+ ClassDB::bind_method(D_METHOD("source_geometry_parser_set_callback", "parser", "callback"), &NavigationServer3D::source_geometry_parser_set_callback);
+
ClassDB::bind_method(D_METHOD("simplify_path", "path", "epsilon"), &NavigationServer3D::simplify_path);
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer3D::free);
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index 5a93c662b2d..17c0771732f 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -351,6 +351,9 @@ public:
virtual bool is_baking_navigation_mesh(Ref p_navigation_mesh) const = 0;
#endif // _3D_DISABLED
+ virtual RID source_geometry_parser_create() = 0;
+ virtual void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) = 0;
+
virtual Vector simplify_path(const Vector &p_path, real_t p_epsilon) = 0;
NavigationServer3D();
diff --git a/servers/navigation_server_3d_dummy.h b/servers/navigation_server_3d_dummy.h
index 7079aa66beb..5c9e97d2265 100644
--- a/servers/navigation_server_3d_dummy.h
+++ b/servers/navigation_server_3d_dummy.h
@@ -182,6 +182,9 @@ public:
bool is_baking_navigation_mesh(Ref p_navigation_mesh) const override { return false; }
#endif // _3D_DISABLED
+ RID source_geometry_parser_create() override { return RID(); }
+ void source_geometry_parser_set_callback(RID p_parser, const Callable &p_callback) override {}
+
Vector simplify_path(const Vector &p_path, real_t p_epsilon) override { return Vector(); }
void free(RID p_object) override {}
]