Merge pull request #78081 from smix8/obstacle_api_update_4.x

Update NavigationObstacle API
This commit is contained in:
Rémi Verschelde 2023-06-12 17:10:28 +02:00
commit e208cdb170
No known key found for this signature in database
GPG Key ID: C3336907360768E1
18 changed files with 413 additions and 115 deletions

View File

@ -13,12 +13,6 @@
<link title="Using NavigationObstacles">$DOCS_URL/tutorials/navigation/navigation_using_navigationobstacles.html</link>
</tutorials>
<methods>
<method name="get_agent_rid" qualifiers="const">
<return type="RID" />
<description>
Returns the [RID] of this agent on the [NavigationServer2D]. This [RID] is used for the moving avoidance "obstacle" component (using a fake avoidance agent) which size is defined by [member radius] and velocity set by using [member velocity].
</description>
</method>
<method name="get_avoidance_layer_value" qualifiers="const">
<return type="bool" />
<param index="0" name="layer_number" type="int" />
@ -32,10 +26,10 @@
Returns the [RID] of the navigation map for this NavigationObstacle node. This function returns always the map set on the NavigationObstacle node and not the map of the abstract obstacle on the NavigationServer. If the obstacle map is changed directly with the NavigationServer API the NavigationObstacle node will not be aware of the map change. Use [method set_navigation_map] to change the navigation map for the NavigationObstacle and also update the obstacle on the NavigationServer.
</description>
</method>
<method name="get_obstacle_rid" qualifiers="const">
<method name="get_rid" qualifiers="const">
<return type="RID" />
<description>
Returns the [RID] of this obstacle on the [NavigationServer2D]. This [RID] is used for the static avoidance obstacle component which shape is defined by [member vertices].
Returns the [RID] of this obstacle on the [NavigationServer2D].
</description>
</method>
<method name="set_avoidance_layer_value">
@ -55,6 +49,9 @@
</method>
</methods>
<members>
<member name="avoidance_enabled" type="bool" setter="set_avoidance_enabled" getter="get_avoidance_enabled" default="true">
If [code]true[/code] the obstacle affects avoidance using agents.
</member>
<member name="avoidance_layers" type="int" setter="set_avoidance_layers" getter="get_avoidance_layers" default="1">
A bitfield determining the avoidance layers for this obstacle. Agent's with a matching bit on the their avoidance mask will avoid this obstacle.
</member>

View File

@ -13,12 +13,6 @@
<link title="Using NavigationObstacles">$DOCS_URL/tutorials/navigation/navigation_using_navigationobstacles.html</link>
</tutorials>
<methods>
<method name="get_agent_rid" qualifiers="const">
<return type="RID" />
<description>
Returns the [RID] of this agent on the [NavigationServer3D]. This [RID] is used for the moving avoidance "obstacle" component (using a fake avoidance agent) which size is defined by [member radius] and velocity set by using [member velocity].
</description>
</method>
<method name="get_avoidance_layer_value" qualifiers="const">
<return type="bool" />
<param index="0" name="layer_number" type="int" />
@ -32,10 +26,10 @@
Returns the [RID] of the navigation map for this NavigationObstacle node. This function returns always the map set on the NavigationObstacle node and not the map of the abstract obstacle on the NavigationServer. If the obstacle map is changed directly with the NavigationServer API the NavigationObstacle node will not be aware of the map change. Use [method set_navigation_map] to change the navigation map for the NavigationObstacle and also update the obstacle on the NavigationServer.
</description>
</method>
<method name="get_obstacle_rid" qualifiers="const">
<method name="get_rid" qualifiers="const">
<return type="RID" />
<description>
Returns the [RID] of this obstacle on the [NavigationServer3D]. This [RID] is used for the static avoidance obstacle component which shape is defined by [member vertices].
Returns the [RID] of this obstacle on the [NavigationServer3D].
</description>
</method>
<method name="set_avoidance_layer_value">
@ -55,6 +49,9 @@
</method>
</methods>
<members>
<member name="avoidance_enabled" type="bool" setter="set_avoidance_enabled" getter="get_avoidance_enabled" default="true">
If [code]true[/code] the obstacle affects avoidance using agents.
</member>
<member name="avoidance_layers" type="int" setter="set_avoidance_layers" getter="get_avoidance_layers" default="1">
A bitfield determining the avoidance layers for this obstacle. Agent's with a matching bit on the their avoidance mask will avoid this obstacle.
</member>

View File

@ -464,6 +464,13 @@
Creates a new navigation obstacle.
</description>
</method>
<method name="obstacle_get_avoidance_enabled" qualifiers="const">
<return type="bool" />
<param index="0" name="obstacle" type="RID" />
<description>
Returns [code]true[/code] if the provided [param obstacle] has avoidance enabled.
</description>
</method>
<method name="obstacle_get_map" qualifiers="const">
<return type="RID" />
<param index="0" name="obstacle" type="RID" />
@ -471,11 +478,20 @@
Returns the navigation map [RID] the requested [param obstacle] is currently assigned to.
</description>
</method>
<method name="obstacle_set_avoidance_enabled">
<return type="void" />
<param index="0" name="obstacle" type="RID" />
<param index="1" name="enabled" type="bool" />
<description>
If [param enabled] the provided [param obstacle] affects avoidance using agents.
</description>
</method>
<method name="obstacle_set_avoidance_layers">
<return type="void" />
<param index="0" name="obstacle" type="RID" />
<param index="1" name="layers" type="int" />
<description>
Set the obstacles's [code]avoidance_layers[/code] bitmask.
</description>
</method>
<method name="obstacle_set_map">
@ -494,6 +510,22 @@
Sets the position of the obstacle in world space.
</description>
</method>
<method name="obstacle_set_radius">
<return type="void" />
<param index="0" name="obstacle" type="RID" />
<param index="1" name="radius" type="float" />
<description>
Sets the radius of the dynamic obstacle.
</description>
</method>
<method name="obstacle_set_velocity">
<return type="void" />
<param index="0" name="obstacle" type="RID" />
<param index="1" name="velocity" type="Vector2" />
<description>
Sets [param velocity] of the dynamic [param obstacle]. Allows other agents to better predict the movement of the dynamic obstacle. Only works in combination with the radius of the obstacle.
</description>
</method>
<method name="obstacle_set_vertices">
<return type="void" />
<param index="0" name="obstacle" type="RID" />

