From 8686e84b4408d5ba4a2da81327de4fd2826a23e8 Mon Sep 17 00:00:00 2001 From: smix8 <52464204+smix8@users.noreply.github.com> Date: Fri, 7 Jul 2023 15:59:10 +0200 Subject: [PATCH] Add multi-threaded NavMesh baking to NavigationServer Adds multi-threaded NavMesh baking to NavigationServer. --- doc/classes/NavigationServer3D.xml | 9 ++ doc/classes/ProjectSettings.xml | 6 + .../navigation/godot_navigation_server.cpp | 34 +++-- modules/navigation/godot_navigation_server.h | 5 +- modules/navigation/nav_mesh_generator_3d.cpp | 125 ++++++++++++++++-- modules/navigation/nav_mesh_generator_3d.h | 32 ++++- scene/3d/navigation_region_3d.cpp | 53 ++------ scene/3d/navigation_region_3d.h | 2 - servers/navigation_server_3d.cpp | 4 + servers/navigation_server_3d.h | 5 +- servers/navigation_server_3d_dummy.h | 5 +- 11 files changed, 205 insertions(+), 75 deletions(-) diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml index 86c605b8a30..b56b86f435d 100644 --- a/doc/classes/NavigationServer3D.xml +++ b/doc/classes/NavigationServer3D.xml @@ -216,6 +216,15 @@ Bakes the provided [param navigation_mesh] with the data from the provided [param source_geometry_data]. After the process is finished the optional [param callback] will be called. + + + + + + + Bakes the provided [param navigation_mesh] with the data from the provided [param source_geometry_data] as an async task running on a background thread. After the process is finished the optional [param callback] will be called. + + diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index de667a02e6b..52ae508bb1b 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -1991,6 +1991,12 @@ If enabled the avoidance calculations use multiple threads. + + If enabled and async navmesh baking uses multiple threads the threads run with high priority. + + + If enabled the async navmesh baking uses multiple threads. + Maximum number of characters allowed to send as output from the debugger. Over this value, content is dropped. This helps not to stall the debugger connection. diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp index 8f56bf0f1d1..9162fcf171a 100644 --- a/modules/navigation/godot_navigation_server.cpp +++ b/modules/navigation/godot_navigation_server.cpp @@ -930,7 +930,7 @@ COMMAND_2(obstacle_set_avoidance_layers, RID, p_obstacle, uint32_t, p_layers) { obstacle->set_avoidance_layers(p_layers); } -void GodotNavigationServer::parse_source_geometry_data(const Ref &p_navigation_mesh, Ref p_source_geometry_data, Node *p_root_node, const Callable &p_callback) { +void GodotNavigationServer::parse_source_geometry_data(const Ref &p_navigation_mesh, const Ref &p_source_geometry_data, Node *p_root_node, const Callable &p_callback) { #ifndef _3D_DISABLED ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "The SceneTree can only be parsed on the main thread. Call this function from the main thread or use call_deferred()."); ERR_FAIL_COND_MSG(!p_navigation_mesh.is_valid(), "Invalid navigation mesh."); @@ -942,26 +942,26 @@ void GodotNavigationServer::parse_source_geometry_data(const Ref #endif // _3D_DISABLED } -void GodotNavigationServer::bake_from_source_geometry_data(Ref p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback) { +void GodotNavigationServer::bake_from_source_geometry_data(const Ref &p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback) { #ifndef _3D_DISABLED ERR_FAIL_COND_MSG(!p_navigation_mesh.is_valid(), "Invalid navigation mesh."); ERR_FAIL_COND_MSG(!p_source_geometry_data.is_valid(), "Invalid NavigationMeshSourceGeometryData3D."); - if (!p_source_geometry_data->has_data()) { - p_navigation_mesh->clear(); - if (p_callback.is_valid()) { - Callable::CallError ce; - Variant result; - p_callback.callp(nullptr, 0, result, ce); - } - return; - } - ERR_FAIL_NULL(NavMeshGenerator3D::get_singleton()); NavMeshGenerator3D::get_singleton()->bake_from_source_geometry_data(p_navigation_mesh, p_source_geometry_data, p_callback); #endif // _3D_DISABLED } +void GodotNavigationServer::bake_from_source_geometry_data_async(const Ref &p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback) { +#ifndef _3D_DISABLED + ERR_FAIL_COND_MSG(!p_navigation_mesh.is_valid(), "Invalid navigation mesh."); + ERR_FAIL_COND_MSG(!p_source_geometry_data.is_valid(), "Invalid NavigationMeshSourceGeometryData3D."); + + ERR_FAIL_NULL(NavMeshGenerator3D::get_singleton()); + NavMeshGenerator3D::get_singleton()->bake_from_source_geometry_data_async(p_navigation_mesh, p_source_geometry_data, p_callback); +#endif // _3D_DISABLED +} + COMMAND_1(free, RID, p_object) { if (map_owner.owns(p_object)) { NavMap *map = map_owner.get_or_null(p_object); @@ -1093,6 +1093,16 @@ void GodotNavigationServer::process(real_t p_delta_time) { return; } +#ifndef _3D_DISABLED + // Sync finished navmesh bakes before doing NavMap updates. + if (navmesh_generator_3d) { + navmesh_generator_3d->sync(); + // Finished bakes emit callbacks and users might have reacted to those. + // Flush queue again so users do not have to wait for the next sync. + flush_queries(); + } +#endif // _3D_DISABLED + int _new_pm_region_count = 0; int _new_pm_agent_count = 0; int _new_pm_link_count = 0; diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h index 8b91ca36bdc..40893bada6a 100644 --- a/modules/navigation/godot_navigation_server.h +++ b/modules/navigation/godot_navigation_server.h @@ -228,8 +228,9 @@ public: virtual void obstacle_set_vertices(RID p_obstacle, const Vector &p_vertices) override; COMMAND_2(obstacle_set_avoidance_layers, RID, p_obstacle, uint32_t, p_layers); - virtual void parse_source_geometry_data(const Ref &p_navigation_mesh, Ref p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()) override; - virtual void bake_from_source_geometry_data(Ref p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback = Callable()) override; + virtual void parse_source_geometry_data(const Ref &p_navigation_mesh, const Ref &p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()) override; + virtual void bake_from_source_geometry_data(const Ref &p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback = Callable()) override; + 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; COMMAND_1(free, RID, p_object); diff --git a/modules/navigation/nav_mesh_generator_3d.cpp b/modules/navigation/nav_mesh_generator_3d.cpp index ab25a18d280..068ee31b5f8 100644 --- a/modules/navigation/nav_mesh_generator_3d.cpp +++ b/modules/navigation/nav_mesh_generator_3d.cpp @@ -32,6 +32,7 @@ #include "nav_mesh_generator_3d.h" +#include "core/config/project_settings.h" #include "core/math/convex_hull.h" #include "core/os/thread.h" #include "scene/3d/mesh_instance_3d.h" @@ -62,7 +63,12 @@ NavMeshGenerator3D *NavMeshGenerator3D::singleton = nullptr; Mutex NavMeshGenerator3D::baking_navmesh_mutex; +Mutex NavMeshGenerator3D::generator_task_mutex; +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; NavMeshGenerator3D *NavMeshGenerator3D::get_singleton() { return singleton; @@ -71,15 +77,67 @@ NavMeshGenerator3D *NavMeshGenerator3D::get_singleton() { NavMeshGenerator3D::NavMeshGenerator3D() { ERR_FAIL_COND(singleton != nullptr); singleton = this; + + baking_use_multiple_threads = GLOBAL_GET("navigation/baking/thread_model/baking_use_multiple_threads"); + baking_use_high_priority_threads = GLOBAL_GET("navigation/baking/thread_model/baking_use_high_priority_threads"); + + // Using threads might cause problems on certain exports or with the Editor on certain devices. + // This is the main switch to turn threaded navmesh baking off should the need arise. + use_threads = baking_use_multiple_threads && !Engine::get_singleton()->is_editor_hint(); } NavMeshGenerator3D::~NavMeshGenerator3D() { cleanup(); } +void NavMeshGenerator3D::sync() { + if (generator_tasks.size() == 0) { + return; + } + + baking_navmesh_mutex.lock(); + generator_task_mutex.lock(); + + LocalVector finished_task_ids; + + for (KeyValue &E : generator_tasks) { + if (WorkerThreadPool::get_singleton()->is_task_completed(E.key)) { + WorkerThreadPool::get_singleton()->wait_for_task_completion(E.key); + finished_task_ids.push_back(E.key); + + NavMeshGeneratorTask3D *generator_task = E.value; + DEV_ASSERT(generator_task->status == NavMeshGeneratorTask3D::TaskStatus::BAKING_FINISHED); + + baking_navmeshes.erase(generator_task->navigation_mesh); + if (generator_task->callback.is_valid()) { + generator_emit_callback(generator_task->callback); + } + memdelete(generator_task); + } + } + + for (WorkerThreadPool::TaskID finished_task_id : finished_task_ids) { + generator_tasks.erase(finished_task_id); + } + + generator_task_mutex.unlock(); + baking_navmesh_mutex.unlock(); +} + void NavMeshGenerator3D::cleanup() { baking_navmesh_mutex.lock(); + generator_task_mutex.lock(); + baking_navmeshes.clear(); + + for (KeyValue &E : generator_tasks) { + WorkerThreadPool::get_singleton()->wait_for_task_completion(E.key); + NavMeshGeneratorTask3D *generator_task = E.value; + memdelete(generator_task); + } + generator_tasks.clear(); + + generator_task_mutex.unlock(); baking_navmesh_mutex.unlock(); } @@ -87,7 +145,7 @@ void NavMeshGenerator3D::finish() { cleanup(); } -void NavMeshGenerator3D::parse_source_geometry_data(const Ref &p_navigation_mesh, Ref p_source_geometry_data, Node *p_root_node, const Callable &p_callback) { +void NavMeshGenerator3D::parse_source_geometry_data(Ref p_navigation_mesh, Ref p_source_geometry_data, Node *p_root_node, const Callable &p_callback) { ERR_FAIL_COND(!Thread::is_main_thread()); ERR_FAIL_COND(!p_navigation_mesh.is_valid()); ERR_FAIL_COND(p_root_node == nullptr); @@ -101,19 +159,25 @@ void NavMeshGenerator3D::parse_source_geometry_data(const Ref &p } } -void NavMeshGenerator3D::bake_from_source_geometry_data(Ref p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback) { +void NavMeshGenerator3D::bake_from_source_geometry_data(Ref p_navigation_mesh, Ref p_source_geometry_data, const Callable &p_callback) { ERR_FAIL_COND(!p_navigation_mesh.is_valid()); ERR_FAIL_COND(!p_source_geometry_data.is_valid()); - ERR_FAIL_COND(!p_source_geometry_data->has_data()); + + if (!p_source_geometry_data->has_data()) { + p_navigation_mesh->clear(); + if (p_callback.is_valid()) { + generator_emit_callback(p_callback); + } + return; + } baking_navmesh_mutex.lock(); if (baking_navmeshes.has(p_navigation_mesh)) { baking_navmesh_mutex.unlock(); ERR_FAIL_MSG("NavigationMesh is already baking. Wait for current bake to finish."); - } else { - baking_navmeshes.insert(p_navigation_mesh); - baking_navmesh_mutex.unlock(); } + baking_navmeshes.insert(p_navigation_mesh); + baking_navmesh_mutex.unlock(); generator_bake_from_source_geometry_data(p_navigation_mesh, p_source_geometry_data); @@ -126,6 +190,51 @@ void NavMeshGenerator3D::bake_from_source_geometry_data(Ref p_na } } +void NavMeshGenerator3D::bake_from_source_geometry_data_async(Ref p_navigation_mesh, Ref p_source_geometry_data, const Callable &p_callback) { + ERR_FAIL_COND(!p_navigation_mesh.is_valid()); + ERR_FAIL_COND(!p_source_geometry_data.is_valid()); + + if (!p_source_geometry_data->has_data()) { + p_navigation_mesh->clear(); + if (p_callback.is_valid()) { + generator_emit_callback(p_callback); + } + return; + } + + if (!use_threads) { + bake_from_source_geometry_data(p_navigation_mesh, p_source_geometry_data, p_callback); + return; + } + + baking_navmesh_mutex.lock(); + if (baking_navmeshes.has(p_navigation_mesh)) { + baking_navmesh_mutex.unlock(); + ERR_FAIL_MSG("NavigationMesh is already baking. Wait for current bake to finish."); + return; + } + baking_navmeshes.insert(p_navigation_mesh); + baking_navmesh_mutex.unlock(); + + generator_task_mutex.lock(); + NavMeshGeneratorTask3D *generator_task = memnew(NavMeshGeneratorTask3D); + generator_task->navigation_mesh = p_navigation_mesh; + generator_task->source_geometry_data = p_source_geometry_data; + generator_task->callback = p_callback; + generator_task->status = NavMeshGeneratorTask3D::TaskStatus::BAKING_STARTED; + generator_task->thread_task_id = WorkerThreadPool::get_singleton()->add_native_task(&NavMeshGenerator3D::generator_thread_bake, generator_task, NavMeshGenerator3D::baking_use_high_priority_threads, SNAME("NavMeshGeneratorBake3D")); + generator_tasks.insert(generator_task->thread_task_id, generator_task); + generator_task_mutex.unlock(); +} + +void NavMeshGenerator3D::generator_thread_bake(void *p_arg) { + NavMeshGeneratorTask3D *generator_task = static_cast(p_arg); + + generator_bake_from_source_geometry_data(generator_task->navigation_mesh, generator_task->source_geometry_data); + + generator_task->status = NavMeshGeneratorTask3D::TaskStatus::BAKING_FINISHED; +} + void NavMeshGenerator3D::generator_parse_geometry_node(const Ref &p_navigation_mesh, Ref p_source_geometry_data, Node *p_node, bool p_recurse_children) { generator_parse_meshinstance3d_node(p_navigation_mesh, p_source_geometry_data, p_node); generator_parse_multimeshinstance3d_node(p_navigation_mesh, p_source_geometry_data, p_node); @@ -503,8 +612,8 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Ref vertices = p_source_geometry_data->get_vertices(); - const Vector indices = p_source_geometry_data->get_indices(); + const Vector &vertices = p_source_geometry_data->get_vertices(); + const Vector &indices = p_source_geometry_data->get_indices(); if (vertices.size() < 3 || indices.size() < 3) { return; diff --git a/modules/navigation/nav_mesh_generator_3d.h b/modules/navigation/nav_mesh_generator_3d.h index dc844c2595c..4220927641a 100644 --- a/modules/navigation/nav_mesh_generator_3d.h +++ b/modules/navigation/nav_mesh_generator_3d.h @@ -34,6 +34,7 @@ #ifndef _3D_DISABLED #include "core/object/class_db.h" +#include "core/object/worker_thread_pool.h" #include "modules/modules_enabled.gen.h" // For csg, gridmap. class Node; @@ -44,6 +45,31 @@ class NavMeshGenerator3D : public Object { static NavMeshGenerator3D *singleton; static Mutex baking_navmesh_mutex; + static Mutex generator_task_mutex; + + static bool use_threads; + static bool baking_use_multiple_threads; + static bool baking_use_high_priority_threads; + + struct NavMeshGeneratorTask3D { + enum TaskStatus { + BAKING_STARTED, + BAKING_FINISHED, + BAKING_FAILED, + CALLBACK_DISPATCHED, + CALLBACK_FAILED, + }; + + Ref navigation_mesh; + Ref source_geometry_data; + Callable callback; + WorkerThreadPool::TaskID thread_task_id = WorkerThreadPool::INVALID_TASK_ID; + NavMeshGeneratorTask3D::TaskStatus status = NavMeshGeneratorTask3D::TaskStatus::BAKING_STARTED; + }; + + static HashMap generator_tasks; + + static void generator_thread_bake(void *p_arg); static HashSet> baking_navmeshes; @@ -66,11 +92,13 @@ class NavMeshGenerator3D : public Object { public: static NavMeshGenerator3D *get_singleton(); + static void sync(); static void cleanup(); static void finish(); - static void parse_source_geometry_data(const Ref &p_navigation_mesh, Ref p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()); - static void bake_from_source_geometry_data(Ref p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback = Callable()); + static void parse_source_geometry_data(Ref p_navigation_mesh, Ref p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()); + static void bake_from_source_geometry_data(Ref p_navigation_mesh, Ref p_source_geometry_data, const Callable &p_callback = Callable()); + static void bake_from_source_geometry_data_async(Ref p_navigation_mesh, Ref p_source_geometry_data, const Callable &p_callback = Callable()); NavMeshGenerator3D(); ~NavMeshGenerator3D(); diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp index 367a1d445f6..e03640f6cbf 100644 --- a/scene/3d/navigation_region_3d.cpp +++ b/scene/3d/navigation_region_3d.cpp @@ -236,62 +236,29 @@ RID NavigationRegion3D::get_navigation_map() const { return RID(); } -struct BakeThreadsArgs { - NavigationRegion3D *nav_region = nullptr; - Ref source_geometry_data; -}; - -void _bake_navigation_mesh(void *p_user_data) { - BakeThreadsArgs *args = static_cast(p_user_data); - - if (args->nav_region->get_navigation_mesh().is_valid()) { - Ref nav_mesh = args->nav_region->get_navigation_mesh(); - Ref source_geometry_data = args->source_geometry_data; - - NavigationServer3D::get_singleton()->bake_from_source_geometry_data(nav_mesh, source_geometry_data); - if (!Thread::is_main_thread()) { - args->nav_region->call_deferred(SNAME("_bake_finished"), nav_mesh); - } else { - args->nav_region->_bake_finished(nav_mesh); - } - memdelete(args); - } else { - ERR_PRINT("Can't bake the navigation mesh if the `NavigationMesh` resource doesn't exist"); - if (!Thread::is_main_thread()) { - args->nav_region->call_deferred(SNAME("_bake_finished"), Ref()); - } else { - args->nav_region->_bake_finished(Ref()); - } - memdelete(args); - } -} - void NavigationRegion3D::bake_navigation_mesh(bool p_on_thread) { ERR_FAIL_COND_MSG(!Thread::is_main_thread(), "The SceneTree can only be parsed on the main thread. Call this function from the main thread or use call_deferred()."); ERR_FAIL_COND_MSG(!navigation_mesh.is_valid(), "Baking the navigation mesh requires a valid `NavigationMesh` resource."); - ERR_FAIL_COND_MSG(bake_thread.is_started(), "Unable to start another bake request. The navigation mesh bake thread is already baking a navigation mesh."); Ref source_geometry_data; source_geometry_data.instantiate(); NavigationServer3D::get_singleton()->parse_source_geometry_data(navigation_mesh, source_geometry_data, this); - BakeThreadsArgs *args = memnew(BakeThreadsArgs); - args->nav_region = this; - args->source_geometry_data = source_geometry_data; - if (p_on_thread) { - bake_thread.start(_bake_navigation_mesh, args); + NavigationServer3D::get_singleton()->bake_from_source_geometry_data_async(navigation_mesh, source_geometry_data, callable_mp(this, &NavigationRegion3D::_bake_finished).bind(navigation_mesh)); } else { - _bake_navigation_mesh(args); + NavigationServer3D::get_singleton()->bake_from_source_geometry_data(navigation_mesh, source_geometry_data, callable_mp(this, &NavigationRegion3D::_bake_finished).bind(navigation_mesh)); } } -void NavigationRegion3D::_bake_finished(Ref p_nav_mesh) { - set_navigation_mesh(p_nav_mesh); - if (bake_thread.is_started()) { - bake_thread.wait_to_finish(); +void NavigationRegion3D::_bake_finished(Ref p_navigation_mesh) { + if (!Thread::is_main_thread()) { + call_deferred(SNAME("_bake_finished"), p_navigation_mesh); + return; } + + set_navigation_mesh(p_navigation_mesh); emit_signal(SNAME("bake_finished")); } @@ -452,10 +419,6 @@ NavigationRegion3D::NavigationRegion3D() { } NavigationRegion3D::~NavigationRegion3D() { - if (bake_thread.is_started()) { - bake_thread.wait_to_finish(); - } - if (navigation_mesh.is_valid()) { navigation_mesh->disconnect_changed(callable_mp(this, &NavigationRegion3D::_navigation_mesh_changed)); } diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h index e41d07f4cf6..02fe5524b2e 100644 --- a/scene/3d/navigation_region_3d.h +++ b/scene/3d/navigation_region_3d.h @@ -49,8 +49,6 @@ class NavigationRegion3D : public Node3D { Transform3D current_global_transform; - Thread bake_thread; - void _navigation_mesh_changed(); #ifdef DEBUG_ENABLED diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 04facdb8d95..75036b935b6 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -155,6 +155,7 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("parse_source_geometry_data", "navigation_mesh", "source_geometry_data", "root_node", "callback"), &NavigationServer3D::parse_source_geometry_data, DEFVAL(Callable())); ClassDB::bind_method(D_METHOD("bake_from_source_geometry_data", "navigation_mesh", "source_geometry_data", "callback"), &NavigationServer3D::bake_from_source_geometry_data, DEFVAL(Callable())); + ClassDB::bind_method(D_METHOD("bake_from_source_geometry_data_async", "navigation_mesh", "source_geometry_data", "callback"), &NavigationServer3D::bake_from_source_geometry_data_async, DEFVAL(Callable())); ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer3D::free); @@ -204,6 +205,9 @@ NavigationServer3D::NavigationServer3D() { GLOBAL_DEF("navigation/avoidance/thread_model/avoidance_use_multiple_threads", true); GLOBAL_DEF("navigation/avoidance/thread_model/avoidance_use_high_priority_threads", true); + GLOBAL_DEF("navigation/baking/thread_model/baking_use_multiple_threads", true); + GLOBAL_DEF("navigation/baking/thread_model/baking_use_high_priority_threads", true); + #ifdef DEBUG_ENABLED debug_navigation_edge_connection_color = GLOBAL_DEF("debug/shapes/navigation/edge_connection_color", Color(1.0, 0.0, 1.0, 1.0)); debug_navigation_geometry_edge_color = GLOBAL_DEF("debug/shapes/navigation/geometry_edge_color", Color(0.5, 1.0, 1.0, 1.0)); diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index 4bf25f7a331..39f147357ad 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -309,8 +309,9 @@ public: virtual NavigationUtilities::PathQueryResult _query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const = 0; - virtual void parse_source_geometry_data(const Ref &p_navigation_mesh, Ref p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()) = 0; - virtual void bake_from_source_geometry_data(Ref p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback = Callable()) = 0; + virtual void parse_source_geometry_data(const Ref &p_navigation_mesh, const Ref &p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()) = 0; + virtual void bake_from_source_geometry_data(const Ref &p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback = Callable()) = 0; + 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; NavigationServer3D(); ~NavigationServer3D() override; diff --git a/servers/navigation_server_3d_dummy.h b/servers/navigation_server_3d_dummy.h index a5c9fc57f29..b1ec214bb0b 100644 --- a/servers/navigation_server_3d_dummy.h +++ b/servers/navigation_server_3d_dummy.h @@ -145,8 +145,9 @@ public: void obstacle_set_position(RID p_obstacle, Vector3 p_position) override {} void obstacle_set_vertices(RID p_obstacle, const Vector &p_vertices) override {} void obstacle_set_avoidance_layers(RID p_obstacle, uint32_t p_layers) override {} - void parse_source_geometry_data(const Ref &p_navigation_mesh, Ref p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()) override {} - void bake_from_source_geometry_data(Ref p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback = Callable()) override {} + void parse_source_geometry_data(const Ref &p_navigation_mesh, const Ref &p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()) override {} + void bake_from_source_geometry_data(const Ref &p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback = Callable()) override {} + void bake_from_source_geometry_data_async(const Ref &p_navigation_mesh, const Ref &p_source_geometry_data, const Callable &p_callback = Callable()) override {} void free(RID p_object) override {} void set_active(bool p_active) override {} void process(real_t delta_time) override {}