summaryrefslogtreecommitdiff
path: root/scene/3d/physics_body.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/3d/physics_body.cpp')
-rw-r--r--scene/3d/physics_body.cpp406
1 files changed, 303 insertions, 103 deletions
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index 4b3a4add4a..bcfcf33e57 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -31,8 +31,11 @@
#include "physics_body.h"
#include "core/core_string_names.h"
-#include "engine.h"
-#include "method_bind_ext.gen.inc"
+#include "core/engine.h"
+#include "core/list.h"
+#include "core/method_bind_ext.gen.inc"
+#include "core/object.h"
+#include "core/rid.h"
#include "scene/scene_string_names.h"
#ifdef TOOLS_ENABLED
@@ -40,17 +43,6 @@
#endif
void PhysicsBody::_notification(int p_what) {
-
- /*
- switch(p_what) {
-
- case NOTIFICATION_TRANSFORM_CHANGED: {
-
- PhysicsServer::get_singleton()->body_set_state(get_rid(),PhysicsServer::BODY_STATE_TRANSFORM,get_global_transform());
-
- } break;
- }
- */
}
Vector3 PhysicsBody::get_linear_velocity() const {
@@ -119,6 +111,20 @@ bool PhysicsBody::get_collision_layer_bit(int p_bit) const {
return get_collision_layer() & (1 << p_bit);
}
+Array PhysicsBody::get_collision_exceptions() {
+ List<RID> exceptions;
+ PhysicsServer::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions);
+ Array ret;
+ for (List<RID>::Element *E = exceptions.front(); E; E = E->next()) {
+ RID body = E->get();
+ ObjectID instance_id = PhysicsServer::get_singleton()->body_get_object_instance_id(body);
+ Object *obj = ObjectDB::get_instance(instance_id);
+ PhysicsBody *physics_body = Object::cast_to<PhysicsBody>(obj);
+ ret.append(physics_body);
+ }
+ return ret;
+}
+
void PhysicsBody::add_collision_exception_with(Node *p_node) {
ERR_FAIL_NULL(p_node);
@@ -182,21 +188,25 @@ PhysicsBody::PhysicsBody(PhysicsServer::BodyMode p_mode) :
#ifndef DISABLE_DEPRECATED
void StaticBody::set_friction(real_t p_friction) {
- ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physical material")
+ if (p_friction == 1.0) { // default value, don't create an override for that
+ return;
+ }
+
+ ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.")
WARN_DEPRECATED
ERR_FAIL_COND(p_friction < 0 || p_friction > 1);
if (physics_material_override.is_null()) {
physics_material_override.instance();
+ set_physics_material_override(physics_material_override);
}
physics_material_override->set_friction(p_friction);
- _reload_physics_characteristics();
}
real_t StaticBody::get_friction() const {
- ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physical material")
+ ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physics material instead.")
WARN_DEPRECATED
if (physics_material_override.is_null()) {
@@ -208,21 +218,25 @@ real_t StaticBody::get_friction() const {
void StaticBody::set_bounce(real_t p_bounce) {
- ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physical material")
+ if (p_bounce == 0.0) { // default value, don't create an override for that
+ return;
+ }
+
+ ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.")
WARN_DEPRECATED
ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1);
if (physics_material_override.is_null()) {
physics_material_override.instance();
+ set_physics_material_override(physics_material_override);
}
physics_material_override->set_bounce(p_bounce);
- _reload_physics_characteristics();
}
real_t StaticBody::get_bounce() const {
- ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physical material")
+ ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.")
WARN_DEPRECATED
if (physics_material_override.is_null()) {
@@ -235,7 +249,8 @@ real_t StaticBody::get_bounce() const {
void StaticBody::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
if (physics_material_override.is_valid()) {
- physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics");
+ if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics"))
+ physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics");
}
physics_material_override = p_physics_material_override;
@@ -291,12 +306,13 @@ void StaticBody::_bind_methods() {
ClassDB::bind_method(D_METHOD("_reload_physics_characteristics"), &StaticBody::_reload_physics_characteristics);
+ ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody::get_collision_exceptions);
ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody::add_collision_exception_with);
ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &PhysicsBody::remove_collision_exception_with);
#ifndef DISABLE_DEPRECATED
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_friction", "get_friction");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_bounce", "get_bounce");
#endif // DISABLE_DEPRECATED
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
@@ -313,13 +329,9 @@ void StaticBody::_reload_physics_characteristics() {
if (physics_material_override.is_null()) {
PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, 0);
PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, 1);
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, PhysicsServer::COMBINE_MODE_INHERIT);
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, PhysicsServer::COMBINE_MODE_INHERIT);
} else {
- PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->get_bounce());
- PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->get_friction());
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->get_bounce_combine_mode());
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->get_friction_combine_mode());
+ PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
+ PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
}
}
@@ -421,7 +433,7 @@ void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_shape,
node->disconnect(SceneStringNames::get_singleton()->tree_entered, this, SceneStringNames::get_singleton()->_body_enter_tree);
node->disconnect(SceneStringNames::get_singleton()->tree_exiting, this, SceneStringNames::get_singleton()->_body_exit_tree);
if (in_tree)
- emit_signal(SceneStringNames::get_singleton()->body_exited, obj);
+ emit_signal(SceneStringNames::get_singleton()->body_exited, node);
}
contact_monitor->body_map.erase(E);
@@ -620,20 +632,26 @@ real_t RigidBody::get_weight() const {
#ifndef DISABLE_DEPRECATED
void RigidBody::set_friction(real_t p_friction) {
- ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physical material")
+ if (p_friction == 1.0) { // default value, don't create an override for that
+ return;
+ }
+
+ ERR_EXPLAIN("The method set_friction has been deprecated and will be removed in the future, use physics material instead.")
WARN_DEPRECATED
+
ERR_FAIL_COND(p_friction < 0 || p_friction > 1);
if (physics_material_override.is_null()) {
physics_material_override.instance();
+ set_physics_material_override(physics_material_override);
}
physics_material_override->set_friction(p_friction);
- _reload_physics_characteristics();
}
real_t RigidBody::get_friction() const {
- ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physical material")
+ ERR_EXPLAIN("The method get_friction has been deprecated and will be removed in the future, use physics material instead.")
WARN_DEPRECATED
+
if (physics_material_override.is_null()) {
return 1;
}
@@ -642,18 +660,24 @@ real_t RigidBody::get_friction() const {
}
void RigidBody::set_bounce(real_t p_bounce) {
- ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physical material")
+
+ if (p_bounce == 0.0) { // default value, don't create an override for that
+ return;
+ }
+
+ ERR_EXPLAIN("The method set_bounce has been deprecated and will be removed in the future, use physics material instead.")
WARN_DEPRECATED
+
ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1);
if (physics_material_override.is_null()) {
physics_material_override.instance();
+ set_physics_material_override(physics_material_override);
}
physics_material_override->set_bounce(p_bounce);
- _reload_physics_characteristics();
}
real_t RigidBody::get_bounce() const {
- ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physical material")
+ ERR_EXPLAIN("The method get_bounce has been deprecated and will be removed in the future, use physics material instead.")
WARN_DEPRECATED
if (physics_material_override.is_null()) {
return 0;
@@ -665,7 +689,8 @@ real_t RigidBody::get_bounce() const {
void RigidBody::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) {
if (physics_material_override.is_valid()) {
- physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics");
+ if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics"))
+ physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, this, "_reload_physics_characteristics");
}
physics_material_override = p_physics_material_override;
@@ -999,8 +1024,8 @@ void RigidBody::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "mass", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01"), "set_mass", "get_mass");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "weight", PROPERTY_HINT_EXP_RANGE, "0.01,65535,0.01", PROPERTY_USAGE_EDITOR), "set_weight", "get_weight");
#ifndef DISABLE_DEPRECATED
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_friction", "get_friction");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_bounce", "get_bounce");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "friction", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_friction", "get_friction");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce", PROPERTY_HINT_RANGE, "0,1,0.01", 0), "set_bounce", "get_bounce");
#endif // DISABLE_DEPRECATED
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "gravity_scale", PROPERTY_HINT_RANGE, "-128,128,0.01"), "set_gravity_scale", "get_gravity_scale");
@@ -1024,10 +1049,10 @@ void RigidBody::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_damp", PROPERTY_HINT_RANGE, "-1,128,0.01"), "set_angular_damp", "get_angular_damp");
- ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
- ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
- ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body")));
- ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body")));
+ ADD_SIGNAL(MethodInfo("body_shape_entered", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_shape_exited", PropertyInfo(Variant::INT, "body_id"), PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node"), PropertyInfo(Variant::INT, "body_shape"), PropertyInfo(Variant::INT, "local_shape")));
+ ADD_SIGNAL(MethodInfo("body_entered", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
+ ADD_SIGNAL(MethodInfo("body_exited", PropertyInfo(Variant::OBJECT, "body", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("sleeping_state_changed"));
BIND_ENUM_CONSTANT(MODE_RIGID);
@@ -1070,23 +1095,19 @@ void RigidBody::_reload_physics_characteristics() {
if (physics_material_override.is_null()) {
PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, 0);
PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, 1);
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, PhysicsServer::COMBINE_MODE_INHERIT);
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, PhysicsServer::COMBINE_MODE_INHERIT);
} else {
- PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->get_bounce());
- PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->get_friction());
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->get_bounce_combine_mode());
- PhysicsServer::get_singleton()->body_set_combine_mode(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->get_friction_combine_mode());
+ PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce());
+ PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->computed_friction());
}
}
//////////////////////////////////////////////////////
//////////////////////////
-Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion, bool p_infinite_inertia) {
+Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion, bool p_infinite_inertia, bool p_test_only) {
Collision col;
- if (move_and_collide(p_motion, p_infinite_inertia, col)) {
+ if (move_and_collide(p_motion, p_infinite_inertia, col, p_test_only)) {
if (motion_cache.is_null()) {
motion_cache.instance();
motion_cache->owner = this;
@@ -1100,7 +1121,7 @@ Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion, bool p_inf
return Ref<KinematicCollision>();
}
-bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision) {
+bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_test_only) {
Transform gt = get_global_transform();
PhysicsServer::MotionResult result;
@@ -1113,6 +1134,7 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_in
r_collision.collision = result.collision_point;
r_collision.normal = result.collision_normal;
r_collision.collider = result.collider_id;
+ r_collision.collider_rid = result.collider;
r_collision.travel = result.motion;
r_collision.remainder = result.remainder;
r_collision.local_shape = result.collision_local_shape;
@@ -1124,13 +1146,18 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_in
}
}
- gt.origin += result.motion;
- set_global_transform(gt);
+ if (!p_test_only) {
+ gt.origin += result.motion;
+ set_global_transform(gt);
+ }
return colliding;
}
-Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
+//so, if you pass 45 as limit, avoid numerical precision erros when angle is 45.
+#define FLOOR_ANGLE_THRESHOLD 0.01
+
+Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
Vector3 lv = p_linear_velocity;
@@ -1140,7 +1167,8 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
}
}
- Vector3 motion = (floor_velocity + lv) * get_physics_process_delta_time();
+ // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
+ Vector3 motion = (floor_velocity + lv) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time());
on_floor = false;
on_ceiling = false;
@@ -1148,69 +1176,127 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
colliders.clear();
floor_velocity = Vector3();
+ Vector3 lv_n = p_linear_velocity.normalized();
+
while (p_max_slides) {
Collision collision;
- bool collided = move_and_collide(motion, p_infinite_inertia, collision);
+ bool found_collision = false;
- if (collided) {
+ int test_type = 0;
- motion = collision.remainder;
-
- if (p_floor_direction == Vector3()) {
- //all is a wall
- on_wall = true;
+ do {
+ bool collided;
+ if (test_type == 0) { //collide
+ collided = move_and_collide(motion, p_infinite_inertia, collision);
+ if (!collided) {
+ motion = Vector3(); //clear because no collision happened and motion completed
+ }
} else {
- if (collision.normal.dot(p_floor_direction) >= Math::cos(p_floor_max_angle)) { //floor
+ collided = separate_raycast_shapes(p_infinite_inertia, collision);
+ if (collided) {
+ collision.remainder = motion; //keep
+ collision.travel = Vector3();
+ }
+ }
- on_floor = true;
- floor_velocity = collision.collider_vel;
+ if (collided) {
+ found_collision = true;
+ }
- Vector3 rel_v = lv - floor_velocity;
- Vector3 hv = rel_v - p_floor_direction * p_floor_direction.dot(rel_v);
+ if (collided) {
- if (collision.travel.length() < 0.05 && hv.length() < p_slope_stop_min_velocity) {
- Transform gt = get_global_transform();
- gt.origin -= collision.travel;
- set_global_transform(gt);
- return floor_velocity - p_floor_direction * p_floor_direction.dot(floor_velocity);
- }
- } else if (collision.normal.dot(-p_floor_direction) >= Math::cos(p_floor_max_angle)) { //ceiling
- on_ceiling = true;
- } else {
+ colliders.push_back(collision);
+ motion = collision.remainder;
+
+ bool is_on_slope = false;
+ if (p_floor_direction == Vector3()) {
+ //all is a wall
on_wall = true;
+ } else {
+ if (collision.normal.dot(p_floor_direction) >= Math::cos(p_floor_max_angle + FLOOR_ANGLE_THRESHOLD)) { //floor
+
+ on_floor = true;
+ on_floor_body = collision.collider_rid;
+ floor_velocity = collision.collider_vel;
+
+ if (p_stop_on_slope) {
+ if (Vector3() == lv_n + p_floor_direction) {
+ Transform gt = get_global_transform();
+ gt.origin -= collision.travel;
+ set_global_transform(gt);
+ return Vector3();
+ }
+ }
+
+ is_on_slope = true;
+
+ } else if (collision.normal.dot(-p_floor_direction) >= Math::cos(p_floor_max_angle + FLOOR_ANGLE_THRESHOLD)) { //ceiling
+ on_ceiling = true;
+ } else {
+ on_wall = true;
+ }
}
- }
- Vector3 n = collision.normal;
- motion = motion.slide(n);
- lv = lv.slide(n);
+ if (p_stop_on_slope && is_on_slope) {
+ motion = motion.slide(p_floor_direction);
+ lv = lv.slide(p_floor_direction);
+ } else {
+ Vector3 n = collision.normal;
+ motion = motion.slide(n);
+ lv = lv.slide(n);
+ }
- for (int i = 0; i < 3; i++) {
- if (locked_axis & (1 << i)) {
- lv[i] = 0;
+ for (int i = 0; i < 3; i++) {
+ if (locked_axis & (1 << i)) {
+ lv[i] = 0;
+ }
}
}
- colliders.push_back(collision);
+ ++test_type;
+ } while (!p_stop_on_slope && test_type < 2);
- } else {
+ if (!found_collision || motion == Vector3())
break;
- }
- p_max_slides--;
- if (motion == Vector3())
- break;
+ --p_max_slides;
}
return lv;
}
+Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
+
+ bool was_on_floor = on_floor;
+
+ Vector3 ret = move_and_slide(p_linear_velocity, p_floor_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia);
+ if (!was_on_floor || p_snap == Vector3()) {
+ return ret;
+ }
+
+ Collision col;
+ Transform gt = get_global_transform();
+
+ if (move_and_collide(p_snap, p_infinite_inertia, col, true)) {
+ gt.origin += col.travel;
+ if (p_floor_direction != Vector3() && Math::acos(p_floor_direction.normalized().dot(col.normal)) < p_floor_max_angle) {
+ on_floor = true;
+ on_floor_body = col.collider_rid;
+ floor_velocity = col.collider_vel;
+ }
+ set_global_transform(gt);
+ }
+
+ return ret;
+}
+
bool KinematicBody::is_on_floor() const {
return on_floor;
}
+
bool KinematicBody::is_on_wall() const {
return on_wall;
@@ -1232,6 +1318,43 @@ bool KinematicBody::test_move(const Transform &p_from, const Vector3 &p_motion,
return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia);
}
+bool KinematicBody::separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision) {
+
+ PhysicsServer::SeparationResult sep_res[8]; //max 8 rays
+
+ Transform gt = get_global_transform();
+
+ Vector3 recover;
+ int hits = PhysicsServer::get_singleton()->body_test_ray_separation(get_rid(), gt, p_infinite_inertia, recover, sep_res, 8, margin);
+ int deepest = -1;
+ float deepest_depth;
+ for (int i = 0; i < hits; i++) {
+ if (deepest == -1 || sep_res[i].collision_depth > deepest_depth) {
+ deepest = i;
+ deepest_depth = sep_res[i].collision_depth;
+ }
+ }
+
+ gt.origin += recover;
+ set_global_transform(gt);
+
+ if (deepest != -1) {
+ r_collision.collider = sep_res[deepest].collider_id;
+ r_collision.collider_metadata = sep_res[deepest].collider_metadata;
+ r_collision.collider_shape = sep_res[deepest].collider_shape;
+ r_collision.collider_vel = sep_res[deepest].collider_velocity;
+ r_collision.collision = sep_res[deepest].collision_point;
+ r_collision.normal = sep_res[deepest].collision_normal;
+ r_collision.local_shape = sep_res[deepest].collision_local_shape;
+ r_collision.travel = recover;
+ r_collision.remainder = Vector3();
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
void KinematicBody::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock) {
PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock);
}
@@ -1278,10 +1401,11 @@ Ref<KinematicCollision> KinematicBody::_get_slide_collision(int p_bounce) {
void KinematicBody::_bind_methods() {
- ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia"), &KinematicBody::_move, DEFVAL(true));
- ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "slope_stop_min_velocity", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(0.05), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "test_only"), &KinematicBody::_move, DEFVAL(true), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true));
- ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody::test_move);
+ ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody::test_move, DEFVAL(true));
ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody::is_on_floor);
ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody::is_on_ceiling);
@@ -1297,13 +1421,9 @@ void KinematicBody::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_slide_count"), &KinematicBody::get_slide_count);
ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &KinematicBody::_get_slide_collision);
- ADD_GROUP("Axis Lock", "axis_lock_");
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_x"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_X);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_y"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Y);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Z);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_x"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_X);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_y"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Y);
- ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Z);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_x", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_X);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_y", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Y);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_z", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Z);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
}
@@ -1787,6 +1907,26 @@ bool PhysicalBone::SixDOFJointData::_set(const StringName &p_name, const Variant
if (j.is_valid())
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, axis_data[axis].linear_limit_softness);
+ } else if ("linear_spring_enabled" == var_name) {
+ axis_data[axis].linear_spring_enabled = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, axis_data[axis].linear_spring_enabled);
+
+ } else if ("linear_spring_stiffness" == var_name) {
+ axis_data[axis].linear_spring_stiffness = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, axis_data[axis].linear_spring_stiffness);
+
+ } else if ("linear_spring_damping" == var_name) {
+ axis_data[axis].linear_spring_damping = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, axis_data[axis].linear_spring_damping);
+
+ } else if ("linear_equilibrium_point" == var_name) {
+ axis_data[axis].linear_equilibrium_point = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].linear_equilibrium_point);
+
} else if ("linear_restitution" == var_name) {
axis_data[axis].linear_restitution = p_value;
if (j.is_valid())
@@ -1832,6 +1972,26 @@ bool PhysicalBone::SixDOFJointData::_set(const StringName &p_name, const Variant
if (j.is_valid())
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, axis_data[axis].erp);
+ } else if ("angular_spring_enabled" == var_name) {
+ axis_data[axis].angular_spring_enabled = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, axis_data[axis].angular_spring_enabled);
+
+ } else if ("angular_spring_stiffness" == var_name) {
+ axis_data[axis].angular_spring_stiffness = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, axis_data[axis].angular_spring_stiffness);
+
+ } else if ("angular_spring_damping" == var_name) {
+ axis_data[axis].angular_spring_damping = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, axis_data[axis].angular_spring_damping);
+
+ } else if ("angular_equilibrium_point" == var_name) {
+ axis_data[axis].angular_equilibrium_point = p_value;
+ if (j.is_valid())
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].angular_equilibrium_point);
+
} else {
return false;
}
@@ -1870,6 +2030,14 @@ bool PhysicalBone::SixDOFJointData::_get(const StringName &p_name, Variant &r_re
r_ret = axis_data[axis].linear_limit_lower;
} else if ("linear_limit_softness" == var_name) {
r_ret = axis_data[axis].linear_limit_softness;
+ } else if ("linear_spring_enabled" == var_name) {
+ r_ret = axis_data[axis].linear_spring_enabled;
+ } else if ("linear_spring_stiffness" == var_name) {
+ r_ret = axis_data[axis].linear_spring_stiffness;
+ } else if ("linear_spring_damping" == var_name) {
+ r_ret = axis_data[axis].linear_spring_damping;
+ } else if ("linear_equilibrium_point" == var_name) {
+ r_ret = axis_data[axis].linear_equilibrium_point;
} else if ("linear_restitution" == var_name) {
r_ret = axis_data[axis].linear_restitution;
} else if ("linear_damping" == var_name) {
@@ -1888,6 +2056,14 @@ bool PhysicalBone::SixDOFJointData::_get(const StringName &p_name, Variant &r_re
r_ret = axis_data[axis].angular_damping;
} else if ("erp" == var_name) {
r_ret = axis_data[axis].erp;
+ } else if ("angular_spring_enabled" == var_name) {
+ r_ret = axis_data[axis].angular_spring_enabled;
+ } else if ("angular_spring_stiffness" == var_name) {
+ r_ret = axis_data[axis].angular_spring_stiffness;
+ } else if ("angular_spring_damping" == var_name) {
+ r_ret = axis_data[axis].angular_spring_damping;
+ } else if ("angular_equilibrium_point" == var_name) {
+ r_ret = axis_data[axis].angular_equilibrium_point;
} else {
return false;
}
@@ -1902,6 +2078,10 @@ void PhysicalBone::SixDOFJointData::_get_property_list(List<PropertyInfo> *p_lis
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_limit_upper"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_limit_lower"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_limit_softness", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/linear_spring_enabled"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_spring_stiffness"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_spring_damping"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_equilibrium_point"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/linear_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/angular_limit_enabled"));
@@ -1911,6 +2091,10 @@ void PhysicalBone::SixDOFJointData::_get_property_list(List<PropertyInfo> *p_lis
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_restitution", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_damping", PROPERTY_HINT_RANGE, "0.01,16,0.01"));
p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/erp"));
+ p_list->push_back(PropertyInfo(Variant::BOOL, "joint_constraints/" + axis_names[i] + "/angular_spring_enabled"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_spring_stiffness"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_spring_damping"));
+ p_list->push_back(PropertyInfo(Variant::REAL, "joint_constraints/" + axis_names[i] + "/angular_equilibrium_point"));
}
}
@@ -2044,6 +2228,8 @@ void PhysicalBone::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_simulating_physics"), &PhysicalBone::is_simulating_physics);
+ ClassDB::bind_method(D_METHOD("get_bone_id"), &PhysicalBone::get_bone_id);
+
ClassDB::bind_method(D_METHOD("set_mass", "mass"), &PhysicalBone::set_mass);
ClassDB::bind_method(D_METHOD("get_mass"), &PhysicalBone::get_mass);
@@ -2172,6 +2358,10 @@ void PhysicalBone::_reload_joint() {
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT, g6dofjd->axis_data[axis].linear_limit_upper);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT, g6dofjd->axis_data[axis].linear_limit_lower);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].linear_limit_softness);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, g6dofjd->axis_data[axis].linear_spring_enabled);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].linear_spring_stiffness);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, g6dofjd->axis_data[axis].linear_spring_damping);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].linear_equilibrium_point);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION, g6dofjd->axis_data[axis].linear_restitution);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING, g6dofjd->axis_data[axis].linear_damping);
PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, g6dofjd->axis_data[axis].angular_limit_enabled);
@@ -2181,9 +2371,15 @@ void PhysicalBone::_reload_joint() {
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION, g6dofjd->axis_data[axis].angular_restitution);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING, g6dofjd->axis_data[axis].angular_damping);
PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, g6dofjd->axis_data[axis].erp);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, g6dofjd->axis_data[axis].angular_spring_enabled);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].angular_spring_stiffness);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, g6dofjd->axis_data[axis].angular_spring_damping);
+ PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast<Vector3::Axis>(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].angular_equilibrium_point);
}
} break;
+ case JOINT_TYPE_NONE: {
+ } break;
}
}
@@ -2221,7 +2417,8 @@ void PhysicalBone::set_joint_type(JointType p_joint_type) {
if (p_joint_type == get_joint_type())
return;
- memdelete(joint_data);
+ if (joint_data)
+ memdelete(joint_data);
joint_data = NULL;
switch (p_joint_type) {
case JOINT_TYPE_PIN:
@@ -2239,6 +2436,8 @@ void PhysicalBone::set_joint_type(JointType p_joint_type) {
case JOINT_TYPE_6DOF:
joint_data = memnew(SixDOFJointData);
break;
+ case JOINT_TYPE_NONE:
+ break;
}
_reload_joint();
@@ -2402,12 +2601,12 @@ PhysicalBone::PhysicalBone() :
gizmo_move_joint(false),
#endif
joint_data(NULL),
+ parent_skeleton(NULL),
static_body(false),
- simulate_physics(false),
_internal_static_body(false),
+ simulate_physics(false),
_internal_simulate_physics(false),
bone_id(-1),
- parent_skeleton(NULL),
bone_name(""),
bounce(0),
mass(1),
@@ -2419,7 +2618,8 @@ PhysicalBone::PhysicalBone() :
}
PhysicalBone::~PhysicalBone() {
- memdelete(joint_data);
+ if (joint_data)
+ memdelete(joint_data);
}
void PhysicalBone::update_bone_id() {