1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-04 12:00:25 +00:00

Make NavigationServer backend engine selectable

Adds engine backend selection for NavigationServers, aka allows to swap navigation module for other backend implementations.
This commit is contained in:
smix8
2025-04-30 00:27:39 +02:00
parent 07f4c06601
commit 419fc6e22d
13 changed files with 439 additions and 54 deletions

View File

@@ -1033,25 +1033,16 @@ bool NavigationServer3D::get_debug_avoidance_enabled() const {
static NavigationServer3D *navigation_server_3d = nullptr;
NavigationServer3DCallback NavigationServer3DManager::create_callback = nullptr;
void NavigationServer3DManager::set_default_server(NavigationServer3DCallback p_callback) {
create_callback = p_callback;
}
NavigationServer3D *NavigationServer3DManager::new_default_server() {
if (create_callback == nullptr) {
return nullptr;
}
return create_callback();
}
void NavigationServer3DManager::initialize_server() {
ERR_FAIL_COND(navigation_server_3d != nullptr);
// Init 3D Navigation Server
navigation_server_3d = NavigationServer3DManager::new_default_server();
// Init 3D Navigation Server.
navigation_server_3d = NavigationServer3DManager::get_singleton()->new_server(
GLOBAL_GET(NavigationServer3DManager::setting_property_name));
if (!navigation_server_3d) {
// Navigation server not found, use the default.
navigation_server_3d = NavigationServer3DManager::get_singleton()->new_default_server();
}
// Fall back to dummy if no default server has been registered.
if (!navigation_server_3d) {
@@ -1070,3 +1061,101 @@ void NavigationServer3DManager::finalize_server() {
memdelete(navigation_server_3d);
navigation_server_3d = nullptr;
}
const String NavigationServer3DManager::setting_property_name(PNAME("navigation/3d/navigation_engine"));
void NavigationServer3DManager::on_servers_changed() {
String navigation_servers_enum_str("DEFAULT");
for (int i = get_servers_count() - 1; 0 <= i; --i) {
navigation_servers_enum_str += "," + get_server_name(i);
}
ProjectSettings::get_singleton()->set_custom_property_info(PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, navigation_servers_enum_str));
ProjectSettings::get_singleton()->set_restart_if_changed(setting_property_name, true);
ProjectSettings::get_singleton()->set_as_basic(setting_property_name, true);
}
void NavigationServer3DManager::_bind_methods() {
ClassDB::bind_method(D_METHOD("register_server", "name", "create_callback"), &NavigationServer3DManager::register_server);
ClassDB::bind_method(D_METHOD("set_default_server", "name", "priority"), &NavigationServer3DManager::set_default_server);
}
NavigationServer3DManager *NavigationServer3DManager::get_singleton() {
return singleton;
}
void NavigationServer3DManager::register_server(const String &p_name, const Callable &p_create_callback) {
ERR_FAIL_COND(find_server_id(p_name) != -1);
navigation_servers.push_back(ClassInfo(p_name, p_create_callback));
on_servers_changed();
}
void NavigationServer3DManager::set_default_server(const String &p_name, int p_priority) {
const int id = find_server_id(p_name);
ERR_FAIL_COND(id == -1); // Not found
if (default_server_priority < p_priority) {
default_server_id = id;
default_server_priority = p_priority;
}
}
int NavigationServer3DManager::find_server_id(const String &p_name) {
for (int i = navigation_servers.size() - 1; 0 <= i; --i) {
if (p_name == navigation_servers[i].name) {
return i;
}
}
return -1;
}
int NavigationServer3DManager::get_servers_count() {
return navigation_servers.size();
}
String NavigationServer3DManager::get_server_name(int p_id) {
ERR_FAIL_INDEX_V(p_id, get_servers_count(), "");
return navigation_servers[p_id].name;
}
NavigationServer3D *NavigationServer3DManager::new_default_server() {
if (default_server_id == -1) {
return nullptr;
}
Variant ret;
Callable::CallError ce;
navigation_servers[default_server_id].create_callback.callp(nullptr, 0, ret, ce);
ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr);
return Object::cast_to<NavigationServer3D>(ret.get_validated_object());
}
NavigationServer3D *NavigationServer3DManager::new_server(const String &p_name) {
int id = find_server_id(p_name);
if (id == -1) {
return nullptr;
} else {
Variant ret;
Callable::CallError ce;
navigation_servers[id].create_callback.callp(nullptr, 0, ret, ce);
ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr);
return Object::cast_to<NavigationServer3D>(ret.get_validated_object());
}
}
NavigationServer3D *NavigationServer3DManager::create_dummy_server_callback() {
return memnew(NavigationServer3DDummy);
}
NavigationServer3DManager::NavigationServer3DManager() {
}
NavigationServer3DManager::~NavigationServer3DManager() {
}
void NavigationServer3DManager::initialize_server_manager() {
ERR_FAIL_COND(singleton != nullptr);
singleton = memnew(NavigationServer3DManager);
}
void NavigationServer3DManager::finalize_server_manager() {
ERR_FAIL_NULL(singleton);
memdelete(singleton);
}