View File

@ -529,6 +529,13 @@
Creates a new obstacle.
</description>
</method>
<method name="obstacle_get_avoidance_enabled" qualifiers="const">
<return type="bool" />
<param index="0" name="obstacle" type="RID" />
<description>
Returns [code]true[/code] if the provided [param obstacle] has avoidance enabled.
</description>
</method>
<method name="obstacle_get_map" qualifiers="const">
<return type="RID" />
<param index="0" name="obstacle" type="RID" />
@ -536,6 +543,21 @@
Returns the navigation map [RID] the requested [param obstacle] is currently assigned to.
</description>
</method>
<method name="obstacle_get_use_3d_avoidance" qualifiers="const">
<return type="bool" />
<param index="0" name="obstacle" type="RID" />
<description>
Returns [code]true[/code] if the provided [param obstacle] uses avoidance in 3D space Vector3(x,y,z) instead of horizontal 2D Vector2(x,y) / Vector3(x,0.0,z).
</description>
</method>
<method name="obstacle_set_avoidance_enabled">
<return type="void" />
<param index="0" name="obstacle" type="RID" />
<param index="1" name="enabled" type="bool" />
<description>
If [param enabled] the provided [param obstacle] affects avoidance using agents.
</description>
</method>
<method name="obstacle_set_avoidance_layers">
<return type="void" />
<param index="0" name="obstacle" type="RID" />
@ -568,6 +590,30 @@
Updates the [param position] in world space for the [param obstacle].
</description>
</method>
<method name="obstacle_set_radius">
<return type="void" />
<param index="0" name="obstacle" type="RID" />
<param index="1" name="radius" type="float" />
<description>
Sets the radius of the dynamic obstacle.
</description>
</method>
<method name="obstacle_set_use_3d_avoidance">
<return type="void" />
<param index="0" name="obstacle" type="RID" />
<param index="1" name="enabled" type="bool" />
<description>
Sets if the [param obstacle] uses the 2D avoidance or the 3D avoidance while avoidance is enabled.
</description>
</method>
<method name="obstacle_set_velocity">
<return type="void" />
<param index="0" name="obstacle" type="RID" />
<param index="1" name="velocity" type="Vector3" />
<description>
Sets [param velocity] of the dynamic [param obstacle]. Allows other agents to better predict the movement of the dynamic obstacle. Only works in combination with the radius of the obstacle.
</description>
</method>
<method name="obstacle_set_vertices">
<return type="void" />
<param index="0" name="obstacle" type="RID" />

View File

@ -85,11 +85,9 @@ Validate extension JSON: API was removed: classes/NavigationAgent3D/methods/set_
Validate extension JSON: API was removed: classes/NavigationAgent3D/properties/agent_height_offset
Validate extension JSON: API was removed: classes/NavigationAgent3D/properties/ignore_y
Validate extension JSON: API was removed: classes/NavigationAgent3D/properties/time_horizon
Validate extension JSON: API was removed: classes/NavigationObstacle2D/methods/get_rid
Validate extension JSON: API was removed: classes/NavigationObstacle2D/methods/is_radius_estimated
Validate extension JSON: API was removed: classes/NavigationObstacle2D/methods/set_estimate_radius
Validate extension JSON: API was removed: classes/NavigationObstacle2D/properties/estimate_radius
Validate extension JSON: API was removed: classes/NavigationObstacle3D/methods/get_rid
Validate extension JSON: API was removed: classes/NavigationObstacle3D/methods/is_radius_estimated
Validate extension JSON: API was removed: classes/NavigationObstacle3D/methods/set_estimate_radius
Validate extension JSON: API was removed: classes/NavigationObstacle3D/properties/estimate_radius

View File

