diff options
author | Pawel Lampe <pawel.lampe@gmail.com> | 2024-01-29 22:28:01 +0100 |
---|---|---|
committer | Pawel Lampe <pawel.lampe@gmail.com> | 2024-02-05 22:04:22 +0100 |
commit | c2cfc0d409b5adf892c6daa86d128f6e98633bee (patch) | |
tree | a4bd096edc45131e5da177295ddabe802b7d64be | |
parent | 4b6ad349886288405890b07d4a8da425eb3c97ec (diff) | |
download | redot-engine-c2cfc0d409b5adf892c6daa86d128f6e98633bee.tar.gz |
Expose `is_baking` method in navigation servers and region nodes.
24 files changed, 137 insertions, 12 deletions
diff --git a/doc/classes/NavigationRegion2D.xml b/doc/classes/NavigationRegion2D.xml index 089359da7a..4ad552e97e 100644 --- a/doc/classes/NavigationRegion2D.xml +++ b/doc/classes/NavigationRegion2D.xml @@ -56,6 +56,12 @@ Returns the [RID] of this region on the [NavigationServer2D]. Combined with [method NavigationServer2D.map_get_closest_point_owner] can be used to identify the [NavigationRegion2D] closest to a point on the merged navigation map. </description> </method> + <method name="is_baking" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] when the [NavigationPolygon] is being baked on a background thread. + </description> + </method> <method name="set_avoidance_layer_value"> <return type="void" /> <param index="0" name="layer_number" type="int" /> diff --git a/doc/classes/NavigationRegion3D.xml b/doc/classes/NavigationRegion3D.xml index 4415c10210..2a84270d7d 100644 --- a/doc/classes/NavigationRegion3D.xml +++ b/doc/classes/NavigationRegion3D.xml @@ -49,6 +49,12 @@ Returns the [RID] of this region on the [NavigationServer3D]. Combined with [method NavigationServer3D.map_get_closest_point_owner] can be used to identify the [NavigationRegion3D] closest to a point on the merged navigation map. </description> </method> + <method name="is_baking" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] when the [NavigationMesh] is being baked on a background thread. + </description> + </method> <method name="set_navigation_layer_value"> <return type="void" /> <param index="0" name="layer_number" type="int" /> diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml index 2bb0090282..2fe60a1118 100644 --- a/doc/classes/NavigationServer2D.xml +++ b/doc/classes/NavigationServer2D.xml @@ -303,6 +303,13 @@ Returns all created navigation map [RID]s on the NavigationServer. This returns both 2D and 3D created navigation maps as there is technically no distinction between them. </description> </method> + <method name="is_baking_navigation_polygon" qualifiers="const"> + <return type="bool" /> + <param index="0" name="navigation_polygon" type="NavigationPolygon" /> + <description> + Returns [code]true[/code] when the provided navigation polygon is being baked on a background thread. + </description> + </method> <method name="link_create"> <return type="RID" /> <description> diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml index bff5d63a17..0d1744162d 100644 --- a/doc/classes/NavigationServer3D.xml +++ b/doc/classes/NavigationServer3D.xml @@ -342,6 +342,13 @@ Returns information about the current state of the NavigationServer. See [enum ProcessInfo] for a list of available states. </description> </method> + <method name="is_baking_navigation_mesh" qualifiers="const"> + <return type="bool" /> + <param index="0" name="navigation_mesh" type="NavigationMesh" /> + <description> + Returns [code]true[/code] when the provided navigation mesh is being baked on a background thread. + </description> + </method> <method name="link_create"> <return type="RID" /> <description> diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp index 5a27f315b9..f6d94f280b 100644 --- a/modules/navigation/godot_navigation_server.cpp +++ b/modules/navigation/godot_navigation_server.cpp @@ -1116,6 +1116,10 @@ void GodotNavigationServer::bake_from_source_geometry_data_async(const Ref<Navig #endif // _3D_DISABLED } +bool GodotNavigationServer::is_baking_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh) const { + return NavMeshGenerator3D::get_singleton()->is_baking(p_navigation_mesh); +} + COMMAND_1(free, RID, p_object) { if (map_owner.owns(p_object)) { NavMap *map = map_owner.get_or_null(p_object); diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h index f19450db27..6798978d21 100644 --- a/modules/navigation/godot_navigation_server.h +++ b/modules/navigation/godot_navigation_server.h @@ -258,6 +258,7 @@ public: virtual void parse_source_geometry_data(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()) override; virtual void bake_from_source_geometry_data(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, const Callable &p_callback = Callable()) override; virtual void bake_from_source_geometry_data_async(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, const Callable &p_callback = Callable()) override; + virtual bool is_baking_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh) const override; COMMAND_1(free, RID, p_object); diff --git a/modules/navigation/godot_navigation_server_2d.cpp b/modules/navigation/godot_navigation_server_2d.cpp index 76bfd3a101..5bd4a37fd7 100644 --- a/modules/navigation/godot_navigation_server_2d.cpp +++ b/modules/navigation/godot_navigation_server_2d.cpp @@ -221,6 +221,10 @@ void GodotNavigationServer2D::bake_from_source_geometry_data_async(const Ref<Nav #endif // CLIPPER2_ENABLED } +bool GodotNavigationServer2D::is_baking_navigation_polygon(Ref<NavigationPolygon> p_navigation_polygon) const { + return NavMeshGenerator2D::get_singleton()->is_baking(p_navigation_polygon); +} + GodotNavigationServer2D::GodotNavigationServer2D() {} GodotNavigationServer2D::~GodotNavigationServer2D() {} diff --git a/modules/navigation/godot_navigation_server_2d.h b/modules/navigation/godot_navigation_server_2d.h index 2f473da1ab..08f1730441 100644 --- a/modules/navigation/godot_navigation_server_2d.h +++ b/modules/navigation/godot_navigation_server_2d.h @@ -250,6 +250,7 @@ public: virtual void parse_source_geometry_data(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()) override; virtual void bake_from_source_geometry_data(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, const Callable &p_callback = Callable()) override; virtual void bake_from_source_geometry_data_async(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, const Callable &p_callback = Callable()) override; + virtual bool is_baking_navigation_polygon(Ref<NavigationPolygon> p_navigation_polygon) const override; }; #endif // GODOT_NAVIGATION_SERVER_2D_H diff --git a/modules/navigation/nav_mesh_generator_2d.cpp b/modules/navigation/nav_mesh_generator_2d.cpp index 6dfafa4e91..697b434974 100644 --- a/modules/navigation/nav_mesh_generator_2d.cpp +++ b/modules/navigation/nav_mesh_generator_2d.cpp @@ -157,11 +157,10 @@ void NavMeshGenerator2D::bake_from_source_geometry_data(Ref<NavigationPolygon> p return; } - baking_navmesh_mutex.lock(); - if (baking_navmeshes.has(p_navigation_mesh)) { - baking_navmesh_mutex.unlock(); + if (is_baking(p_navigation_mesh)) { ERR_FAIL_MSG("NavigationPolygon is already baking. Wait for current bake to finish."); } + baking_navmesh_mutex.lock(); baking_navmeshes.insert(p_navigation_mesh); baking_navmesh_mutex.unlock(); @@ -193,11 +192,10 @@ void NavMeshGenerator2D::bake_from_source_geometry_data_async(Ref<NavigationPoly return; } - baking_navmesh_mutex.lock(); - if (baking_navmeshes.has(p_navigation_mesh)) { - baking_navmesh_mutex.unlock(); + if (is_baking(p_navigation_mesh)) { ERR_FAIL_MSG("NavigationPolygon is already baking. Wait for current bake to finish."); } + baking_navmesh_mutex.lock(); baking_navmeshes.insert(p_navigation_mesh); baking_navmesh_mutex.unlock(); @@ -212,6 +210,13 @@ void NavMeshGenerator2D::bake_from_source_geometry_data_async(Ref<NavigationPoly generator_task_mutex.unlock(); } +bool NavMeshGenerator2D::is_baking(Ref<NavigationPolygon> p_navigation_polygon) { + baking_navmesh_mutex.lock(); + bool baking = baking_navmeshes.has(p_navigation_polygon); + baking_navmesh_mutex.unlock(); + return baking; +} + void NavMeshGenerator2D::generator_thread_bake(void *p_arg) { NavMeshGeneratorTask2D *generator_task = static_cast<NavMeshGeneratorTask2D *>(p_arg); diff --git a/modules/navigation/nav_mesh_generator_2d.h b/modules/navigation/nav_mesh_generator_2d.h index 763ad24636..4ec582bd51 100644 --- a/modules/navigation/nav_mesh_generator_2d.h +++ b/modules/navigation/nav_mesh_generator_2d.h @@ -92,6 +92,7 @@ public: static void parse_source_geometry_data(Ref<NavigationPolygon> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()); static void bake_from_source_geometry_data(Ref<NavigationPolygon> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, const Callable &p_callback = Callable()); static void bake_from_source_geometry_data_async(Ref<NavigationPolygon> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData2D> p_source_geometry_data, const Callable &p_callback = Callable()); + static bool is_baking(Ref<NavigationPolygon> p_navigation_polygon); NavMeshGenerator2D(); ~NavMeshGenerator2D(); diff --git a/modules/navigation/nav_mesh_generator_3d.cpp b/modules/navigation/nav_mesh_generator_3d.cpp index 8719801c72..f20b4d25e3 100644 --- a/modules/navigation/nav_mesh_generator_3d.cpp +++ b/modules/navigation/nav_mesh_generator_3d.cpp @@ -172,11 +172,10 @@ void NavMeshGenerator3D::bake_from_source_geometry_data(Ref<NavigationMesh> p_na return; } - baking_navmesh_mutex.lock(); - if (baking_navmeshes.has(p_navigation_mesh)) { - baking_navmesh_mutex.unlock(); + if (is_baking(p_navigation_mesh)) { ERR_FAIL_MSG("NavigationMesh is already baking. Wait for current bake to finish."); } + baking_navmesh_mutex.lock(); baking_navmeshes.insert(p_navigation_mesh); baking_navmesh_mutex.unlock(); @@ -208,12 +207,11 @@ void NavMeshGenerator3D::bake_from_source_geometry_data_async(Ref<NavigationMesh return; } - baking_navmesh_mutex.lock(); - if (baking_navmeshes.has(p_navigation_mesh)) { - baking_navmesh_mutex.unlock(); + if (is_baking(p_navigation_mesh)) { ERR_FAIL_MSG("NavigationMesh is already baking. Wait for current bake to finish."); return; } + baking_navmesh_mutex.lock(); baking_navmeshes.insert(p_navigation_mesh); baking_navmesh_mutex.unlock(); @@ -228,6 +226,13 @@ void NavMeshGenerator3D::bake_from_source_geometry_data_async(Ref<NavigationMesh generator_task_mutex.unlock(); } +bool NavMeshGenerator3D::is_baking(Ref<NavigationMesh> p_navigation_mesh) { + baking_navmesh_mutex.lock(); + bool baking = baking_navmeshes.has(p_navigation_mesh); + baking_navmesh_mutex.unlock(); + return baking; +} + void NavMeshGenerator3D::generator_thread_bake(void *p_arg) { NavMeshGeneratorTask3D *generator_task = static_cast<NavMeshGeneratorTask3D *>(p_arg); diff --git a/modules/navigation/nav_mesh_generator_3d.h b/modules/navigation/nav_mesh_generator_3d.h index 4220927641..0251b02235 100644 --- a/modules/navigation/nav_mesh_generator_3d.h +++ b/modules/navigation/nav_mesh_generator_3d.h @@ -99,6 +99,7 @@ public: static void parse_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()); static void bake_from_source_geometry_data(Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, const Callable &p_callback = Callable()); static void bake_from_source_geometry_data_async(Ref<NavigationMesh> p_navigation_mesh, Ref<NavigationMeshSourceGeometryData3D> p_source_geometry_data, const Callable &p_callback = Callable()); + static bool is_baking(Ref<NavigationMesh> p_navigation_mesh); NavMeshGenerator3D(); ~NavMeshGenerator3D(); diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index 00c0912690..9a689c0f21 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -253,6 +253,10 @@ void NavigationRegion2D::_bake_finished(Ref<NavigationPolygon> p_navigation_poly emit_signal(SNAME("bake_finished")); } +bool NavigationRegion2D::is_baking() const { + return NavigationServer2D::get_singleton()->is_baking_navigation_polygon(navigation_polygon); +} + void NavigationRegion2D::_navigation_polygon_changed() { if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint())) { queue_redraw(); @@ -320,6 +324,7 @@ void NavigationRegion2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationRegion2D::get_travel_cost); ClassDB::bind_method(D_METHOD("bake_navigation_polygon", "on_thread"), &NavigationRegion2D::bake_navigation_polygon, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("is_baking"), &NavigationRegion2D::is_baking); ClassDB::bind_method(D_METHOD("_navigation_polygon_changed"), &NavigationRegion2D::_navigation_polygon_changed); diff --git a/scene/2d/navigation_region_2d.h b/scene/2d/navigation_region_2d.h index 3b880dd00d..0719f786fd 100644 --- a/scene/2d/navigation_region_2d.h +++ b/scene/2d/navigation_region_2d.h @@ -117,6 +117,7 @@ public: void bake_navigation_polygon(bool p_on_thread); void _bake_finished(Ref<NavigationPolygon> p_navigation_polygon); + bool is_baking() const; NavigationRegion2D(); ~NavigationRegion2D(); diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp index fa5c8f820d..753bc0434b 100644 --- a/scene/3d/navigation_region_3d.cpp +++ b/scene/3d/navigation_region_3d.cpp @@ -266,6 +266,10 @@ void NavigationRegion3D::_bake_finished(Ref<NavigationMesh> p_navigation_mesh) { emit_signal(SNAME("bake_finished")); } +bool NavigationRegion3D::is_baking() const { + return NavigationServer3D::get_singleton()->is_baking_navigation_mesh(navigation_mesh); +} + PackedStringArray NavigationRegion3D::get_configuration_warnings() const { PackedStringArray warnings = Node::get_configuration_warnings(); @@ -308,6 +312,7 @@ void NavigationRegion3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_travel_cost"), &NavigationRegion3D::get_travel_cost); ClassDB::bind_method(D_METHOD("bake_navigation_mesh", "on_thread"), &NavigationRegion3D::bake_navigation_mesh, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("is_baking"), &NavigationRegion3D::is_baking); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navigation_mesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "enabled"), "set_enabled", "is_enabled"); diff --git a/scene/3d/navigation_region_3d.h b/scene/3d/navigation_region_3d.h index fe9ee178ff..ea0a0cd391 100644 --- a/scene/3d/navigation_region_3d.h +++ b/scene/3d/navigation_region_3d.h @@ -105,6 +105,7 @@ public: /// sets the new navigation mesh and emits a signal void bake_navigation_mesh(bool p_on_thread); void _bake_finished(Ref<NavigationMesh> p_navigation_mesh); + bool is_baking() const; PackedStringArray get_configuration_warnings() const override; diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index 81f389e19b..32c77195f8 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -162,6 +162,7 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("parse_source_geometry_data", "navigation_polygon", "source_geometry_data", "root_node", "callback"), &NavigationServer2D::parse_source_geometry_data, DEFVAL(Callable())); ClassDB::bind_method(D_METHOD("bake_from_source_geometry_data", "navigation_polygon", "source_geometry_data", "callback"), &NavigationServer2D::bake_from_source_geometry_data, DEFVAL(Callable())); 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("free_rid", "rid"), &NavigationServer2D::free); diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h index be3818fe9d..c7d97c004b 100644 --- a/servers/navigation_server_2d.h +++ b/servers/navigation_server_2d.h @@ -303,6 +303,7 @@ public: virtual void parse_source_geometry_data(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()) = 0; virtual void bake_from_source_geometry_data(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, const Callable &p_callback = Callable()) = 0; virtual void bake_from_source_geometry_data_async(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, const Callable &p_callback = Callable()) = 0; + virtual bool is_baking_navigation_polygon(Ref<NavigationPolygon> p_navigation_polygon) const = 0; NavigationServer2D(); ~NavigationServer2D() override; diff --git a/servers/navigation_server_2d_dummy.h b/servers/navigation_server_2d_dummy.h index 5b33a4f170..3ec6d11352 100644 --- a/servers/navigation_server_2d_dummy.h +++ b/servers/navigation_server_2d_dummy.h @@ -167,6 +167,7 @@ public: void parse_source_geometry_data(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()) override {} void bake_from_source_geometry_data(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, const Callable &p_callback = Callable()) override {} void bake_from_source_geometry_data_async(const Ref<NavigationPolygon> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData2D> &p_source_geometry_data, const Callable &p_callback = Callable()) override {} + bool is_baking_navigation_polygon(Ref<NavigationPolygon> p_navigation_polygon) const override { return false; } void set_debug_enabled(bool p_enabled) {} bool get_debug_enabled() const { return false; } diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 412b12e145..9ea1e8f59d 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -179,6 +179,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("is_baking_navigation_mesh", "navigation_mesh"), &NavigationServer3D::is_baking_navigation_mesh); 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 dc58502b1e..02985ec6c1 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -343,6 +343,7 @@ public: virtual void parse_source_geometry_data(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()) = 0; virtual void bake_from_source_geometry_data(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, const Callable &p_callback = Callable()) = 0; virtual void bake_from_source_geometry_data_async(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, const Callable &p_callback = Callable()) = 0; + virtual bool is_baking_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh) const = 0; NavigationServer3D(); ~NavigationServer3D() override; diff --git a/servers/navigation_server_3d_dummy.h b/servers/navigation_server_3d_dummy.h index dd0dfc7348..c93953eb27 100644 --- a/servers/navigation_server_3d_dummy.h +++ b/servers/navigation_server_3d_dummy.h @@ -170,6 +170,8 @@ public: void parse_source_geometry_data(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, Node *p_root_node, const Callable &p_callback = Callable()) override {} void bake_from_source_geometry_data(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, const Callable &p_callback = Callable()) override {} void bake_from_source_geometry_data_async(const Ref<NavigationMesh> &p_navigation_mesh, const Ref<NavigationMeshSourceGeometryData3D> &p_source_geometry_data, const Callable &p_callback = Callable()) override {} + bool is_baking_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh) const override { return false; } + void free(RID p_object) override {} void set_active(bool p_active) override {} void process(real_t delta_time) override {} diff --git a/tests/scene/test_navigation_region_3d.h b/tests/scene/test_navigation_region_3d.h index 4c5ae34615..f7cf7c7912 100644 --- a/tests/scene/test_navigation_region_3d.h +++ b/tests/scene/test_navigation_region_3d.h @@ -31,8 +31,10 @@ #ifndef TEST_NAVIGATION_REGION_3D_H #define TEST_NAVIGATION_REGION_3D_H +#include "scene/3d/mesh_instance_3d.h" #include "scene/3d/navigation_region_3d.h" #include "scene/main/window.h" +#include "scene/resources/primitive_meshes.h" #include "tests/test_macros.h" @@ -44,6 +46,44 @@ TEST_SUITE("[Navigation]") { CHECK(region_node->get_region_rid().is_valid()); memdelete(region_node); } + + TEST_CASE("[SceneTree][NavigationRegion3D] Region should bake successfully from valid geometry") { + Node3D *node_3d = memnew(Node3D); + SceneTree::get_singleton()->get_root()->add_child(node_3d); + Ref<NavigationMesh> navigation_mesh = memnew(NavigationMesh); + NavigationRegion3D *navigation_region = memnew(NavigationRegion3D); + navigation_region->set_navigation_mesh(navigation_mesh); + node_3d->add_child(navigation_region); + Ref<PlaneMesh> plane_mesh = memnew(PlaneMesh); + plane_mesh->set_size(Size2(10.0, 10.0)); + MeshInstance3D *mesh_instance = memnew(MeshInstance3D); + mesh_instance->set_mesh(plane_mesh); + navigation_region->add_child(mesh_instance); + + CHECK_FALSE(navigation_region->is_baking()); + CHECK_EQ(navigation_mesh->get_polygon_count(), 0); + CHECK_EQ(navigation_mesh->get_vertices().size(), 0); + + SUBCASE("Synchronous bake should have immediate effects") { + navigation_region->bake_navigation_mesh(false); + CHECK_FALSE(navigation_region->is_baking()); + CHECK_NE(navigation_mesh->get_polygon_count(), 0); + CHECK_NE(navigation_mesh->get_vertices().size(), 0); + } + + // Race condition is present in the below subcase, but baking should take many + // orders of magnitude longer than basic checks on the main thread, so it's fine. + SUBCASE("Asynchronous bake should not be immediate") { + navigation_region->bake_navigation_mesh(true); + CHECK(navigation_region->is_baking()); + CHECK_EQ(navigation_mesh->get_polygon_count(), 0); + CHECK_EQ(navigation_mesh->get_vertices().size(), 0); + } + + memdelete(mesh_instance); + memdelete(navigation_region); + memdelete(node_3d); + } } } //namespace TestNavigationRegion3D diff --git a/tests/servers/test_navigation_server_3d.h b/tests/servers/test_navigation_server_3d.h index 5ab2975b74..5b5c1faac8 100644 --- a/tests/servers/test_navigation_server_3d.h +++ b/tests/servers/test_navigation_server_3d.h @@ -720,6 +720,24 @@ TEST_SUITE("[Navigation]") { navigation_server->free(map); navigation_server->process(0.0); // Give server some cycles to commit. } + + TEST_CASE("[NavigationServer3D] Server should be able to bake asynchronously") { + NavigationServer3D *navigation_server = NavigationServer3D::get_singleton(); + Ref<NavigationMesh> navigation_mesh = memnew(NavigationMesh); + Ref<NavigationMeshSourceGeometryData3D> source_geometry = memnew(NavigationMeshSourceGeometryData3D); + + Array arr; + arr.resize(RS::ARRAY_MAX); + BoxMesh::create_mesh_array(arr, Vector3(10.0, 0.001, 10.0)); + source_geometry->add_mesh_array(arr, Transform3D()); + + // Race condition is present below, but baking should take many orders of magnitude + // longer than basic checks on the main thread, so it's fine. + navigation_server->bake_from_source_geometry_data_async(navigation_mesh, source_geometry, Callable()); + CHECK(navigation_server->is_baking_navigation_mesh(navigation_mesh)); + CHECK_EQ(navigation_mesh->get_polygon_count(), 0); + CHECK_EQ(navigation_mesh->get_vertices().size(), 0); + } } } //namespace TestNavigationServer3D |