Update navigation obstacle API

Updates navigation obstacle API.
This commit is contained in:
smix8
2023-06-10 15:16:04 +02:00
parent 66423d440e
commit c1fc331b88
18 changed files with 413 additions and 115 deletions

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