[Navigation] Create a dedicated 2D navigation server

* Add a dedicated 2D server
* Create dedicated tests
* Split performance metrics between 2D and 3D
* Rename the 3D only server module
This commit is contained in:
A Thousand Ships
2025-02-26 11:48:13 +01:00
parent 7598b08ec2
commit 5cc0539961
90 changed files with 8083 additions and 910 deletions

View File

@@ -31,8 +31,10 @@
#include "navigation_server_2d.h"
#include "navigation_server_2d.compat.inc"
#include "core/config/project_settings.h"
#include "scene/main/node.h"
#include "servers/navigation/navigation_globals.h"
#include "servers/navigation_server_2d_dummy.h"
#include "servers/navigation_server_3d.h"
NavigationServer2D *NavigationServer2D::singleton = nullptr;
@@ -182,12 +184,28 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer2D::free);
ClassDB::bind_method(D_METHOD("set_active", "active"), &NavigationServer2D::set_active);
ClassDB::bind_method(D_METHOD("set_debug_enabled", "enabled"), &NavigationServer2D::set_debug_enabled);
ClassDB::bind_method(D_METHOD("get_debug_enabled"), &NavigationServer2D::get_debug_enabled);
ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
ADD_SIGNAL(MethodInfo("navigation_debug_changed"));
ADD_SIGNAL(MethodInfo("avoidance_debug_changed"));
ClassDB::bind_method(D_METHOD("get_process_info", "process_info"), &NavigationServer2D::get_process_info);
BIND_ENUM_CONSTANT(INFO_ACTIVE_MAPS);
BIND_ENUM_CONSTANT(INFO_REGION_COUNT);
BIND_ENUM_CONSTANT(INFO_AGENT_COUNT);
BIND_ENUM_CONSTANT(INFO_LINK_COUNT);
BIND_ENUM_CONSTANT(INFO_POLYGON_COUNT);
BIND_ENUM_CONSTANT(INFO_EDGE_COUNT);
BIND_ENUM_CONSTANT(INFO_EDGE_MERGE_COUNT);
BIND_ENUM_CONSTANT(INFO_EDGE_CONNECTION_COUNT);
BIND_ENUM_CONSTANT(INFO_EDGE_FREE_COUNT);
BIND_ENUM_CONSTANT(INFO_OBSTACLE_COUNT);
}
NavigationServer2D *NavigationServer2D::get_singleton() {
@@ -197,19 +215,49 @@ NavigationServer2D *NavigationServer2D::get_singleton() {
NavigationServer2D::NavigationServer2D() {
ERR_FAIL_COND(singleton != nullptr);
singleton = this;
ERR_FAIL_NULL_MSG(NavigationServer3D::get_singleton(), "The Navigation3D singleton should be initialized before the 2D one.");
NavigationServer3D::get_singleton()->connect("map_changed", callable_mp(this, &NavigationServer2D::_emit_map_changed));
GLOBAL_DEF_BASIC(PropertyInfo(Variant::FLOAT, "navigation/2d/default_cell_size", PROPERTY_HINT_RANGE, NavigationDefaults2D::navmesh_cell_size_hint), NavigationDefaults2D::navmesh_cell_size);
GLOBAL_DEF("navigation/2d/use_edge_connections", true);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::FLOAT, "navigation/2d/default_edge_connection_margin", PROPERTY_HINT_RANGE, "0.01,10,0.001,or_greater"), NavigationDefaults2D::edge_connection_margin);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::FLOAT, "navigation/2d/default_link_connection_radius", PROPERTY_HINT_RANGE, "0.01,10,0.001,or_greater"), NavigationDefaults2D::link_connection_radius);
#ifdef DEBUG_ENABLED
NavigationServer3D::get_singleton()->connect(SNAME("navigation_debug_changed"), callable_mp(this, &NavigationServer2D::_emit_navigation_debug_changed_signal));
#endif // DEBUG_ENABLED
}
debug_navigation_edge_connection_color = GLOBAL_DEF("debug/shapes/navigation/2d/edge_connection_color", Color(1.0, 0.0, 1.0, 1.0));
debug_navigation_geometry_edge_color = GLOBAL_DEF("debug/shapes/navigation/2d/geometry_edge_color", Color(0.5, 1.0, 1.0, 1.0));
debug_navigation_geometry_face_color = GLOBAL_DEF("debug/shapes/navigation/2d/geometry_face_color", Color(0.5, 1.0, 1.0, 0.4));
debug_navigation_geometry_edge_disabled_color = GLOBAL_DEF("debug/shapes/navigation/2d/geometry_edge_disabled_color", Color(0.5, 0.5, 0.5, 1.0));
debug_navigation_geometry_face_disabled_color = GLOBAL_DEF("debug/shapes/navigation/2d/geometry_face_disabled_color", Color(0.5, 0.5, 0.5, 0.4));
debug_navigation_link_connection_color = GLOBAL_DEF("debug/shapes/navigation/2d/link_connection_color", Color(1.0, 0.5, 1.0, 1.0));
debug_navigation_link_connection_disabled_color = GLOBAL_DEF("debug/shapes/navigation/2d/link_connection_disabled_color", Color(0.5, 0.5, 0.5, 1.0));
debug_navigation_agent_path_color = GLOBAL_DEF("debug/shapes/navigation/2d/agent_path_color", Color(1.0, 0.0, 0.0, 1.0));
#ifdef DEBUG_ENABLED
void NavigationServer2D::_emit_navigation_debug_changed_signal() {
emit_signal(SNAME("navigation_debug_changed"));
}
debug_navigation_enable_edge_connections = GLOBAL_DEF("debug/shapes/navigation/2d/enable_edge_connections", true);
debug_navigation_enable_edge_lines = GLOBAL_DEF("debug/shapes/navigation/2d/enable_edge_lines", true);
debug_navigation_enable_geometry_face_random_color = GLOBAL_DEF("debug/shapes/navigation/2d/enable_geometry_face_random_color", true);
debug_navigation_enable_link_connections = GLOBAL_DEF("debug/shapes/navigation/2d/enable_link_connections", true);
debug_navigation_enable_agent_paths = GLOBAL_DEF("debug/shapes/navigation/2d/enable_agent_paths", true);
debug_navigation_agent_path_point_size = GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "debug/shapes/navigation/2d/agent_path_point_size", PROPERTY_HINT_RANGE, "0.01,10,0.001,or_greater"), 4.0);
debug_navigation_avoidance_agents_radius_color = GLOBAL_DEF("debug/shapes/avoidance/2d/agents_radius_color", Color(1.0, 1.0, 0.0, 0.25));
debug_navigation_avoidance_obstacles_radius_color = GLOBAL_DEF("debug/shapes/avoidance/2d/obstacles_radius_color", Color(1.0, 0.5, 0.0, 0.25));
debug_navigation_avoidance_static_obstacle_pushin_face_color = GLOBAL_DEF("debug/shapes/avoidance/2d/obstacles_static_face_pushin_color", Color(1.0, 0.0, 0.0, 0.0));
debug_navigation_avoidance_static_obstacle_pushin_edge_color = GLOBAL_DEF("debug/shapes/avoidance/2d/obstacles_static_edge_pushin_color", Color(1.0, 0.0, 0.0, 1.0));
debug_navigation_avoidance_static_obstacle_pushout_face_color = GLOBAL_DEF("debug/shapes/avoidance/2d/obstacles_static_face_pushout_color", Color(1.0, 1.0, 0.0, 0.5));
debug_navigation_avoidance_static_obstacle_pushout_edge_color = GLOBAL_DEF("debug/shapes/avoidance/2d/obstacles_static_edge_pushout_color", Color(1.0, 1.0, 0.0, 1.0));
debug_navigation_avoidance_enable_agents_radius = GLOBAL_DEF("debug/shapes/avoidance/2d/enable_agents_radius", true);
debug_navigation_avoidance_enable_obstacles_radius = GLOBAL_DEF("debug/shapes/avoidance/2d/enable_obstacles_radius", true);
debug_navigation_avoidance_enable_obstacles_static = GLOBAL_DEF("debug/shapes/avoidance/2d/enable_obstacles_static", true);
if (Engine::get_singleton()->is_editor_hint()) {
// enable NavigationServer3D when in Editor or else navigation mesh edge connections are invisible
// on runtime tests SceneTree has "Visible Navigation" set and main iteration takes care of this.
set_debug_enabled(true);
set_debug_navigation_enabled(true);
set_debug_avoidance_enabled(true);
}
#endif // DEBUG_ENABLED
}
NavigationServer2D::~NavigationServer2D() {
singleton = nullptr;
@@ -256,209 +304,239 @@ void NavigationServer2D::source_geometry_parser_set_callback(RID p_parser, const
parser->callback = p_callback;
}
void NavigationServer2D::_emit_map_changed(RID p_map) {
emit_signal(SNAME("map_changed"), p_map);
}
void NavigationServer2D::set_debug_enabled(bool p_enabled) {
NavigationServer3D::get_singleton()->set_debug_enabled(p_enabled);
#ifdef DEBUG_ENABLED
if (debug_enabled != p_enabled) {
debug_dirty = true;
}
debug_enabled = p_enabled;
if (debug_dirty) {
navigation_debug_dirty = true;
callable_mp(this, &NavigationServer2D::_emit_navigation_debug_changed_signal).call_deferred();
avoidance_debug_dirty = true;
callable_mp(this, &NavigationServer2D::_emit_avoidance_debug_changed_signal).call_deferred();
}
#endif // DEBUG_ENABLED
}
bool NavigationServer2D::get_debug_enabled() const {
return NavigationServer3D::get_singleton()->get_debug_enabled();
return debug_enabled;
}
#ifdef DEBUG_ENABLED
void NavigationServer2D::_emit_navigation_debug_changed_signal() {
if (navigation_debug_dirty) {
navigation_debug_dirty = false;
emit_signal(SNAME("navigation_debug_changed"));
}
}
void NavigationServer2D::_emit_avoidance_debug_changed_signal() {
if (avoidance_debug_dirty) {
avoidance_debug_dirty = false;
emit_signal(SNAME("avoidance_debug_changed"));
}
}
#endif // DEBUG_ENABLED
#ifdef DEBUG_ENABLED
void NavigationServer2D::set_debug_navigation_enabled(bool p_enabled) {
NavigationServer3D::get_singleton()->set_debug_navigation_enabled(p_enabled);
debug_navigation_enabled = p_enabled;
navigation_debug_dirty = true;
callable_mp(this, &NavigationServer2D::_emit_navigation_debug_changed_signal).call_deferred();
}
bool NavigationServer2D::get_debug_navigation_enabled() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_enabled();
return debug_navigation_enabled;
}
void NavigationServer2D::set_debug_avoidance_enabled(bool p_enabled) {
NavigationServer3D::get_singleton()->set_debug_avoidance_enabled(p_enabled);
debug_avoidance_enabled = p_enabled;
avoidance_debug_dirty = true;
callable_mp(this, &NavigationServer2D::_emit_avoidance_debug_changed_signal).call_deferred();
}
bool NavigationServer2D::get_debug_avoidance_enabled() const {
return NavigationServer3D::get_singleton()->get_debug_avoidance_enabled();
return debug_avoidance_enabled;
}
void NavigationServer2D::set_debug_navigation_edge_connection_color(const Color &p_color) {
NavigationServer3D::get_singleton()->set_debug_navigation_edge_connection_color(p_color);
debug_navigation_edge_connection_color = p_color;
}
Color NavigationServer2D::get_debug_navigation_edge_connection_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_edge_connection_color();
return debug_navigation_edge_connection_color;
}
void NavigationServer2D::set_debug_navigation_geometry_face_color(const Color &p_color) {
NavigationServer3D::get_singleton()->set_debug_navigation_geometry_face_color(p_color);
debug_navigation_geometry_face_color = p_color;
}
Color NavigationServer2D::get_debug_navigation_geometry_face_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_color();
return debug_navigation_geometry_face_color;
}
void NavigationServer2D::set_debug_navigation_geometry_face_disabled_color(const Color &p_color) {
NavigationServer3D::get_singleton()->set_debug_navigation_geometry_face_disabled_color(p_color);
debug_navigation_geometry_face_disabled_color = p_color;
}
Color NavigationServer2D::get_debug_navigation_geometry_face_disabled_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_disabled_color();
return debug_navigation_geometry_face_disabled_color;
}
void NavigationServer2D::set_debug_navigation_link_connection_color(const Color &p_color) {
NavigationServer3D::get_singleton()->set_debug_navigation_link_connection_color(p_color);
debug_navigation_link_connection_color = p_color;
}
Color NavigationServer2D::get_debug_navigation_link_connection_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_link_connection_color();
return debug_navigation_link_connection_color;
}
void NavigationServer2D::set_debug_navigation_link_connection_disabled_color(const Color &p_color) {
NavigationServer3D::get_singleton()->set_debug_navigation_link_connection_disabled_color(p_color);
debug_navigation_link_connection_disabled_color = p_color;
}
Color NavigationServer2D::get_debug_navigation_link_connection_disabled_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_link_connection_disabled_color();
return debug_navigation_link_connection_disabled_color;
}
void NavigationServer2D::set_debug_navigation_geometry_edge_color(const Color &p_color) {
NavigationServer3D::get_singleton()->set_debug_navigation_geometry_edge_color(p_color);
debug_navigation_geometry_edge_color = p_color;
}
Color NavigationServer2D::get_debug_navigation_geometry_edge_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_geometry_edge_color();
return debug_navigation_geometry_edge_color;
}
void NavigationServer2D::set_debug_navigation_geometry_edge_disabled_color(const Color &p_color) {
NavigationServer3D::get_singleton()->set_debug_navigation_geometry_edge_disabled_color(p_color);
debug_navigation_geometry_edge_disabled_color = p_color;
}
Color NavigationServer2D::get_debug_navigation_geometry_edge_disabled_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_geometry_edge_disabled_color();
return debug_navigation_geometry_edge_disabled_color;
}
void NavigationServer2D::set_debug_navigation_enable_edge_connections(const bool p_value) {
NavigationServer3D::get_singleton()->set_debug_navigation_enable_edge_connections(p_value);
debug_navigation_enable_edge_connections = p_value;
}
bool NavigationServer2D::get_debug_navigation_enable_edge_connections() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_connections();
return debug_navigation_enable_edge_connections;
}
void NavigationServer2D::set_debug_navigation_enable_geometry_face_random_color(const bool p_value) {
NavigationServer3D::get_singleton()->set_debug_navigation_enable_geometry_face_random_color(p_value);
debug_navigation_enable_geometry_face_random_color = p_value;
}
bool NavigationServer2D::get_debug_navigation_enable_geometry_face_random_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_enable_geometry_face_random_color();
return debug_navigation_enable_geometry_face_random_color;
}
void NavigationServer2D::set_debug_navigation_enable_edge_lines(const bool p_value) {
NavigationServer3D::get_singleton()->set_debug_navigation_enable_edge_lines(p_value);
debug_navigation_enable_edge_lines = p_value;
}
bool NavigationServer2D::get_debug_navigation_enable_edge_lines() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_lines();
return debug_navigation_enable_edge_lines;
}
void NavigationServer2D::set_debug_navigation_agent_path_color(const Color &p_color) {
NavigationServer3D::get_singleton()->set_debug_navigation_agent_path_color(p_color);
debug_navigation_agent_path_color = p_color;
}
Color NavigationServer2D::get_debug_navigation_agent_path_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_agent_path_color();
return debug_navigation_agent_path_color;
}
void NavigationServer2D::set_debug_navigation_enable_agent_paths(const bool p_value) {
NavigationServer3D::get_singleton()->set_debug_navigation_enable_agent_paths(p_value);
debug_navigation_enable_agent_paths = p_value;
}
bool NavigationServer2D::get_debug_navigation_enable_agent_paths() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_enable_agent_paths();
return debug_navigation_enable_agent_paths;
}
void NavigationServer2D::set_debug_navigation_agent_path_point_size(real_t p_point_size) {
NavigationServer3D::get_singleton()->set_debug_navigation_agent_path_point_size(p_point_size);
debug_navigation_agent_path_point_size = p_point_size;
}
real_t NavigationServer2D::get_debug_navigation_agent_path_point_size() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_agent_path_point_size();
return debug_navigation_agent_path_point_size;
}
void NavigationServer2D::set_debug_navigation_avoidance_enable_agents_radius(const bool p_value) {
NavigationServer3D::get_singleton()->set_debug_navigation_avoidance_enable_agents_radius(p_value);
debug_navigation_avoidance_enable_agents_radius = p_value;
}
bool NavigationServer2D::get_debug_navigation_avoidance_enable_agents_radius() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_enable_agents_radius();
return debug_navigation_avoidance_enable_agents_radius;
}
void NavigationServer2D::set_debug_navigation_avoidance_enable_obstacles_radius(const bool p_value) {
NavigationServer3D::get_singleton()->set_debug_navigation_avoidance_enable_obstacles_radius(p_value);
debug_navigation_avoidance_enable_obstacles_radius = p_value;
}
bool NavigationServer2D::get_debug_navigation_avoidance_enable_obstacles_radius() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_enable_obstacles_radius();
return debug_navigation_avoidance_enable_obstacles_radius;
}
void NavigationServer2D::set_debug_navigation_avoidance_agents_radius_color(const Color &p_color) {
NavigationServer3D::get_singleton()->set_debug_navigation_avoidance_agents_radius_color(p_color);
debug_navigation_avoidance_agents_radius_color = p_color;
}
Color NavigationServer2D::get_debug_navigation_avoidance_agents_radius_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_agents_radius_color();
return debug_navigation_avoidance_agents_radius_color;
}
void NavigationServer2D::set_debug_navigation_avoidance_obstacles_radius_color(const Color &p_color) {
NavigationServer3D::get_singleton()->set_debug_navigation_avoidance_obstacles_radius_color(p_color);
debug_navigation_avoidance_obstacles_radius_color = p_color;
}
Color NavigationServer2D::get_debug_navigation_avoidance_obstacles_radius_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_obstacles_radius_color();
return debug_navigation_avoidance_obstacles_radius_color;
}
void NavigationServer2D::set_debug_navigation_avoidance_static_obstacle_pushin_face_color(const Color &p_color) {
NavigationServer3D::get_singleton()->set_debug_navigation_avoidance_static_obstacle_pushin_face_color(p_color);
debug_navigation_avoidance_static_obstacle_pushin_face_color = p_color;
}
Color NavigationServer2D::get_debug_navigation_avoidance_static_obstacle_pushin_face_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_static_obstacle_pushin_face_color();
return debug_navigation_avoidance_static_obstacle_pushin_face_color;
}
void NavigationServer2D::set_debug_navigation_avoidance_static_obstacle_pushout_face_color(const Color &p_color) {
NavigationServer3D::get_singleton()->set_debug_navigation_avoidance_static_obstacle_pushout_face_color(p_color);
debug_navigation_avoidance_static_obstacle_pushout_face_color = p_color;
}
Color NavigationServer2D::get_debug_navigation_avoidance_static_obstacle_pushout_face_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_static_obstacle_pushout_face_color();
return debug_navigation_avoidance_static_obstacle_pushout_face_color;
}
void NavigationServer2D::set_debug_navigation_avoidance_static_obstacle_pushin_edge_color(const Color &p_color) {
NavigationServer3D::get_singleton()->set_debug_navigation_avoidance_static_obstacle_pushin_edge_color(p_color);
debug_navigation_avoidance_static_obstacle_pushin_edge_color = p_color;
}
Color NavigationServer2D::get_debug_navigation_avoidance_static_obstacle_pushin_edge_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_static_obstacle_pushin_edge_color();
return debug_navigation_avoidance_static_obstacle_pushin_edge_color;
}
void NavigationServer2D::set_debug_navigation_avoidance_static_obstacle_pushout_edge_color(const Color &p_color) {
NavigationServer3D::get_singleton()->set_debug_navigation_avoidance_static_obstacle_pushout_edge_color(p_color);
debug_navigation_avoidance_static_obstacle_pushout_edge_color = p_color;
}
Color NavigationServer2D::get_debug_navigation_avoidance_static_obstacle_pushout_edge_color() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_static_obstacle_pushout_edge_color();
return debug_navigation_avoidance_static_obstacle_pushout_edge_color;
}
void NavigationServer2D::set_debug_navigation_avoidance_enable_obstacles_static(const bool p_value) {
NavigationServer3D::get_singleton()->set_debug_navigation_avoidance_enable_obstacles_static(p_value);
debug_navigation_avoidance_enable_obstacles_static = p_value;
}
bool NavigationServer2D::get_debug_navigation_avoidance_enable_obstacles_static() const {
return NavigationServer3D::get_singleton()->get_debug_navigation_avoidance_enable_obstacles_static();
return debug_navigation_avoidance_enable_obstacles_static;
}
#endif // DEBUG_ENABLED
@@ -481,8 +559,6 @@ NavigationServer2D *NavigationServer2DManager::new_default_server() {
}
void NavigationServer2DManager::initialize_server() {
// NavigationServer3D must be initialized before NavigationServer2D.
ERR_FAIL_NULL(NavigationServer3D::get_singleton());
ERR_FAIL_COND(navigation_server_2d != nullptr);
// Init 2D Navigation Server