mirror of
https://github.com/godotengine/godot.git
synced 2024-11-25 13:43:15 +00:00
Merge pull request #72228 from DarkKilauea/nav-agent-callable
Use Callable for Navigation Agent callbacks
This commit is contained in:
commit
3a25148b9b
@ -41,12 +41,10 @@
|
||||
<method name="agent_set_callback">
|
||||
<return type="void" />
|
||||
<param index="0" name="agent" type="RID" />
|
||||
<param index="1" name="object_id" type="int" />
|
||||
<param index="2" name="method" type="StringName" />
|
||||
<param index="3" name="userdata" type="Variant" default="null" />
|
||||
<param index="1" name="callback" type="Callable" />
|
||||
<description>
|
||||
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].
|
||||
</description>
|
||||
</method>
|
||||
<method name="agent_set_map">
|
||||
|
@ -41,12 +41,10 @@
|
||||
<method name="agent_set_callback">
|
||||
<return type="void" />
|
||||
<param index="0" name="agent" type="RID" />
|
||||
<param index="1" name="object_id" type="int" />
|
||||
<param index="2" name="method" type="StringName" />
|
||||
<param index="3" name="userdata" type="Variant" default="null" />
|
||||
<param index="1" name="callback" type="Callable" />
|
||||
<description>
|
||||
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].
|
||||
</description>
|
||||
</method>
|
||||
<method name="agent_set_map">
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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<Node2D>(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<Node2D>(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 {
|
||||
|
@ -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<Node3D>(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<Node3D>(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 {
|
||||
|
@ -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<NavigationMesh> poly_to_mesh(Ref<NavigationPolygon> 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);
|
||||
|
||||
|
@ -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<NavigationPathQueryParameters2D> &p_query_parameters, Ref<NavigationPathQueryResult2D> p_query_result) const;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user