diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index 95e3fded36b..16f6de52380 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -41,12 +41,10 @@
-
-
-
+
- Sets the callback [param object_id] and [param method] that gets called after each avoidance processing step for the [param agent]. The calculated [code]safe_velocity[/code] will be dispatched with a signal to the object just before the physics calculations.
- [b]Note:[/b] Created callbacks are always processed independently of the SceneTree state as long as the agent is on a navigation map and not freed. To disable the dispatch of a callback from an agent use [method agent_set_callback] again with a [code]0[/code] ObjectID as the [param object_id].
+ Sets the callback that gets called after each avoidance processing step for the [param agent]. The calculated [code]safe_velocity[/code] will be passed as the first parameter just before the physics calculations.
+ [b]Note:[/b] Created callbacks are always processed independently of the SceneTree state as long as the agent is on a navigation map and not freed. To disable the dispatch of a callback from an agent use [method agent_set_callback] again with an empty [Callable].
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index fd20f780b30..340821d41e8 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -41,12 +41,10 @@
-
-
-
+
- Sets the callback [param object_id] and [param method] that gets called after each avoidance processing step for the [param agent]. The calculated [code]safe_velocity[/code] will be dispatched with a signal to the object just before the physics calculations.
- [b]Note:[/b] Created callbacks are always processed independently of the SceneTree state as long as the agent is on a navigation map and not freed. To disable the dispatch of a callback from an agent use [method agent_set_callback] again with a [code]0[/code] ObjectID as the [param object_id].
+ Sets the callback that gets called after each avoidance processing step for the [param agent]. The calculated [code]safe_velocity[/code] will be passed as the first parameter just before the physics calculations.
+ [b]Note:[/b] Created callbacks are always processed independently of the SceneTree state as long as the agent is on a navigation map and not freed. To disable the dispatch of a callback from an agent use [method agent_set_callback] again with an empty [Callable].
diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index 5baf6db2e88..d546c5d3bac 100644
--- a/modules/navigation/godot_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -81,36 +81,6 @@ using namespace NavigationUtilities;
} \
void GodotNavigationServer::MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1)
-#define COMMAND_4(F_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3) \
- struct MERGE(F_NAME, _command) : public SetCommand { \
- T_0 d_0; \
- T_1 d_1; \
- T_2 d_2; \
- T_3 d_3; \
- MERGE(F_NAME, _command) \
- ( \
- T_0 p_d_0, \
- T_1 p_d_1, \
- T_2 p_d_2, \
- T_3 p_d_3) : \
- d_0(p_d_0), \
- d_1(p_d_1), \
- d_2(p_d_2), \
- d_3(p_d_3) {} \
- virtual void exec(GodotNavigationServer *server) override { \
- server->MERGE(_cmd_, F_NAME)(d_0, d_1, d_2, d_3); \
- } \
- }; \
- void GodotNavigationServer::F_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) { \
- auto cmd = memnew(MERGE(F_NAME, _command)( \
- D_0, \
- D_1, \
- D_2, \
- D_3)); \
- add_command(cmd); \
- } \
- void GodotNavigationServer::MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3)
-
GodotNavigationServer::GodotNavigationServer() {}
GodotNavigationServer::~GodotNavigationServer() {
@@ -711,17 +681,17 @@ bool GodotNavigationServer::agent_is_map_changed(RID p_agent) const {
return agent->is_map_changed();
}
-COMMAND_4(agent_set_callback, RID, p_agent, ObjectID, p_object_id, StringName, p_method, Variant, p_udata) {
+COMMAND_2(agent_set_callback, RID, p_agent, Callable, p_callback) {
RvoAgent *agent = agent_owner.get_or_null(p_agent);
ERR_FAIL_COND(agent == nullptr);
- agent->set_callback(p_object_id, p_method, p_udata);
+ agent->set_callback(p_callback);
if (agent->get_map()) {
- if (p_object_id == ObjectID()) {
- agent->get_map()->remove_agent_as_controlled(agent);
- } else {
+ if (p_callback.is_valid()) {
agent->get_map()->set_agent_as_controlled(agent);
+ } else {
+ agent->get_map()->remove_agent_as_controlled(agent);
}
}
}
@@ -946,4 +916,3 @@ int GodotNavigationServer::get_process_info(ProcessInfo p_info) const {
#undef COMMAND_1
#undef COMMAND_2
-#undef COMMAND_4
diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h
index efefa60de8d..eea5713c402 100644
--- a/modules/navigation/godot_navigation_server.h
+++ b/modules/navigation/godot_navigation_server.h
@@ -54,10 +54,6 @@
virtual void F_NAME(T_0 D_0, T_1 D_1) override; \
void MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1)
-#define COMMAND_4_DEF(F_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, D_3_DEF) \
- virtual void F_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3 = D_3_DEF) override; \
- void MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3)
-
class GodotNavigationServer;
struct SetCommand {
@@ -182,7 +178,7 @@ public:
COMMAND_2(agent_set_position, RID, p_agent, Vector3, p_position);
COMMAND_2(agent_set_ignore_y, RID, p_agent, bool, p_ignore);
virtual bool agent_is_map_changed(RID p_agent) const override;
- COMMAND_4_DEF(agent_set_callback, RID, p_agent, ObjectID, p_object_id, StringName, p_method, Variant, p_udata, Variant());
+ COMMAND_2(agent_set_callback, RID, p_agent, Callable, p_callback);
COMMAND_1(free, RID, p_object);
@@ -198,6 +194,5 @@ public:
#undef COMMAND_1
#undef COMMAND_2
-#undef COMMAND_4_DEF
#endif // GODOT_NAVIGATION_SERVER_H
diff --git a/modules/navigation/rvo_agent.cpp b/modules/navigation/rvo_agent.cpp
index 979ef0d9171..40f1e925bef 100644
--- a/modules/navigation/rvo_agent.cpp
+++ b/modules/navigation/rvo_agent.cpp
@@ -32,10 +32,6 @@
#include "nav_map.h"
-RvoAgent::RvoAgent() {
- callback.id = ObjectID();
-}
-
void RvoAgent::set_map(NavMap *p_map) {
map = p_map;
}
@@ -50,31 +46,25 @@ bool RvoAgent::is_map_changed() {
}
}
-void RvoAgent::set_callback(ObjectID p_id, const StringName p_method, const Variant p_udata) {
- callback.id = p_id;
- callback.method = p_method;
- callback.udata = p_udata;
+void RvoAgent::set_callback(Callable p_callback) {
+ callback = p_callback;
}
bool RvoAgent::has_callback() const {
- return callback.id.is_valid();
+ return callback.is_valid();
}
void RvoAgent::dispatch_callback() {
- if (callback.id.is_null()) {
- return;
- }
- Object *obj = ObjectDB::get_instance(callback.id);
- if (!obj) {
- callback.id = ObjectID();
+ if (!callback.is_valid()) {
return;
}
- Callable::CallError responseCallError;
+ Vector3 new_velocity = Vector3(agent.newVelocity_.x(), agent.newVelocity_.y(), agent.newVelocity_.z());
- callback.new_velocity = Vector3(agent.newVelocity_.x(), agent.newVelocity_.y(), agent.newVelocity_.z());
-
- const Variant *vp[2] = { &callback.new_velocity, &callback.udata };
- int argc = (callback.udata.get_type() == Variant::NIL) ? 1 : 2;
- obj->callp(callback.method, vp, argc, responseCallError);
+ // Invoke the callback with the new velocity.
+ Variant args[] = { new_velocity };
+ const Variant *args_p[] = { &args[0] };
+ Variant return_value;
+ Callable::CallError call_error;
+ callback.callp(args_p, 1, return_value, call_error);
}
diff --git a/modules/navigation/rvo_agent.h b/modules/navigation/rvo_agent.h
index 7b19907b2ba..5f377b60791 100644
--- a/modules/navigation/rvo_agent.h
+++ b/modules/navigation/rvo_agent.h
@@ -39,21 +39,12 @@
class NavMap;
class RvoAgent : public NavRid {
- struct AvoidanceComputedCallback {
- ObjectID id;
- StringName method;
- Variant udata;
- Variant new_velocity;
- };
-
NavMap *map = nullptr;
RVO::Agent agent;
- AvoidanceComputedCallback callback;
+ Callable callback = Callable();
uint32_t map_update_id = 0;
public:
- RvoAgent();
-
void set_map(NavMap *p_map);
NavMap *get_map() {
return map;
@@ -65,7 +56,7 @@ public:
bool is_map_changed();
- void set_callback(ObjectID p_id, const StringName p_method, const Variant p_udata = Variant());
+ void set_callback(Callable p_callback);
bool has_callback() const;
void dispatch_callback();
diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp
index 907fb7e6a9b..e73b6e7e23a 100644
--- a/scene/2d/navigation_agent_2d.cpp
+++ b/scene/2d/navigation_agent_2d.cpp
@@ -205,9 +205,9 @@ NavigationAgent2D::~NavigationAgent2D() {
void NavigationAgent2D::set_avoidance_enabled(bool p_enabled) {
avoidance_enabled = p_enabled;
if (avoidance_enabled) {
- NavigationServer2D::get_singleton()->agent_set_callback(agent, get_instance_id(), "_avoidance_done");
+ NavigationServer2D::get_singleton()->agent_set_callback(agent, callable_mp(this, &NavigationAgent2D::_avoidance_done));
} else {
- NavigationServer2D::get_singleton()->agent_set_callback(agent, ObjectID(), "_avoidance_done");
+ NavigationServer2D::get_singleton()->agent_set_callback(agent, Callable());
}
}
@@ -217,7 +217,8 @@ bool NavigationAgent2D::get_avoidance_enabled() const {
void NavigationAgent2D::set_agent_parent(Node *p_agent_parent) {
// remove agent from any avoidance map before changing parent or there will be leftovers on the RVO map
- NavigationServer2D::get_singleton()->agent_set_callback(agent, ObjectID(), "_avoidance_done");
+ NavigationServer2D::get_singleton()->agent_set_callback(agent, Callable());
+
if (Object::cast_to(p_agent_parent) != nullptr) {
// place agent on navigation map first or else the RVO agent callback creation fails silently later
agent_parent = Object::cast_to(p_agent_parent);
@@ -226,6 +227,7 @@ void NavigationAgent2D::set_agent_parent(Node *p_agent_parent) {
} else {
NavigationServer2D::get_singleton()->agent_set_map(get_rid(), agent_parent->get_world_2d()->get_navigation_map());
}
+
// create new avoidance callback if enabled
set_avoidance_enabled(avoidance_enabled);
} else {
diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp
index fe7ddcb06ef..4aa6e61ec54 100644
--- a/scene/3d/navigation_agent_3d.cpp
+++ b/scene/3d/navigation_agent_3d.cpp
@@ -212,9 +212,9 @@ NavigationAgent3D::~NavigationAgent3D() {
void NavigationAgent3D::set_avoidance_enabled(bool p_enabled) {
avoidance_enabled = p_enabled;
if (avoidance_enabled) {
- NavigationServer3D::get_singleton()->agent_set_callback(agent, get_instance_id(), "_avoidance_done");
+ NavigationServer3D::get_singleton()->agent_set_callback(agent, callable_mp(this, &NavigationAgent3D::_avoidance_done));
} else {
- NavigationServer3D::get_singleton()->agent_set_callback(agent, ObjectID(), "_avoidance_done");
+ NavigationServer3D::get_singleton()->agent_set_callback(agent, Callable());
}
}
@@ -224,7 +224,8 @@ bool NavigationAgent3D::get_avoidance_enabled() const {
void NavigationAgent3D::set_agent_parent(Node *p_agent_parent) {
// remove agent from any avoidance map before changing parent or there will be leftovers on the RVO map
- NavigationServer3D::get_singleton()->agent_set_callback(agent, ObjectID(), "_avoidance_done");
+ NavigationServer3D::get_singleton()->agent_set_callback(agent, Callable());
+
if (Object::cast_to(p_agent_parent) != nullptr) {
// place agent on navigation map first or else the RVO agent callback creation fails silently later
agent_parent = Object::cast_to(p_agent_parent);
@@ -233,6 +234,7 @@ void NavigationAgent3D::set_agent_parent(Node *p_agent_parent) {
} else {
NavigationServer3D::get_singleton()->agent_set_map(get_rid(), agent_parent->get_world_3d()->get_navigation_map());
}
+
// create new avoidance callback if enabled
set_avoidance_enabled(avoidance_enabled);
} else {
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index 88178d5c7d7..2e4087c1de5 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -81,35 +81,12 @@ NavigationServer2D *NavigationServer2D::singleton = nullptr;
return CONV_R(NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1))); \
}
-#define FORWARD_4(FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, CONV_0, CONV_1, CONV_2, CONV_3) \
- NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) { \
- return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3)); \
- }
-
-#define FORWARD_4_R_C(CONV_R, FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, CONV_0, CONV_1, CONV_2, CONV_3) \
- NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) \
- const { \
- return CONV_R(NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3))); \
- }
-
-#define FORWARD_4_C(FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, CONV_0, CONV_1, CONV_2, CONV_3) \
- NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) \
- const { \
- return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3)); \
- }
-
#define FORWARD_5_R_C(CONV_R, FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, T_4, D_4, CONV_0, CONV_1, CONV_2, CONV_3, CONV_4) \
NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3, T_4 D_4) \
const { \
return CONV_R(NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3), CONV_4(D_4))); \
}
-#define FORWARD_5_C(FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, T_4, D_4, CONV_0, CONV_1, CONV_2, CONV_3, CONV_4) \
- NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3, T_4 D_4) \
- const { \
- return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3), CONV_4(D_4)); \
- }
-
static RID rid_to_rid(const RID d) {
return d;
}
@@ -155,18 +132,14 @@ static Transform3D trf2_to_trf3(const Transform2D &d) {
return Transform3D(b, o);
}
-static StringName sn_to_sn(const StringName &d) {
- return d;
-}
-
-static Variant var_to_var(const Variant &d) {
- return d;
-}
-
static ObjectID id_to_id(const ObjectID &id) {
return id;
}
+static Callable callable_to_callable(const Callable &c) {
+ return c;
+}
+
static Ref poly_to_mesh(Ref d) {
if (d.is_valid()) {
return d->get_navigation_mesh();
@@ -308,7 +281,7 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_set_target_velocity", "agent", "target_velocity"), &NavigationServer2D::agent_set_target_velocity);
ClassDB::bind_method(D_METHOD("agent_set_position", "agent", "position"), &NavigationServer2D::agent_set_position);
ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &NavigationServer2D::agent_is_map_changed);
- ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "object_id", "method", "userdata"), &NavigationServer2D::agent_set_callback, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "callback"), &NavigationServer2D::agent_set_callback);
ClassDB::bind_method(D_METHOD("free_rid", "rid"), &NavigationServer2D::free);
@@ -420,7 +393,7 @@ void FORWARD_2(agent_set_target_velocity, RID, p_agent, Vector2, p_velocity, rid
void FORWARD_2(agent_set_position, RID, p_agent, Vector2, p_position, rid_to_rid, v2_to_v3);
void FORWARD_2(agent_set_ignore_y, RID, p_agent, bool, p_ignore, rid_to_rid, bool_to_bool);
bool FORWARD_1_C(agent_is_map_changed, RID, p_agent, rid_to_rid);
-void FORWARD_4(agent_set_callback, RID, p_agent, ObjectID, p_object_id, StringName, p_method, Variant, p_udata, rid_to_rid, id_to_id, sn_to_sn, var_to_var);
+void FORWARD_2(agent_set_callback, RID, p_agent, Callable, p_callback, rid_to_rid, callable_to_callable);
void FORWARD_1(free, RID, p_object, rid_to_rid);
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index b50808cddf3..cd18476182f 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -223,7 +223,7 @@ public:
virtual bool agent_is_map_changed(RID p_agent) const;
/// Callback called at the end of the RVO process
- virtual void agent_set_callback(RID p_agent, ObjectID p_object_id, StringName p_method, Variant p_udata = Variant());
+ virtual void agent_set_callback(RID p_agent, Callable p_callback);
virtual void query_path(const Ref &p_query_parameters, Ref p_query_result) const;
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index 07256badefd..5b95317a38f 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -113,7 +113,7 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_set_target_velocity", "agent", "target_velocity"), &NavigationServer3D::agent_set_target_velocity);
ClassDB::bind_method(D_METHOD("agent_set_position", "agent", "position"), &NavigationServer3D::agent_set_position);
ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &NavigationServer3D::agent_is_map_changed);
- ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "object_id", "method", "userdata"), &NavigationServer3D::agent_set_callback, DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "callback"), &NavigationServer3D::agent_set_callback);
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 4d81726fc35..9c468d1b10e 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -238,7 +238,7 @@ public:
virtual bool agent_is_map_changed(RID p_agent) const = 0;
/// Callback called at the end of the RVO process
- virtual void agent_set_callback(RID p_agent, ObjectID p_object_id, StringName p_method, Variant p_udata = Variant()) = 0;
+ virtual void agent_set_callback(RID p_agent, Callable p_callback) = 0;
/// Destroy the `RID`
virtual void free(RID p_object) = 0;