@ -802,9 +802,44 @@ RID GodotNavigationServer::obstacle_create() {
RID rid = obstacle_owner.make_rid();
NavObstacle *obstacle = obstacle_owner.get_or_null(rid);
obstacle->set_self(rid);
RID agent_rid = agent_owner.make_rid();
NavAgent *agent = agent_owner.get_or_null(agent_rid);
agent->set_self(agent_rid);
obstacle->set_agent(agent);
return rid;
}
COMMAND_2(obstacle_set_avoidance_enabled, RID, p_obstacle, bool, p_enabled) {
NavObstacle *obstacle = obstacle_owner.get_or_null(p_obstacle);
ERR_FAIL_COND(obstacle == nullptr);
obstacle->set_avoidance_enabled(p_enabled);
}
bool GodotNavigationServer::obstacle_get_avoidance_enabled(RID p_obstacle) const {
NavObstacle *obstacle = obstacle_owner.get_or_null(p_obstacle);
ERR_FAIL_COND_V(obstacle == nullptr, false);
return obstacle->is_avoidance_enabled();
}
COMMAND_2(obstacle_set_use_3d_avoidance, RID, p_obstacle, bool, p_enabled) {
NavObstacle *obstacle = obstacle_owner.get_or_null(p_obstacle);
ERR_FAIL_COND(obstacle == nullptr);
obstacle->set_use_3d_avoidance(p_enabled);
}
bool GodotNavigationServer::obstacle_get_use_3d_avoidance(RID p_obstacle) const {
NavObstacle *obstacle = obstacle_owner.get_or_null(p_obstacle);
ERR_FAIL_COND_V(obstacle == nullptr, false);
return obstacle->get_use_3d_avoidance();
}
COMMAND_2(obstacle_set_map, RID, p_obstacle, RID, p_map) {
NavObstacle *obstacle = obstacle_owner.get_or_null(p_obstacle);
ERR_FAIL_COND(obstacle == nullptr);
@ -837,12 +872,27 @@ RID GodotNavigationServer::obstacle_get_map(RID p_obstacle) const {
return RID();
}
COMMAND_2(obstacle_set_radius, RID, p_obstacle, real_t, p_radius) {
ERR_FAIL_COND_MSG(p_radius < 0.0, "Radius must be positive.");
NavObstacle *obstacle = obstacle_owner.get_or_null(p_obstacle);
ERR_FAIL_COND(obstacle == nullptr);
obstacle->set_radius(p_radius);
}
COMMAND_2(obstacle_set_height, RID, p_obstacle, real_t, p_height) {
NavObstacle *obstacle = obstacle_owner.get_or_null(p_obstacle);
ERR_FAIL_COND(obstacle == nullptr);
obstacle->set_height(p_height);
}
COMMAND_2(obstacle_set_velocity, RID, p_obstacle, Vector3, p_velocity) {
NavObstacle *obstacle = obstacle_owner.get_or_null(p_obstacle);
ERR_FAIL_COND(obstacle == nullptr);
obstacle->set_velocity(p_velocity);
}
COMMAND_2(obstacle_set_position, RID, p_obstacle, Vector3, p_position) {
NavObstacle *obstacle = obstacle_owner.get_or_null(p_obstacle);
ERR_FAIL_COND(obstacle == nullptr);
@ -917,29 +967,42 @@ COMMAND_1(free, RID, p_object) {
link_owner.free(p_object);
} else if (agent_owner.owns(p_object)) {
NavAgent *agent = agent_owner.get_or_null(p_object);
internal_free_agent(p_object);
// Removes this agent from the map if assigned
} else if (obstacle_owner.owns(p_object)) {
internal_free_obstacle(p_object);
} else {
ERR_PRINT("Attempted to free a NavigationServer RID that did not exist (or was already freed).");
}
}
void GodotNavigationServer::internal_free_agent(RID p_object) {
NavAgent *agent = agent_owner.get_or_null(p_object);
if (agent) {
if (agent->get_map() != nullptr) {
agent->get_map()->remove_agent(agent);
agent->set_map(nullptr);
}
agent_owner.free(p_object);
}
}
} else if (obstacle_owner.owns(p_object)) {
NavObstacle *obstacle = obstacle_owner.get_or_null(p_object);
// Removes this agent from the map if assigned
void GodotNavigationServer::internal_free_obstacle(RID p_object) {
NavObstacle *obstacle = obstacle_owner.get_or_null(p_object);
if (obstacle) {
if (obstacle->get_map() != nullptr) {
obstacle->get_map()->remove_obstacle(obstacle);
obstacle->set_map(nullptr);
}
if (obstacle->get_agent()) {
if (obstacle->get_agent()->get_self() != RID()) {
RID _agent_rid = obstacle->get_agent()->get_self();
obstacle->set_agent(nullptr);
internal_free_agent(_agent_rid);
}
}
obstacle_owner.free(p_object);
} else {
ERR_PRINT("Attempted to free a NavigationServer RID that did not exist (or was already freed).");
}
}

View File

@ -198,8 +198,14 @@ public:
COMMAND_2(agent_set_avoidance_priority, RID, p_agent, real_t, p_priority);
virtual RID obstacle_create() override;
COMMAND_2(obstacle_set_avoidance_enabled, RID, p_obstacle, bool, p_enabled);
virtual bool obstacle_get_avoidance_enabled(RID p_obstacle) const override;
COMMAND_2(obstacle_set_use_3d_avoidance, RID, p_obstacle, bool, p_enabled);
virtual bool obstacle_get_use_3d_avoidance(RID p_obstacle) const override;
COMMAND_2(obstacle_set_map, RID, p_obstacle, RID, p_map);
virtual RID obstacle_get_map(RID p_obstacle) const override;
COMMAND_2(obstacle_set_radius, RID, p_obstacle, real_t, p_radius);
COMMAND_2(obstacle_set_velocity, RID, p_obstacle, Vector3, p_velocity);
COMMAND_2(obstacle_set_position, RID, p_obstacle, Vector3, p_position);
COMMAND_2(obstacle_set_height, RID, p_obstacle, real_t, p_height);
virtual void obstacle_set_vertices(RID p_obstacle, const Vector<Vector3> &p_vertices) override;
@ -215,6 +221,10 @@ public:
virtual NavigationUtilities::PathQueryResult _query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const override;
int get_process_info(ProcessInfo p_info) const override;
private:
void internal_free_agent(RID p_object);
void internal_free_obstacle(RID p_object);
};
#undef COMMAND_1

View File

