diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml index 39f0718a718..dccdd02d0af 100644 --- a/doc/classes/NavigationServer2D.xml +++ b/doc/classes/NavigationServer2D.xml @@ -504,6 +504,14 @@ Returns the edge connection margin of the map. The edge connection margin is a distance used to connect two regions. + + + + + Returns the current iteration id of the navigation map. Every time the navigation map changes and synchronizes the iteration id increases. An iteration id of 0 means the navigation map has never synchronized. + [b]Note:[/b] The iteration id will wrap back to 1 after reaching its range limit. + + diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml index e88792cadee..4fc75461e78 100644 --- a/doc/classes/NavigationServer3D.xml +++ b/doc/classes/NavigationServer3D.xml @@ -568,6 +568,14 @@ Returns the edge connection margin of the map. This distance is the minimum vertex distance needed to connect two edges from different regions. + + + + + Returns the current iteration id of the navigation map. Every time the navigation map changes and synchronizes the iteration id increases. An iteration id of 0 means the navigation map has never synchronized. + [b]Note:[/b] The iteration id will wrap back to 1 after reaching its range limit. + + diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp index 14c72f3db40..4bb9c27b1d7 100644 --- a/modules/navigation/godot_navigation_server.cpp +++ b/modules/navigation/godot_navigation_server.cpp @@ -121,13 +121,13 @@ COMMAND_2(map_set_active, RID, p_map, bool, p_active) { if (p_active) { if (!map_is_active(p_map)) { active_maps.push_back(map); - active_maps_update_id.push_back(map->get_map_update_id()); + active_maps_iteration_id.push_back(map->get_iteration_id()); } } else { int map_index = active_maps.find(map); ERR_FAIL_COND(map_index < 0); active_maps.remove_at(map_index); - active_maps_update_id.remove_at(map_index); + active_maps_iteration_id.remove_at(map_index); } } @@ -1165,7 +1165,7 @@ COMMAND_1(free, RID, p_object) { int map_index = active_maps.find(map); if (map_index >= 0) { active_maps.remove_at(map_index); - active_maps_update_id.remove_at(map_index); + active_maps_iteration_id.remove_at(map_index); } map_owner.free(p_object); @@ -1258,6 +1258,13 @@ void GodotNavigationServer::map_force_update(RID p_map) { map->sync(); } +uint32_t GodotNavigationServer::map_get_iteration_id(RID p_map) const { + NavMap *map = map_owner.get_or_null(p_map); + ERR_FAIL_NULL_V(map, 0); + + return map->get_iteration_id(); +} + void GodotNavigationServer::sync() { #ifndef _3D_DISABLED if (navmesh_generator_3d) { @@ -1300,10 +1307,10 @@ void GodotNavigationServer::process(real_t p_delta_time) { _new_pm_edge_free_count += active_maps[i]->get_pm_edge_free_count(); // Emit a signal if a map changed. - const uint32_t new_map_update_id = active_maps[i]->get_map_update_id(); - if (new_map_update_id != active_maps_update_id[i]) { + const uint32_t new_map_iteration_id = active_maps[i]->get_iteration_id(); + if (new_map_iteration_id != active_maps_iteration_id[i]) { emit_signal(SNAME("map_changed"), active_maps[i]->get_self()); - active_maps_update_id[i] = new_map_update_id; + active_maps_iteration_id[i] = new_map_iteration_id; } } diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h index f3bc1185d82..8af0eb18747 100644 --- a/modules/navigation/godot_navigation_server.h +++ b/modules/navigation/godot_navigation_server.h @@ -80,7 +80,7 @@ class GodotNavigationServer : public NavigationServer3D { bool active = true; LocalVector active_maps; - LocalVector active_maps_update_id; + LocalVector active_maps_iteration_id; #ifndef _3D_DISABLED NavMeshGenerator3D *navmesh_generator_3d = nullptr; @@ -142,6 +142,7 @@ public: virtual TypedArray map_get_obstacles(RID p_map) const override; virtual void map_force_update(RID p_map) override; + virtual uint32_t map_get_iteration_id(RID p_map) const override; virtual Vector3 map_get_random_point(RID p_map, uint32_t p_navigation_layers, bool p_uniformly) const override; diff --git a/modules/navigation/godot_navigation_server_2d.cpp b/modules/navigation/godot_navigation_server_2d.cpp index 5bd4a37fd71..4b8640249d2 100644 --- a/modules/navigation/godot_navigation_server_2d.cpp +++ b/modules/navigation/godot_navigation_server_2d.cpp @@ -253,6 +253,10 @@ void GodotNavigationServer2D::map_force_update(RID p_map) { NavigationServer3D::get_singleton()->map_force_update(p_map); } +uint32_t GodotNavigationServer2D::map_get_iteration_id(RID p_map) const { + return NavigationServer3D::get_singleton()->map_get_iteration_id(p_map); +} + void FORWARD_2(map_set_cell_size, RID, p_map, real_t, p_cell_size, rid_to_rid, real_to_real); real_t FORWARD_1_C(map_get_cell_size, RID, p_map, rid_to_rid); diff --git a/modules/navigation/godot_navigation_server_2d.h b/modules/navigation/godot_navigation_server_2d.h index 08f1730441a..225fd8f3a63 100644 --- a/modules/navigation/godot_navigation_server_2d.h +++ b/modules/navigation/godot_navigation_server_2d.h @@ -77,6 +77,7 @@ public: virtual TypedArray map_get_obstacles(RID p_map) const override; virtual void map_force_update(RID p_map) override; virtual Vector2 map_get_random_point(RID p_map, uint32_t p_navigation_layers, bool p_uniformly) const override; + virtual uint32_t map_get_iteration_id(RID p_map) const override; virtual RID region_create() override; virtual void region_set_enabled(RID p_region, bool p_enabled) override; diff --git a/modules/navigation/nav_agent.cpp b/modules/navigation/nav_agent.cpp index 5a87ff6c4bf..2dbe57eb4aa 100644 --- a/modules/navigation/nav_agent.cpp +++ b/modules/navigation/nav_agent.cpp @@ -111,8 +111,8 @@ void NavAgent::set_map(NavMap *p_map) { bool NavAgent::is_map_changed() { if (map) { - bool is_changed = map->get_map_update_id() != map_update_id; - map_update_id = map->get_map_update_id(); + bool is_changed = map->get_iteration_id() != last_map_iteration_id; + last_map_iteration_id = map->get_iteration_id(); return is_changed; } else { return false; diff --git a/modules/navigation/nav_agent.h b/modules/navigation/nav_agent.h index 9ab6f555448..00b5bc13ab4 100644 --- a/modules/navigation/nav_agent.h +++ b/modules/navigation/nav_agent.h @@ -72,7 +72,7 @@ class NavAgent : public NavRid { bool agent_dirty = true; - uint32_t map_update_id = 0; + uint32_t last_map_iteration_id = 0; bool paused = false; public: diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp index 9482da39ef0..f163f4e5294 100644 --- a/modules/navigation/nav_map.cpp +++ b/modules/navigation/nav_map.cpp @@ -128,7 +128,7 @@ gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const { Vector NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers, Vector *r_path_types, TypedArray *r_path_rids, Vector *r_path_owners) const { RWLockRead read_lock(map_rwlock); - if (map_update_id == 0) { + if (iteration_id == 0) { ERR_FAIL_V_MSG(Vector(), "NavigationServer map query failed because it was made before first map synchronization."); } @@ -592,7 +592,7 @@ Vector NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p Vector3 NavMap::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const { RWLockRead read_lock(map_rwlock); - if (map_update_id == 0) { + if (iteration_id == 0) { ERR_FAIL_V_MSG(Vector3(), "NavigationServer map query failed because it was made before first map synchronization."); } @@ -644,7 +644,7 @@ Vector3 NavMap::get_closest_point_to_segment(const Vector3 &p_from, const Vector Vector3 NavMap::get_closest_point(const Vector3 &p_point) const { RWLockRead read_lock(map_rwlock); - if (map_update_id == 0) { + if (iteration_id == 0) { ERR_FAIL_V_MSG(Vector3(), "NavigationServer map query failed because it was made before first map synchronization."); } gd::ClosestPointQueryResult cp = get_closest_point_info(p_point); @@ -653,7 +653,7 @@ Vector3 NavMap::get_closest_point(const Vector3 &p_point) const { Vector3 NavMap::get_closest_point_normal(const Vector3 &p_point) const { RWLockRead read_lock(map_rwlock); - if (map_update_id == 0) { + if (iteration_id == 0) { ERR_FAIL_V_MSG(Vector3(), "NavigationServer map query failed because it was made before first map synchronization."); } gd::ClosestPointQueryResult cp = get_closest_point_info(p_point); @@ -662,7 +662,7 @@ Vector3 NavMap::get_closest_point_normal(const Vector3 &p_point) const { RID NavMap::get_closest_point_owner(const Vector3 &p_point) const { RWLockRead read_lock(map_rwlock); - if (map_update_id == 0) { + if (iteration_id == 0) { ERR_FAIL_V_MSG(RID(), "NavigationServer map query failed because it was made before first map synchronization."); } gd::ClosestPointQueryResult cp = get_closest_point_info(p_point); @@ -1160,9 +1160,8 @@ void NavMap::sync() { } } - // Update the update ID. - // Some code treats 0 as a failure case, so we avoid returning 0. - map_update_id = map_update_id % 9999999 + 1; + // Some code treats 0 as a failure case, so we avoid returning 0 and modulo wrap UINT32_MAX manually. + iteration_id = iteration_id % UINT32_MAX + 1; } // Do we have modified obstacle positions? diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h index 311a265e0c9..d6215ea57f1 100644 --- a/modules/navigation/nav_map.h +++ b/modules/navigation/nav_map.h @@ -108,7 +108,7 @@ class NavMap : public NavRid { real_t deltatime = 0.0; /// Change the id each time the map is updated. - uint32_t map_update_id = 0; + uint32_t iteration_id = 0; bool use_threads = true; bool avoidance_use_multiple_threads = true; @@ -128,6 +128,8 @@ public: NavMap(); ~NavMap(); + uint32_t get_iteration_id() const { return iteration_id; } + void set_up(Vector3 p_up); Vector3 get_up() const { return up; @@ -199,10 +201,6 @@ public: return obstacles; } - uint32_t get_map_update_id() const { - return map_update_id; - } - Vector3 get_random_point(uint32_t p_navigation_layers, bool p_uniformly) const; void sync(); diff --git a/modules/navigation/nav_obstacle.cpp b/modules/navigation/nav_obstacle.cpp index 34e5f7aa851..14dfd4eae34 100644 --- a/modules/navigation/nav_obstacle.cpp +++ b/modules/navigation/nav_obstacle.cpp @@ -149,8 +149,8 @@ void NavObstacle::set_vertices(const Vector &p_vertices) { bool NavObstacle::is_map_changed() { if (map) { - bool is_changed = map->get_map_update_id() != map_update_id; - map_update_id = map->get_map_update_id(); + bool is_changed = map->get_iteration_id() != last_map_iteration_id; + last_map_iteration_id = map->get_iteration_id(); return is_changed; } else { return false; diff --git a/modules/navigation/nav_obstacle.h b/modules/navigation/nav_obstacle.h index eb44f63d03d..e231e83836c 100644 --- a/modules/navigation/nav_obstacle.h +++ b/modules/navigation/nav_obstacle.h @@ -55,7 +55,7 @@ class NavObstacle : public NavRid { bool obstacle_dirty = true; - uint32_t map_update_id = 0; + uint32_t last_map_iteration_id = 0; bool paused = false; public: diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index 32c77195f88..d87ac00e327 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -58,6 +58,7 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_get_obstacles", "map"), &NavigationServer2D::map_get_obstacles); ClassDB::bind_method(D_METHOD("map_force_update", "map"), &NavigationServer2D::map_force_update); + ClassDB::bind_method(D_METHOD("map_get_iteration_id", "map"), &NavigationServer2D::map_get_iteration_id); ClassDB::bind_method(D_METHOD("map_get_random_point", "map", "navigation_layers", "uniformly"), &NavigationServer2D::map_get_random_point); diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h index c7d97c004b4..d7dc9d6526c 100644 --- a/servers/navigation_server_2d.h +++ b/servers/navigation_server_2d.h @@ -102,6 +102,7 @@ public: virtual TypedArray map_get_obstacles(RID p_map) const = 0; virtual void map_force_update(RID p_map) = 0; + virtual uint32_t map_get_iteration_id(RID p_map) const = 0; virtual Vector2 map_get_random_point(RID p_map, uint32_t p_navigation_layers, bool p_uniformly) const = 0; diff --git a/servers/navigation_server_2d_dummy.h b/servers/navigation_server_2d_dummy.h index 3ec6d113525..94c6dfd6a79 100644 --- a/servers/navigation_server_2d_dummy.h +++ b/servers/navigation_server_2d_dummy.h @@ -59,6 +59,7 @@ public: TypedArray map_get_obstacles(RID p_map) const override { return TypedArray(); } void map_force_update(RID p_map) override {} Vector2 map_get_random_point(RID p_map, uint32_t p_naviation_layers, bool p_uniformly) const override { return Vector2(); }; + uint32_t map_get_iteration_id(RID p_map) const override { return 0; } RID region_create() override { return RID(); } void region_set_enabled(RID p_region, bool p_enabled) override {} diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index 7fc027284bc..00db1440f65 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -65,6 +65,7 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_get_obstacles", "map"), &NavigationServer3D::map_get_obstacles); ClassDB::bind_method(D_METHOD("map_force_update", "map"), &NavigationServer3D::map_force_update); + ClassDB::bind_method(D_METHOD("map_get_iteration_id", "map"), &NavigationServer3D::map_get_iteration_id); ClassDB::bind_method(D_METHOD("map_get_random_point", "map", "navigation_layers", "uniformly"), &NavigationServer3D::map_get_random_point); diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index 552e3185868..975ffdee945 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -116,6 +116,7 @@ public: virtual TypedArray map_get_obstacles(RID p_map) const = 0; virtual void map_force_update(RID p_map) = 0; + virtual uint32_t map_get_iteration_id(RID p_map) const = 0; virtual Vector3 map_get_random_point(RID p_map, uint32_t p_navigation_layers, bool p_uniformly) const = 0; diff --git a/servers/navigation_server_3d_dummy.h b/servers/navigation_server_3d_dummy.h index d595fcde7eb..9ba9b20d004 100644 --- a/servers/navigation_server_3d_dummy.h +++ b/servers/navigation_server_3d_dummy.h @@ -66,6 +66,8 @@ public: TypedArray map_get_agents(RID p_map) const override { return TypedArray(); } TypedArray map_get_obstacles(RID p_map) const override { return TypedArray(); } void map_force_update(RID p_map) override {} + uint32_t map_get_iteration_id(RID p_map) const override { return 0; } + 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; } @@ -92,6 +94,7 @@ public: Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const override { return Vector3(); } Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const override { return Vector3(); } Vector3 region_get_random_point(RID p_region, uint32_t p_navigation_layers, bool p_uniformly) const override { return Vector3(); } + 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(); } @@ -111,6 +114,7 @@ public: real_t link_get_travel_cost(RID p_link) const override { return 0; } void link_set_owner_id(RID p_link, ObjectID p_owner_id) override {} ObjectID link_get_owner_id(RID p_link) const override { return ObjectID(); } + RID agent_create() override { return RID(); } void agent_set_map(RID p_agent, RID p_map) override {} RID agent_get_map(RID p_agent) const override { return RID(); } @@ -148,6 +152,7 @@ public: uint32_t agent_get_avoidance_mask(RID p_agent) const override { return 0; } void agent_set_avoidance_priority(RID p_agent, real_t p_priority) override {} real_t agent_get_avoidance_priority(RID p_agent) const override { return 0; } + RID obstacle_create() override { return RID(); } void obstacle_set_map(RID p_obstacle, RID p_map) override {} RID obstacle_get_map(RID p_obstacle) const override { return RID(); } @@ -169,6 +174,7 @@ public: Vector obstacle_get_vertices(RID p_obstacle) const override { return Vector(); } void obstacle_set_avoidance_layers(RID p_obstacle, uint32_t p_layers) override {} uint32_t obstacle_get_avoidance_layers(RID p_obstacle) const override { return 0; } + 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 {} @@ -180,8 +186,10 @@ public: void init() override {} void sync() override {} void finish() override {} + NavigationUtilities::PathQueryResult _query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const override { return NavigationUtilities::PathQueryResult(); } int get_process_info(ProcessInfo p_info) const override { return 0; } + void set_debug_enabled(bool p_enabled) {} bool get_debug_enabled() const { return false; } };