|
@@ -35,19 +35,41 @@
|
|
#include "servers/navigation_server_3d.h"
|
|
#include "servers/navigation_server_3d.h"
|
|
|
|
|
|
void NavigationObstacle3D::_bind_methods() {
|
|
void NavigationObstacle3D::_bind_methods() {
|
|
|
|
+ ClassDB::bind_method(D_METHOD("set_estimate_radius", "estimate_radius"), &NavigationObstacle3D::set_estimate_radius);
|
|
|
|
+ ClassDB::bind_method(D_METHOD("is_radius_estimated"), &NavigationObstacle3D::is_radius_estimated);
|
|
|
|
+ ClassDB::bind_method(D_METHOD("set_radius", "radius"), &NavigationObstacle3D::set_radius);
|
|
|
|
+ ClassDB::bind_method(D_METHOD("get_radius"), &NavigationObstacle3D::get_radius);
|
|
|
|
+
|
|
|
|
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "estimate_radius"), "set_estimate_radius", "is_radius_estimated");
|
|
|
|
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "radius", PROPERTY_HINT_RANGE, "0.01,100,0.01"), "set_radius", "get_radius");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void NavigationObstacle3D::_validate_property(PropertyInfo &p_property) const {
|
|
|
|
+ if (p_property.name == "radius") {
|
|
|
|
+ if (estimate_radius) {
|
|
|
|
+ p_property.usage = PROPERTY_USAGE_NOEDITOR;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
void NavigationObstacle3D::_notification(int p_what) {
|
|
void NavigationObstacle3D::_notification(int p_what) {
|
|
switch (p_what) {
|
|
switch (p_what) {
|
|
case NOTIFICATION_READY: {
|
|
case NOTIFICATION_READY: {
|
|
|
|
+ initialize_agent();
|
|
|
|
+ parent_node3d = Object::cast_to<Node3D>(get_parent());
|
|
|
|
+ if (parent_node3d != nullptr) {
|
|
|
|
+ // place agent on navigation map first or else the RVO agent callback creation fails silently later
|
|
|
|
+ NavigationServer3D::get_singleton()->agent_set_map(get_rid(), parent_node3d->get_world_3d()->get_navigation_map());
|
|
|
|
+ }
|
|
set_physics_process_internal(true);
|
|
set_physics_process_internal(true);
|
|
} break;
|
|
} break;
|
|
case NOTIFICATION_EXIT_TREE: {
|
|
case NOTIFICATION_EXIT_TREE: {
|
|
|
|
+ parent_node3d = nullptr;
|
|
set_physics_process_internal(false);
|
|
set_physics_process_internal(false);
|
|
} break;
|
|
} break;
|
|
case NOTIFICATION_PARENTED: {
|
|
case NOTIFICATION_PARENTED: {
|
|
parent_node3d = Object::cast_to<Node3D>(get_parent());
|
|
parent_node3d = Object::cast_to<Node3D>(get_parent());
|
|
- update_agent_shape();
|
|
|
|
|
|
+ reevaluate_agent_radius();
|
|
} break;
|
|
} break;
|
|
case NOTIFICATION_UNPARENTED: {
|
|
case NOTIFICATION_UNPARENTED: {
|
|
parent_node3d = nullptr;
|
|
parent_node3d = nullptr;
|
|
@@ -86,7 +108,22 @@ TypedArray<String> NavigationObstacle3D::get_configuration_warnings() const {
|
|
return warnings;
|
|
return warnings;
|
|
}
|
|
}
|
|
|
|
|
|
-void NavigationObstacle3D::update_agent_shape() {
|
|
|
|
|
|
+void NavigationObstacle3D::initialize_agent() {
|
|
|
|
+ NavigationServer3D::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
|
|
|
|
+ NavigationServer3D::get_singleton()->agent_set_max_neighbors(agent, 0);
|
|
|
|
+ NavigationServer3D::get_singleton()->agent_set_time_horizon(agent, 0.0);
|
|
|
|
+ NavigationServer3D::get_singleton()->agent_set_max_speed(agent, 0.0);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void NavigationObstacle3D::reevaluate_agent_radius() {
|
|
|
|
+ if (!estimate_radius) {
|
|
|
|
+ NavigationServer3D::get_singleton()->agent_set_radius(agent, radius);
|
|
|
|
+ } else if (parent_node3d) {
|
|
|
|
+ NavigationServer3D::get_singleton()->agent_set_radius(agent, estimate_agent_radius());
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+real_t NavigationObstacle3D::estimate_agent_radius() const {
|
|
if (parent_node3d) {
|
|
if (parent_node3d) {
|
|
// Estimate the radius of this physics body
|
|
// Estimate the radius of this physics body
|
|
real_t radius = 0.0;
|
|
real_t radius = 0.0;
|
|
@@ -110,15 +147,21 @@ void NavigationObstacle3D::update_agent_shape() {
|
|
Vector3 s = parent_node3d->get_global_transform().basis.get_scale();
|
|
Vector3 s = parent_node3d->get_global_transform().basis.get_scale();
|
|
radius *= MAX(s.x, MAX(s.y, s.z));
|
|
radius *= MAX(s.x, MAX(s.y, s.z));
|
|
|
|
|
|
- if (radius == 0.0) {
|
|
|
|
- radius = 1.0; // Never a 0 radius
|
|
|
|
|
|
+ if (radius > 0.0) {
|
|
|
|
+ return radius;
|
|
}
|
|
}
|
|
-
|
|
|
|
- // Initialize the Agent as an object
|
|
|
|
- NavigationServer3D::get_singleton()->agent_set_neighbor_dist(agent, 0.0);
|
|
|
|
- NavigationServer3D::get_singleton()->agent_set_max_neighbors(agent, 0);
|
|
|
|
- NavigationServer3D::get_singleton()->agent_set_time_horizon(agent, 0.0);
|
|
|
|
- NavigationServer3D::get_singleton()->agent_set_radius(agent, radius);
|
|
|
|
- NavigationServer3D::get_singleton()->agent_set_max_speed(agent, 0.0);
|
|
|
|
}
|
|
}
|
|
|
|
+ return 1.0; // Never a 0 radius
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void NavigationObstacle3D::set_estimate_radius(bool p_estimate_radius) {
|
|
|
|
+ estimate_radius = p_estimate_radius;
|
|
|
|
+ notify_property_list_changed();
|
|
|
|
+ reevaluate_agent_radius();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void NavigationObstacle3D::set_radius(real_t p_radius) {
|
|
|
|
+ ERR_FAIL_COND_MSG(p_radius <= 0.0, "Radius must be greater than 0.");
|
|
|
|
+ radius = p_radius;
|
|
|
|
+ reevaluate_agent_radius();
|
|
}
|
|
}
|