@ -30,38 +30,121 @@
#include "nav_obstacle.h"
#include "nav_agent.h"
#include "nav_map.h"
NavObstacle::NavObstacle() {}
NavObstacle::~NavObstacle() {}
void NavObstacle::set_agent(NavAgent *p_agent) {
if (agent == p_agent) {
return;
}
agent = p_agent;
internal_update_agent();
}
void NavObstacle::set_avoidance_enabled(bool p_enabled) {
if (avoidance_enabled == p_enabled) {
return;
}
avoidance_enabled = p_enabled;
obstacle_dirty = true;
internal_update_agent();
}
void NavObstacle::set_use_3d_avoidance(bool p_enabled) {
if (use_3d_avoidance == p_enabled) {
return;
}
use_3d_avoidance = p_enabled;
obstacle_dirty = true;
if (agent) {
agent->set_use_3d_avoidance(use_3d_avoidance);
}
}
void NavObstacle::set_map(NavMap *p_map) {
if (map != p_map) {
map = p_map;
obstacle_dirty = true;
if (map == p_map) {
return;
}
if (map) {
map->remove_obstacle(this);
if (agent) {
agent->set_map(nullptr);
}
}
map = p_map;
obstacle_dirty = true;
if (map) {
map->add_obstacle(this);
internal_update_agent();
}
}
void NavObstacle::set_position(const Vector3 p_position) {
if (position != p_position) {
position = p_position;
obstacle_dirty = true;
if (position == p_position) {
return;
}
position = p_position;
obstacle_dirty = true;
if (agent) {
agent->set_position(position);
}
}
void NavObstacle::set_radius(real_t p_radius) {
if (radius == p_radius) {
return;
}
radius = p_radius;
if (agent) {
agent->set_radius(radius);
}
}
void NavObstacle::set_height(const real_t p_height) {
if (height != p_height) {
height = p_height;
obstacle_dirty = true;
if (height == p_height) {
return;
}
height = p_height;
obstacle_dirty = true;
if (agent) {
agent->set_height(height);
}
}
void NavObstacle::set_velocity(const Vector3 p_velocity) {
velocity = p_velocity;
if (agent) {
agent->set_velocity(velocity);
}
}
void NavObstacle::set_vertices(const Vector<Vector3> &p_vertices) {
if (vertices != p_vertices) {
vertices = p_vertices;
obstacle_dirty = true;
if (vertices == p_vertices) {
return;
}
vertices = p_vertices;
obstacle_dirty = true;
}
bool NavObstacle::is_map_changed() {
@ -75,8 +158,16 @@ bool NavObstacle::is_map_changed() {
}
void NavObstacle::set_avoidance_layers(uint32_t p_layers) {
if (avoidance_layers == p_layers) {
return;
}
avoidance_layers = p_layers;
obstacle_dirty = true;
if (agent) {
agent->set_avoidance_layers(avoidance_layers);
}
}
bool NavObstacle::check_dirty() {
@ -84,3 +175,22 @@ bool NavObstacle::check_dirty() {
obstacle_dirty = false;
return was_dirty;
}
void NavObstacle::internal_update_agent() {
if (agent) {
agent->set_neighbor_distance(0.0);
agent->set_max_neighbors(0.0);
agent->set_time_horizon_agents(0.0);
agent->set_time_horizon_obstacles(0.0);
agent->set_avoidance_mask(0.0);
agent->set_neighbor_distance(0.0);
agent->set_avoidance_priority(1.0);
agent->set_map(map);
agent->set_radius(radius);
agent->set_height(height);
agent->set_position(position);
agent->set_avoidance_layers(avoidance_layers);
agent->set_avoidance_enabled(avoidance_enabled);
agent->set_use_3d_avoidance(use_3d_avoidance);
}
}

View File

@ -33,18 +33,23 @@
#include "core/object/class_db.h"
#include "core/templates/local_vector.h"
#include "nav_agent.h"
#include "nav_rid.h"
class NavAgent;
class NavMap;
class NavObstacle : public NavRid {
NavAgent *agent = nullptr;
NavMap *map = nullptr;
Vector3 velocity;
Vector3 position;
Vector<Vector3> vertices;
real_t radius = 0.0;
real_t height = 0.0;
bool avoidance_enabled = false;
bool use_3d_avoidance = false;
uint32_t avoidance_layers = 1;
bool obstacle_dirty = true;
@ -55,15 +60,30 @@ public:
NavObstacle();
~NavObstacle();
void set_avoidance_enabled(bool p_enabled);
bool is_avoidance_enabled() { return avoidance_enabled; }
void set_use_3d_avoidance(bool p_enabled);
bool get_use_3d_avoidance() { return use_3d_avoidance; }
void set_map(NavMap *p_map);
NavMap *get_map() { return map; }
void set_agent(NavAgent *p_agent);
NavAgent *get_agent() { return agent; }
void set_position(const Vector3 p_position);
const Vector3 &get_position() const { return position; }
void set_radius(real_t p_radius);
real_t get_radius() const { return radius; }
void set_height(const real_t p_height);
real_t get_height() const { return height; }
void set_velocity(const Vector3 p_velocity);
const Vector3 &get_velocity() const { return velocity; }
void set_vertices(const Vector<Vector3> &p_vertices);
const Vector<Vector3> &get_vertices() const { return vertices; }
@ -73,6 +93,9 @@ public:
uint32_t get_avoidance_layers() const { return avoidance_layers; };
bool check_dirty();
private:
void internal_update_agent();
};
#endif // NAV_OBSTACLE_H

View File

@ -36,8 +36,10 @@
#include "servers/navigation_server_3d.h"
void NavigationObstacle2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_obstacle_rid"), &NavigationObstacle2D::get_obstacle_rid);
ClassDB::bind_method(D_METHOD("get_agent_rid"), &NavigationObstacle2D::get_agent_rid);
ClassDB::bind_method(D_METHOD("get_rid"), &NavigationObstacle2D::get_rid);
ClassDB::bind_method(D_METHOD("set_avoidance_enabled", "enabled"), &NavigationObstacle2D::set_avoidance_enabled);
ClassDB::bind_method(D_METHOD("get_avoidance_enabled"), &NavigationObstacle2D::get_avoidance_enabled);
ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationObstacle2D::set_navigation_map);
ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationObstacle2D::get_navigation_map);
@ -56,7 +58,8 @@ void NavigationObstacle2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_avoidance_layer_value", "layer_number", "value"), &NavigationObstacle2D::set_avoidance_layer_value);
ClassDB::bind_method(D_METHOD("get_avoidance_layer_value", "layer_number"), &NavigationObstacle2D::get_avoidance_layer_value);
ADD_GROUP("Avoidance", "avoidance_");
ADD_GROUP("Avoidance", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_velocity", "get_velocity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.0,500,0.01,suffix:px"), "set_radius", "get_radius");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "vertices"), "set_vertices", "get_vertices");
@ -75,7 +78,7 @@ void NavigationObstacle2D::_notification(int p_what) {
}
previous_transform = get_global_transform();
// need to trigger map controlled agent assignment somehow for the fake_agent since obstacles use no callback like regular agents
NavigationServer2D::get_singleton()->agent_set_avoidance_enabled(fake_agent, radius > 0);
NavigationServer2D::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled);
_update_position(get_global_transform().get_origin());
set_physics_process_internal(true);
} break;
@ -113,7 +116,7 @@ void NavigationObstacle2D::_notification(int p_what) {
velocity_submitted = false;
// only update if there is a noticeable change, else the rvo agent preferred velocity stays the same
if (!previous_velocity.is_equal_approx(velocity)) {
NavigationServer2D::get_singleton()->agent_set_velocity(fake_agent, velocity);
NavigationServer2D::get_singleton()->obstacle_set_velocity(obstacle, velocity);
}
previous_velocity = velocity;
}
@ -142,21 +145,11 @@ void NavigationObstacle2D::_notification(int p_what) {
NavigationObstacle2D::NavigationObstacle2D() {
obstacle = NavigationServer2D::get_singleton()->obstacle_create();
fake_agent = NavigationServer2D::get_singleton()->agent_create();
// change properties of the fake agent so it can act as fake obstacle with a radius
NavigationServer2D::get_singleton()->agent_set_neighbor_distance(fake_agent, 0.0);
NavigationServer2D::get_singleton()->agent_set_max_neighbors(fake_agent, 0);
NavigationServer2D::get_singleton()->agent_set_time_horizon_agents(fake_agent, 0.0);
NavigationServer2D::get_singleton()->agent_set_time_horizon_obstacles(fake_agent, 0.0);
NavigationServer2D::get_singleton()->agent_set_max_speed(fake_agent, 0.0);
NavigationServer2D::get_singleton()->agent_set_avoidance_mask(fake_agent, 0);
NavigationServer2D::get_singleton()->agent_set_avoidance_priority(fake_agent, 1.0);
NavigationServer2D::get_singleton()->agent_set_avoidance_enabled(fake_agent, radius > 0);
set_radius(radius);
set_vertices(vertices);
set_avoidance_layers(avoidance_layers);
set_avoidance_enabled(avoidance_enabled);
}
NavigationObstacle2D::~NavigationObstacle2D() {
@ -164,9 +157,6 @@ NavigationObstacle2D::~NavigationObstacle2D() {
NavigationServer2D::get_singleton()->free(obstacle);
obstacle = RID();
NavigationServer2D::get_singleton()->free(fake_agent);
fake_agent = RID();
}
void NavigationObstacle2D::set_vertices(const Vector<Vector2> &p_vertices) {
@ -202,17 +192,18 @@ void NavigationObstacle2D::set_radius(real_t p_radius) {
radius = p_radius;
NavigationServer2D::get_singleton()->agent_set_avoidance_enabled(fake_agent, radius > 0.0);
NavigationServer2D::get_singleton()->agent_set_radius(fake_agent, radius);
NavigationServer2D::get_singleton()->obstacle_set_radius(obstacle, radius);
if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint())) {
queue_redraw();
}
}
void NavigationObstacle2D::set_avoidance_layers(uint32_t p_layers) {
if (avoidance_layers == p_layers) {
return;
}
avoidance_layers = p_layers;
NavigationServer2D::get_singleton()->obstacle_set_avoidance_layers(obstacle, avoidance_layers);
NavigationServer2D::get_singleton()->agent_set_avoidance_layers(fake_agent, avoidance_layers);
}
uint32_t NavigationObstacle2D::get_avoidance_layers() const {
@ -237,24 +228,31 @@ bool NavigationObstacle2D::get_avoidance_layer_value(int p_layer_number) const {
return get_avoidance_layers() & (1 << (p_layer_number - 1));
}
void NavigationObstacle2D::set_avoidance_enabled(bool p_enabled) {
if (avoidance_enabled == p_enabled) {
return;
}
avoidance_enabled = p_enabled;
NavigationServer2D::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled);
}
bool NavigationObstacle2D::get_avoidance_enabled() const {
return avoidance_enabled;
}
void NavigationObstacle2D::set_velocity(const Vector2 p_velocity) {
velocity = p_velocity;
velocity_submitted = true;
}
void NavigationObstacle2D::_update_map(RID p_map) {
NavigationServer2D::get_singleton()->obstacle_set_map(obstacle, p_map);
NavigationServer2D::get_singleton()->agent_set_map(fake_agent, p_map);
map_current = p_map;
NavigationServer2D::get_singleton()->obstacle_set_map(obstacle, p_map);
}
void NavigationObstacle2D::_update_position(const Vector2 p_position) {
if (vertices.size() > 0) {
NavigationServer2D::get_singleton()->obstacle_set_position(obstacle, p_position);
}
if (radius > 0.0) {
NavigationServer2D::get_singleton()->agent_set_position(fake_agent, p_position);
}
NavigationServer2D::get_singleton()->obstacle_set_position(obstacle, p_position);
}
#ifdef DEBUG_ENABLED

View File

@ -45,7 +45,7 @@ class NavigationObstacle2D : public Node2D {
Vector<Vector2> vertices;
RID fake_agent;
bool avoidance_enabled = true;
uint32_t avoidance_layers = 1;
Transform2D previous_transform;
@ -68,8 +68,10 @@ public:
NavigationObstacle2D();
virtual ~NavigationObstacle2D();
RID get_obstacle_rid() const { return obstacle; }
RID get_agent_rid() const { return fake_agent; }
RID get_rid() const { return obstacle; }
void set_avoidance_enabled(bool p_enabled);
bool get_avoidance_enabled() const;
void set_navigation_map(RID p_navigation_map);
RID get_navigation_map() const;

View File

@ -36,8 +36,10 @@
#include "servers/navigation_server_3d.h"
void NavigationObstacle3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_obstacle_rid"), &NavigationObstacle3D::get_obstacle_rid);
ClassDB::bind_method(D_METHOD("get_agent_rid"), &NavigationObstacle3D::get_agent_rid);
ClassDB::bind_method(D_METHOD("get_rid"), &NavigationObstacle3D::get_rid);
ClassDB::bind_method(D_METHOD("set_avoidance_enabled", "enabled"), &NavigationObstacle3D::set_avoidance_enabled);
ClassDB::bind_method(D_METHOD("get_avoidance_enabled"), &NavigationObstacle3D::get_avoidance_enabled);
ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationObstacle3D::set_navigation_map);
ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationObstacle3D::get_navigation_map);
@ -63,7 +65,8 @@ void NavigationObstacle3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_use_3d_avoidance", "enabled"), &NavigationObstacle3D::set_use_3d_avoidance);
ClassDB::bind_method(D_METHOD("get_use_3d_avoidance"), &NavigationObstacle3D::get_use_3d_avoidance);
ADD_GROUP("Avoidance", "avoidance_");
ADD_GROUP("Avoidance", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_velocity", "get_velocity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.0,100,0.01,suffix:m"), "set_radius", "get_radius");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "height", PROPERTY_HINT_RANGE, "0.0,100,0.01,suffix:m"), "set_height", "get_height");
@ -84,7 +87,7 @@ void NavigationObstacle3D::_notification(int p_what) {
}
previous_transform = get_global_transform();
// need to trigger map controlled agent assignment somehow for the fake_agent since obstacles use no callback like regular agents
NavigationServer3D::get_singleton()->agent_set_avoidance_enabled(fake_agent, radius > 0);
NavigationServer3D::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled);
_update_position(get_global_transform().origin);
set_physics_process_internal(true);
#ifdef DEBUG_ENABLED
@ -137,7 +140,7 @@ void NavigationObstacle3D::_notification(int p_what) {
velocity_submitted = false;
// only update if there is a noticeable change, else the rvo agent preferred velocity stays the same
if (!previous_velocity.is_equal_approx(velocity)) {
NavigationServer3D::get_singleton()->agent_set_velocity(fake_agent, velocity);
NavigationServer3D::get_singleton()->obstacle_set_velocity(obstacle, velocity);
}
previous_velocity = velocity;
}
@ -156,22 +159,12 @@ void NavigationObstacle3D::_notification(int p_what) {
NavigationObstacle3D::NavigationObstacle3D() {
obstacle = NavigationServer3D::get_singleton()->obstacle_create();
fake_agent = NavigationServer3D::get_singleton()->agent_create();
// change properties of the fake agent so it can act as fake obstacle with a radius
NavigationServer3D::get_singleton()->agent_set_neighbor_distance(fake_agent, 0.0);
NavigationServer3D::get_singleton()->agent_set_max_neighbors(fake_agent, 0);
NavigationServer3D::get_singleton()->agent_set_time_horizon_agents(fake_agent, 0.0);
NavigationServer3D::get_singleton()->agent_set_time_horizon_obstacles(fake_agent, 0.0);
NavigationServer3D::get_singleton()->agent_set_max_speed(fake_agent, 0.0);
NavigationServer3D::get_singleton()->agent_set_avoidance_mask(fake_agent, 1);
NavigationServer3D::get_singleton()->agent_set_avoidance_priority(fake_agent, 1.0);
NavigationServer3D::get_singleton()->agent_set_avoidance_enabled(fake_agent, radius > 0);
set_radius(radius);
set_height(height);
set_vertices(vertices);
set_avoidance_layers(avoidance_layers);
set_avoidance_enabled(avoidance_enabled);
set_use_3d_avoidance(use_3d_avoidance);
#ifdef DEBUG_ENABLED
@ -188,9 +181,6 @@ NavigationObstacle3D::~NavigationObstacle3D() {
NavigationServer3D::get_singleton()->free(obstacle);
obstacle = RID();
NavigationServer3D::get_singleton()->free(fake_agent);
fake_agent = RID();
#ifdef DEBUG_ENABLED
NavigationServer3D::get_singleton()->disconnect("avoidance_debug_changed", callable_mp(this, &NavigationObstacle3D::_update_fake_agent_radius_debug));
NavigationServer3D::get_singleton()->disconnect("avoidance_debug_changed", callable_mp(this, &NavigationObstacle3D::_update_static_obstacle_debug));
@ -242,8 +232,7 @@ void NavigationObstacle3D::set_radius(real_t p_radius) {
}
radius = p_radius;
NavigationServer3D::get_singleton()->agent_set_avoidance_enabled(fake_agent, radius > 0.0);
NavigationServer3D::get_singleton()->agent_set_radius(fake_agent, radius);
NavigationServer3D::get_singleton()->obstacle_set_radius(obstacle, radius);
#ifdef DEBUG_ENABLED
_update_fake_agent_radius_debug();
@ -258,7 +247,7 @@ void NavigationObstacle3D::set_height(real_t p_height) {
height = p_height;
NavigationServer3D::get_singleton()->obstacle_set_height(obstacle, height);
NavigationServer3D::get_singleton()->agent_set_height(fake_agent, height);
#ifdef DEBUG_ENABLED
_update_static_obstacle_debug();
#endif // DEBUG_ENABLED
@ -267,7 +256,6 @@ void NavigationObstacle3D::set_height(real_t p_height) {
void NavigationObstacle3D::set_avoidance_layers(uint32_t p_layers) {
avoidance_layers = p_layers;
NavigationServer3D::get_singleton()->obstacle_set_avoidance_layers(obstacle, avoidance_layers);
NavigationServer3D::get_singleton()->agent_set_avoidance_layers(fake_agent, avoidance_layers);
}
uint32_t NavigationObstacle3D::get_avoidance_layers() const {
@ -292,6 +280,19 @@ bool NavigationObstacle3D::get_avoidance_layer_value(int p_layer_number) const {
return get_avoidance_layers() & (1 << (p_layer_number - 1));
}
void NavigationObstacle3D::set_avoidance_enabled(bool p_enabled) {
if (avoidance_enabled == p_enabled) {
return;
}
avoidance_enabled = p_enabled;
NavigationServer3D::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled);
}
bool NavigationObstacle3D::get_avoidance_enabled() const {
return avoidance_enabled;
}
void NavigationObstacle3D::set_use_3d_avoidance(bool p_use_3d_avoidance) {
use_3d_avoidance = p_use_3d_avoidance;
_update_use_3d_avoidance(use_3d_avoidance);
@ -304,27 +305,16 @@ void NavigationObstacle3D::set_velocity(const Vector3 p_velocity) {
}
void NavigationObstacle3D::_update_map(RID p_map) {
// avoidance obstacles are 2D only, no point keeping them on the map while 3D is used
if (use_3d_avoidance) {
NavigationServer3D::get_singleton()->obstacle_set_map(obstacle, RID());
} else {
NavigationServer3D::get_singleton()->obstacle_set_map(obstacle, p_map);
}
NavigationServer3D::get_singleton()->agent_set_map(fake_agent, p_map);
NavigationServer3D::get_singleton()->obstacle_set_map(obstacle, p_map);
map_current = p_map;
}
void NavigationObstacle3D::_update_position(const Vector3 p_position) {
if (vertices.size() > 0) {
NavigationServer3D::get_singleton()->obstacle_set_position(obstacle, p_position);
}
if (radius > 0.0) {
NavigationServer3D::get_singleton()->agent_set_position(fake_agent, p_position);
}
NavigationServer3D::get_singleton()->obstacle_set_position(obstacle, p_position);
}
void NavigationObstacle3D::_update_use_3d_avoidance(bool p_use_3d_avoidance) {
NavigationServer3D::get_singleton()->agent_set_use_3d_avoidance(fake_agent, use_3d_avoidance);
NavigationServer3D::get_singleton()->obstacle_set_use_3d_avoidance(obstacle, use_3d_avoidance);
_update_map(map_current);
}

View File

@ -46,7 +46,7 @@ class NavigationObstacle3D : public Node3D {
Vector<Vector3> vertices;
RID fake_agent;
bool avoidance_enabled = true;
uint32_t avoidance_layers = 1;
bool use_3d_avoidance = false;
@ -77,8 +77,10 @@ public:
NavigationObstacle3D();
virtual ~NavigationObstacle3D();
RID get_obstacle_rid() const { return obstacle; }
RID get_agent_rid() const { return fake_agent; }
RID get_rid() const { return obstacle; }
void set_avoidance_enabled(bool p_enabled);
bool get_avoidance_enabled() const;
void set_navigation_map(RID p_navigation_map);
RID get_navigation_map() const;

View File

@ -449,8 +449,12 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_set_avoidance_priority", "agent", "priority"), &NavigationServer2D::agent_set_avoidance_priority);
ClassDB::bind_method(D_METHOD("obstacle_create"), &NavigationServer2D::obstacle_create);
ClassDB::bind_method(D_METHOD("obstacle_set_avoidance_enabled", "obstacle", "enabled"), &NavigationServer2D::obstacle_set_avoidance_enabled);
ClassDB::bind_method(D_METHOD("obstacle_get_avoidance_enabled", "obstacle"), &NavigationServer2D::obstacle_get_avoidance_enabled);
ClassDB::bind_method(D_METHOD("obstacle_set_map", "obstacle", "map"), &NavigationServer2D::obstacle_set_map);
ClassDB::bind_method(D_METHOD("obstacle_get_map", "obstacle"), &NavigationServer2D::obstacle_get_map);
ClassDB::bind_method(D_METHOD("obstacle_set_radius", "obstacle", "radius"), &NavigationServer2D::obstacle_set_radius);
ClassDB::bind_method(D_METHOD("obstacle_set_velocity", "obstacle", "velocity"), &NavigationServer2D::obstacle_set_velocity);
ClassDB::bind_method(D_METHOD("obstacle_set_position", "obstacle", "position"), &NavigationServer2D::obstacle_set_position);
ClassDB::bind_method(D_METHOD("obstacle_set_vertices", "obstacle", "vertices"), &NavigationServer2D::obstacle_set_vertices);
ClassDB::bind_method(D_METHOD("obstacle_set_avoidance_layers", "obstacle", "layers"), &NavigationServer2D::obstacle_set_avoidance_layers);
@ -602,8 +606,12 @@ RID NavigationServer2D::obstacle_create() {
RID obstacle = NavigationServer3D::get_singleton()->obstacle_create();
return obstacle;
}
void FORWARD_2(obstacle_set_avoidance_enabled, RID, p_obstacle, bool, p_enabled, rid_to_rid, bool_to_bool);
bool FORWARD_1_C(obstacle_get_avoidance_enabled, RID, p_obstacle, rid_to_rid);
void FORWARD_2(obstacle_set_map, RID, p_obstacle, RID, p_map, rid_to_rid, rid_to_rid);
RID FORWARD_1_C(obstacle_get_map, RID, p_obstacle, rid_to_rid);
void FORWARD_2(obstacle_set_radius, RID, p_obstacle, real_t, p_radius, rid_to_rid, real_to_real);
void FORWARD_2(obstacle_set_velocity, RID, p_obstacle, Vector2, p_velocity, rid_to_rid, v2_to_v3);
void FORWARD_2(obstacle_set_position, RID, p_obstacle, Vector2, p_position, rid_to_rid, v2_to_v3);
void FORWARD_2(obstacle_set_avoidance_layers, RID, p_obstacle, uint32_t, p_layers, rid_to_rid, uint32_to_uint32);

View File

@ -240,8 +240,12 @@ public:
/// Creates the obstacle.
virtual RID obstacle_create();
virtual void obstacle_set_avoidance_enabled(RID p_obstacle, bool p_enabled);
virtual bool obstacle_get_avoidance_enabled(RID p_obstacle) const;
virtual void obstacle_set_map(RID p_obstacle, RID p_map);
virtual RID obstacle_get_map(RID p_obstacle) const;
virtual void obstacle_set_radius(RID p_obstacle, real_t p_radius);
virtual void obstacle_set_velocity(RID p_obstacle, Vector2 p_velocity);
virtual void obstacle_set_position(RID p_obstacle, Vector2 p_position);
virtual void obstacle_set_vertices(RID p_obstacle, const Vector<Vector2> &p_vertices);
virtual void obstacle_set_avoidance_layers(RID p_obstacle, uint32_t p_layers);

View File

@ -128,9 +128,15 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_set_avoidance_priority", "agent", "priority"), &NavigationServer3D::agent_set_avoidance_priority);
ClassDB::bind_method(D_METHOD("obstacle_create"), &NavigationServer3D::obstacle_create);
ClassDB::bind_method(D_METHOD("obstacle_set_avoidance_enabled", "obstacle", "enabled"), &NavigationServer3D::obstacle_set_avoidance_enabled);
ClassDB::bind_method(D_METHOD("obstacle_get_avoidance_enabled", "obstacle"), &NavigationServer3D::obstacle_get_avoidance_enabled);
ClassDB::bind_method(D_METHOD("obstacle_set_use_3d_avoidance", "obstacle", "enabled"), &NavigationServer3D::obstacle_set_use_3d_avoidance);
ClassDB::bind_method(D_METHOD("obstacle_get_use_3d_avoidance", "obstacle"), &NavigationServer3D::obstacle_get_use_3d_avoidance);
ClassDB::bind_method(D_METHOD("obstacle_set_map", "obstacle", "map"), &NavigationServer3D::obstacle_set_map);
ClassDB::bind_method(D_METHOD("obstacle_get_map", "obstacle"), &NavigationServer3D::obstacle_get_map);
ClassDB::bind_method(D_METHOD("obstacle_set_radius", "obstacle", "radius"), &NavigationServer3D::obstacle_set_radius);
ClassDB::bind_method(D_METHOD("obstacle_set_height", "obstacle", "height"), &NavigationServer3D::obstacle_set_height);
ClassDB::bind_method(D_METHOD("obstacle_set_velocity", "obstacle", "velocity"), &NavigationServer3D::obstacle_set_velocity);
ClassDB::bind_method(D_METHOD("obstacle_set_position", "obstacle", "position"), &NavigationServer3D::obstacle_set_position);
ClassDB::bind_method(D_METHOD("obstacle_set_vertices", "obstacle", "vertices"), &NavigationServer3D::obstacle_set_vertices);
ClassDB::bind_method(D_METHOD("obstacle_set_avoidance_layers", "obstacle", "layers"), &NavigationServer3D::obstacle_set_avoidance_layers);

View File

@ -260,7 +260,13 @@ public:
virtual RID obstacle_create() = 0;
virtual void obstacle_set_map(RID p_obstacle, RID p_map) = 0;
virtual RID obstacle_get_map(RID p_obstacle) const = 0;
virtual void obstacle_set_avoidance_enabled(RID p_obstacle, bool p_enabled) = 0;
virtual bool obstacle_get_avoidance_enabled(RID p_obstacle) const = 0;
virtual void obstacle_set_use_3d_avoidance(RID p_obstacle, bool p_enabled) = 0;
virtual bool obstacle_get_use_3d_avoidance(RID p_obstacle) const = 0;
virtual void obstacle_set_radius(RID p_obstacle, real_t p_radius) = 0;
virtual void obstacle_set_height(RID p_obstacle, real_t p_height) = 0;
virtual void obstacle_set_velocity(RID p_obstacle, Vector3 p_velocity) = 0;
virtual void obstacle_set_position(RID p_obstacle, Vector3 p_position) = 0;
virtual void obstacle_set_vertices(RID p_obstacle, const Vector<Vector3> &p_vertices) = 0;
virtual void obstacle_set_avoidance_layers(RID p_obstacle, uint32_t p_layers) = 0;

View File

@ -123,7 +123,13 @@ public:
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(); }
void obstacle_set_avoidance_enabled(RID p_obstacle, bool p_enabled) override {}
bool obstacle_get_avoidance_enabled(RID p_obstacle) const override { return false; }
void obstacle_set_use_3d_avoidance(RID p_obstacle, bool p_enabled) override {}
bool obstacle_get_use_3d_avoidance(RID p_obstacle) const override { return false; }
void obstacle_set_radius(RID p_obstacle, real_t p_radius) override {}
void obstacle_set_height(RID p_obstacle, real_t p_height) override {}
void obstacle_set_velocity(RID p_obstacle, Vector3 p_velocity) override {}
void obstacle_set_position(RID p_obstacle, Vector3 p_position) override {}
void obstacle_set_vertices(RID p_obstacle, const Vector<Vector3> &p_vertices) override {}
void obstacle_set_avoidance_layers(RID p_obstacle, uint32_t p_layers) override {}