Merge pull request #84275 from smix8/navmap_iteration_id

Add function to get navigation map iteration id from NavigationServer
This commit is contained in:
Rémi Verschelde 2024-02-22 11:22:52 +01:00
commit 0e704ff682
No known key found for this signature in database
GPG key ID: C3336907360768E1
18 changed files with 65 additions and 26 deletions

View file

@ -504,6 +504,14 @@
Returns the edge connection margin of the map. The edge connection margin is a distance used to connect two regions.
</description>
</method>
<method name="map_get_iteration_id" qualifiers="const">
<return type="int" />
<param index="0" name="map" type="RID" />
<description>
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.
</description>
</method>
<method name="map_get_link_connection_radius" qualifiers="const">
<return type="float" />
<param index="0" name="map" type="RID" />

View file

@ -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.
</description>
</method>
<method name="map_get_iteration_id" qualifiers="const">
<return type="int" />
<param index="0" name="map" type="RID" />
<description>
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.
</description>
</method>
<method name="map_get_link_connection_radius" qualifiers="const">
<return type="float" />
<param index="0" name="map" type="RID" />

View file

@ -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;
}
}

View file

@ -80,7 +80,7 @@ class GodotNavigationServer : public NavigationServer3D {
bool active = true;
LocalVector<NavMap *> active_maps;
LocalVector<uint32_t> active_maps_update_id;
LocalVector<uint32_t> active_maps_iteration_id;
#ifndef _3D_DISABLED
NavMeshGenerator3D *navmesh_generator_3d = nullptr;
@ -142,6 +142,7 @@ public:
virtual TypedArray<RID> 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;

View file

@ -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);

View file

@ -77,6 +77,7 @@ public:
virtual TypedArray<RID> 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;

View file

@ -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;

View file

@ -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:

View file

@ -128,7 +128,7 @@ gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const {
Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers, Vector<int32_t> *r_path_types, TypedArray<RID> *r_path_rids, Vector<int64_t> *r_path_owners) const {
RWLockRead read_lock(map_rwlock);
if (map_update_id == 0) {
if (iteration_id == 0) {
ERR_FAIL_V_MSG(Vector<Vector3>(), "NavigationServer map query failed because it was made before first map synchronization.");
}
@ -592,7 +592,7 @@ Vector<Vector3> 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?

View file

@ -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();

View file

@ -149,8 +149,8 @@ void NavObstacle::set_vertices(const Vector<Vector3> &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;

View file

@ -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:

View file

@ -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);

View file

@ -102,6 +102,7 @@ public:
virtual TypedArray<RID> 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;

View file

@ -59,6 +59,7 @@ public:
TypedArray<RID> map_get_obstacles(RID p_map) const override { return TypedArray<RID>(); }
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 {}

View file

@ -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);

View file

@ -116,6 +116,7 @@ public:
virtual TypedArray<RID> 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;

View file

@ -66,6 +66,8 @@ public:
TypedArray<RID> map_get_agents(RID p_map) const override { return TypedArray<RID>(); }
TypedArray<RID> map_get_obstacles(RID p_map) const override { return TypedArray<RID>(); }
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<Vector3> obstacle_get_vertices(RID p_obstacle) const override { return Vector<Vector3>(); }
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<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 {}
@ -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; }
};