diff options
Diffstat (limited to 'scene/2d/physics_body_2d.cpp')
-rw-r--r-- | scene/2d/physics_body_2d.cpp | 85 |
1 files changed, 42 insertions, 43 deletions
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 8758ffef9f..66686f10a8 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -35,19 +35,6 @@ #include "engine.h" #include "math_funcs.h" #include "scene/scene_string_names.h" -void PhysicsBody2D::_notification(int p_what) { - - /* - switch(p_what) { - - case NOTIFICATION_TRANSFORM_CHANGED: { - - Physics2DServer::get_singleton()->body_set_state(get_rid(),Physics2DServer::BODY_STATE_TRANSFORM,get_global_transform()); - - } break; - } - */ -} void PhysicsBody2D::_set_layers(uint32_t p_mask) { @@ -436,7 +423,7 @@ bool RigidBody2D::_test_motion(const Vector2 &p_motion, bool p_infinite_inertia, Physics2DServer::MotionResult *r = NULL; if (p_result.is_valid()) r = p_result->get_result_ptr(); - return Physics2DServer::get_singleton()->body_test_motion(get_rid(), get_global_transform(), p_motion, p_infinite_inertia, p_margin, r); + return Physics2DServer::get_singleton()->body_test_motion(get_rid(), get_global_transform_with_canvas(), p_motion, p_infinite_inertia, p_margin, r); } void RigidBody2D::_direct_state_changed(Object *p_state) { @@ -449,7 +436,7 @@ void RigidBody2D::_direct_state_changed(Object *p_state) { set_block_transform_notify(true); // don't want notify (would feedback loop) if (mode != MODE_KINEMATIC) - set_global_transform(state->get_transform()); + set_global_transform(get_canvas_transform().affine_inverse() * state->get_transform()); linear_velocity = state->get_linear_velocity(); angular_velocity = state->get_angular_velocity(); if (sleeping != state->is_sleeping()) { @@ -1144,7 +1131,7 @@ bool KinematicBody2D::separate_raycast_shapes(bool p_infinite_inertia, Collision Physics2DServer::SeparationResult sep_res[8]; //max 8 rays - Transform2D gt = get_global_transform(); + Transform2D gt = get_global_transform_with_canvas(); Vector2 recover; int hits = Physics2DServer::get_singleton()->body_test_ray_separation(get_rid(), gt, p_infinite_inertia, recover, sep_res, 8, margin); @@ -1158,7 +1145,7 @@ bool KinematicBody2D::separate_raycast_shapes(bool p_infinite_inertia, Collision } gt.elements[2] += recover; - set_global_transform(gt); + set_global_transform(get_canvas_transform().affine_inverse() * gt); if (deepest != -1) { r_collision.collider = sep_res[deepest].collider_id; @@ -1179,7 +1166,7 @@ bool KinematicBody2D::separate_raycast_shapes(bool p_infinite_inertia, Collision bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only) { - Transform2D gt = get_global_transform(); + Transform2D gt = get_global_transform_with_canvas(); Physics2DServer::MotionResult result; bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, margin, &result, p_exclude_raycast_shapes); @@ -1198,7 +1185,7 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_ if (!p_test_only) { gt.elements[2] += result.motion; - set_global_transform(gt); + set_global_transform(get_canvas_transform().affine_inverse() * gt); } return colliding; @@ -1207,7 +1194,7 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_ //so, if you pass 45 as limit, avoid numerical precision erros when angle is 45. #define FLOOR_ANGLE_THRESHOLD 0.01 -Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, bool p_infinite_inertia, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) { +Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, bool p_infinite_inertia, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle) { Vector2 floor_motion = floor_velocity; if (on_floor && on_floor_body.is_valid()) { @@ -1228,6 +1215,8 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const colliders.clear(); floor_velocity = Vector2(); + Vector2 lv_n = p_linear_velocity.normalized(); + while (p_max_slides) { Collision collision; @@ -1254,8 +1243,10 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const if (collided) { + colliders.push_back(collision); motion = collision.remainder; + bool is_on_slope = false; if (p_floor_direction == Vector2()) { //all is a wall on_wall = true; @@ -1266,15 +1257,17 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const on_floor_body = collision.collider_rid; floor_velocity = collision.collider_vel; - Vector2 rel_v = lv - floor_velocity; - Vector2 hv = rel_v - p_floor_direction * p_floor_direction.dot(rel_v); - - if (collision.travel.length() < 1 && hv.length() < p_slope_stop_min_velocity) { - Transform2D gt = get_global_transform(); - gt.elements[2] -= collision.travel; - set_global_transform(gt); - return Vector2(); + if (p_stop_on_slope) { + if (Vector2() == lv_n + p_floor_direction) { + Transform2D gt = get_global_transform_with_canvas(); + gt.elements[2] -= collision.travel; + set_global_transform(get_canvas_transform().affine_inverse() * gt); + return Vector2(); + } } + + 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 { @@ -1282,12 +1275,18 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const } } - Vector2 n = collision.normal; - motion = motion.slide(n); - lv = lv.slide(n); - - colliders.push_back(collision); + if (p_stop_on_slope && is_on_slope) { + motion = motion.slide(p_floor_direction); + lv = lv.slide(p_floor_direction); + } else { + Vector2 n = collision.normal; + motion = motion.slide(n); + lv = lv.slide(n); + } } + + if (p_stop_on_slope) + break; } if (!found_collision) { @@ -1301,17 +1300,17 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const return lv; } -Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction, bool p_infinite_inertia, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) { +Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction, bool p_infinite_inertia, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle) { bool was_on_floor = on_floor; - Vector2 ret = move_and_slide(p_linear_velocity, p_floor_direction, p_infinite_inertia, p_slope_stop_min_velocity, p_max_slides, p_floor_max_angle); + Vector2 ret = move_and_slide(p_linear_velocity, p_floor_direction, p_infinite_inertia, p_stop_on_slope, p_max_slides, p_floor_max_angle); if (!was_on_floor || p_snap == Vector2()) { return ret; } Collision col; - Transform2D gt = get_global_transform(); + Transform2D gt = get_global_transform_with_canvas(); if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) { gt.elements[2] += col.travel; @@ -1320,7 +1319,7 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci on_floor_body = col.collider_rid; floor_velocity = col.collider_vel; } - set_global_transform(gt); + set_global_transform(get_canvas_transform().affine_inverse() * gt); } return ret; @@ -1417,30 +1416,30 @@ void KinematicBody2D::_direct_state_changed(Object *p_state) { last_valid_transform = state->get_transform(); set_notify_local_transform(false); - set_global_transform(last_valid_transform); + set_global_transform(get_canvas_transform().affine_inverse() * last_valid_transform); set_notify_local_transform(true); } void KinematicBody2D::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - last_valid_transform = get_global_transform(); + last_valid_transform = get_global_transform_with_canvas(); } if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { //used by sync to physics, send the new transform to the physics - Transform2D new_transform = get_global_transform(); + Transform2D new_transform = get_global_transform_with_canvas(); Physics2DServer::get_singleton()->body_set_state(get_rid(), Physics2DServer::BODY_STATE_TRANSFORM, new_transform); //but then revert changes set_notify_local_transform(false); - set_global_transform(last_valid_transform); + set_global_transform(get_canvas_transform().affine_inverse() * last_valid_transform); set_notify_local_transform(true); } } void KinematicBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody2D::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "infinite_inertia", "slope_stop_min_velocity", "max_bounces", "floor_max_angle"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(true), DEFVAL(5), DEFVAL(4), DEFVAL(Math::deg2rad((float)45))); - ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "floor_normal", "infinite_inertia", "slope_stop_min_velocity", "max_bounces", "floor_max_angle"), &KinematicBody2D::move_and_slide_with_snap, DEFVAL(Vector2(0, 0)), DEFVAL(true), DEFVAL(5), DEFVAL(4), DEFVAL(Math::deg2rad((float)45))); + ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "infinite_inertia", "stop_on_slope", "max_bounces", "floor_max_angle"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(true), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45))); + ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "floor_normal", "infinite_inertia", "stop_on_slope", "max_bounces", "floor_max_angle"), &KinematicBody2D::move_and_slide_with_snap, DEFVAL(Vector2(0, 0)), DEFVAL(true), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45))); ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody2D::test_move); |