diff options
Diffstat (limited to 'scene/2d/physics_body_2d.cpp')
-rw-r--r-- | scene/2d/physics_body_2d.cpp | 430 |
1 files changed, 278 insertions, 152 deletions
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 9b4da2a77a..d52c293763 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -30,17 +30,12 @@ #include "physics_body_2d.h" -#include "core/config/engine.h" #include "core/core_string_names.h" -#include "core/math/math_funcs.h" -#include "core/object/class_db.h" -#include "core/templates/list.h" -#include "core/templates/rid.h" #include "scene/scene_string_names.h" void PhysicsBody2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only", "safe_margin"), &PhysicsBody2D::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false), DEFVAL(0.08)); - ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "collision", "safe_margin"), &PhysicsBody2D::test_move, DEFVAL(true), DEFVAL(true), DEFVAL(Variant()), DEFVAL(0.08)); + ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "test_only", "safe_margin"), &PhysicsBody2D::_move, DEFVAL(false), DEFVAL(0.08)); + ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "collision", "safe_margin"), &PhysicsBody2D::test_move, DEFVAL(Variant()), DEFVAL(0.08)); ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &PhysicsBody2D::get_collision_exceptions); ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &PhysicsBody2D::add_collision_exception_with); @@ -59,29 +54,28 @@ PhysicsBody2D::~PhysicsBody2D() { } } -Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, bool p_test_only, real_t p_margin) { +Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_motion, bool p_test_only, real_t p_margin) { PhysicsServer2D::MotionResult result; - if (move_and_collide(p_motion, p_infinite_inertia, result, p_margin, p_exclude_raycast_shapes, p_test_only)) { + if (move_and_collide(p_motion, result, p_margin, p_test_only)) { if (motion_cache.is_null()) { motion_cache.instantiate(); motion_cache->owner = this; } motion_cache->result = result; - return motion_cache; } return Ref<KinematicCollision2D>(); } -bool PhysicsBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, PhysicsServer2D::MotionResult &r_result, real_t p_margin, bool p_exclude_raycast_shapes, bool p_test_only, bool p_cancel_sliding, const Set<RID> &p_exclude) { +bool PhysicsBody2D::move_and_collide(const Vector2 &p_motion, PhysicsServer2D::MotionResult &r_result, real_t p_margin, bool p_test_only, bool p_cancel_sliding, const Set<RID> &p_exclude) { if (is_only_update_transform_changes_enabled()) { ERR_PRINT("Move functions do not work together with 'sync to physics' option. Please read the documentation."); } Transform2D gt = get_global_transform(); - bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, p_margin, &r_result, p_exclude_raycast_shapes, p_exclude); + bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_margin, &r_result, p_exclude); // Restore direction of motion to be along original motion, // in order to avoid sliding due to recovery, @@ -129,7 +123,7 @@ bool PhysicsBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_in return colliding; } -bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, const Ref<KinematicCollision2D> &r_collision, real_t p_margin) { +bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion, const Ref<KinematicCollision2D> &r_collision, real_t p_margin) { ERR_FAIL_COND_V(!is_inside_tree(), false); PhysicsServer2D::MotionResult *r = nullptr; @@ -138,7 +132,7 @@ bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion r = const_cast<PhysicsServer2D::MotionResult *>(&r_collision->result); } - return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia, p_margin, r, p_exclude_raycast_shapes); + return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_margin, r); } TypedArray<PhysicsBody2D> PhysicsBody2D::get_collision_exceptions() { @@ -1046,137 +1040,230 @@ void RigidBody2D::_reload_physics_characteristics() { ////////////////////////// -//so, if you pass 45 as limit, avoid numerical precision errors when angle is 45. +// So, if you pass 45 as limit, avoid numerical precision errors when angle is 45. #define FLOOR_ANGLE_THRESHOLD 0.01 void CharacterBody2D::move_and_slide() { - Vector2 body_velocity_normal = linear_velocity.normalized(); - bool was_on_floor = on_floor; - - // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky + // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky. float delta = Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time(); - Vector2 current_floor_velocity = floor_velocity; - - if ((on_floor || on_wall) && on_floor_body.is_valid()) { - //this approach makes sure there is less delay between the actual body velocity and the one we saved - PhysicsDirectBodyState2D *bs = PhysicsServer2D::get_singleton()->body_get_direct_state(on_floor_body); - if (bs) { - current_floor_velocity = bs->get_linear_velocity(); + Vector2 current_platform_velocity = platform_velocity; + + if ((on_floor || on_wall) && platform_rid.is_valid()) { + bool excluded = (exclude_body_layers & platform_layer) != 0; + if (!excluded) { + // This approach makes sure there is less delay between the actual body velocity and the one we saved. + PhysicsDirectBodyState2D *bs = PhysicsServer2D::get_singleton()->body_get_direct_state(platform_rid); + if (bs) { + Transform2D gt = get_global_transform(); + Vector2 local_position = gt.elements[2] - bs->get_transform().elements[2]; + current_platform_velocity = bs->get_velocity_at_local_position(local_position); + } + } else { + current_platform_velocity = Vector2(); } } motion_results.clear(); + + bool was_on_floor = on_floor; on_floor = false; on_ceiling = false; on_wall = false; - floor_normal = Vector2(); - floor_velocity = Vector2(); - if (current_floor_velocity != Vector2()) { + if (!current_platform_velocity.is_equal_approx(Vector2())) { PhysicsServer2D::MotionResult floor_result; Set<RID> exclude; - exclude.insert(on_floor_body); - if (move_and_collide(current_floor_velocity * delta, infinite_inertia, floor_result, true, false, false, false, exclude)) { + exclude.insert(platform_rid); + if (move_and_collide(current_platform_velocity * delta, floor_result, margin, false, false, exclude)) { motion_results.push_back(floor_result); _set_collision_direction(floor_result); } } - on_floor_body = RID(); Vector2 motion = linear_velocity * delta; + Vector2 motion_slide_up = motion.slide(up_direction); + + Vector2 prev_platform_velocity = current_platform_velocity; + Vector2 prev_floor_normal = floor_normal; + RID prev_platform_rid = platform_rid; + int prev_platform_layer = platform_layer; + + platform_rid = RID(); + floor_normal = Vector2(); + platform_velocity = Vector2(); // No sliding on first attempt to keep floor motion stable when possible, - // when stop on slope is enabled. - bool sliding_enabled = !stop_on_slope; + // When stop on slope is enabled or when there is no up direction. + bool sliding_enabled = !stop_on_slope || up_direction == Vector2(); + // Constant speed can be applied only the first time sliding is enabled. + bool can_apply_constant_speed = sliding_enabled; + bool first_slide = true; + bool vel_dir_facing_up = linear_velocity.dot(up_direction) > 0; + Vector2 last_travel; for (int iteration = 0; iteration < max_slides; ++iteration) { PhysicsServer2D::MotionResult result; bool found_collision = false; - for (int i = 0; i < 2; ++i) { - bool collided; - if (i == 0) { //collide - collided = move_and_collide(motion, infinite_inertia, result, margin, true, false, !sliding_enabled); - if (!collided) { - motion = Vector2(); //clear because no collision happened and motion completed - } - } else { //separate raycasts (if any) - collided = separate_raycast_shapes(result); - if (collided) { - result.remainder = motion; //keep - result.motion = Vector2(); + Vector2 prev_position = get_global_transform().elements[2]; + + bool collided = move_and_collide(motion, result, margin, false, !sliding_enabled); + + if (collided) { + found_collision = true; + motion_results.push_back(result); + _set_collision_direction(result); + + if (on_floor && stop_on_slope && (linear_velocity.normalized() + up_direction).length() < 0.01) { + Transform2D gt = get_global_transform(); + if (result.motion.length() > margin) { + gt.elements[2] -= result.motion.slide(up_direction); + } else { + gt.elements[2] -= result.motion; } + set_global_transform(gt); + linear_velocity = Vector2(); + motion = Vector2(); + break; } - if (collided) { - found_collision = true; - - motion_results.push_back(result); - _set_collision_direction(result); + if (result.remainder.is_equal_approx(Vector2())) { + motion = Vector2(); + break; + } - if (on_floor && stop_on_slope) { - if ((body_velocity_normal + up_direction).length() < 0.01) { + // Move on floor only checks. + if (move_on_floor_only && on_wall && motion_slide_up.dot(result.collision_normal) <= 0) { + // Avoid to move forward on a wall if move_on_floor_only is true. + if (was_on_floor && !is_on_floor_only() && !vel_dir_facing_up) { + // If the movement is large the body can be prevented from reaching the walls. + if (result.motion.length() <= margin) { + // Cancels the motion. Transform2D gt = get_global_transform(); - if (result.motion.length() > margin) { - gt.elements[2] -= result.motion.slide(up_direction); - } else { - gt.elements[2] -= result.motion; - } + gt.elements[2] -= result.motion; set_global_transform(gt); - linear_velocity = Vector2(); - return; } + on_floor = true; + platform_rid = prev_platform_rid; + platform_layer = prev_platform_layer; + + platform_velocity = prev_platform_velocity; + floor_normal = prev_floor_normal; + linear_velocity = Vector2(); + motion = Vector2(); + break; } - - if (sliding_enabled || !on_floor) { - motion = result.remainder.slide(result.collision_normal); - linear_velocity = linear_velocity.slide(result.collision_normal); + // Prevents the body from being able to climb a slope when it moves forward against the wall. + else if (!is_on_floor_only()) { + motion = up_direction * up_direction.dot(result.remainder); + motion = motion.slide(result.collision_normal); } else { motion = result.remainder; } } + // Constant Speed when the slope is upward. + else if (constant_speed_on_floor && is_on_floor_only() && can_apply_constant_speed && was_on_floor && motion.dot(result.collision_normal) < 0) { + can_apply_constant_speed = false; + Vector2 motion_slide_norm = result.remainder.slide(result.collision_normal).normalized(); + if (!motion_slide_norm.is_equal_approx(Vector2())) { + motion = motion_slide_norm * (motion_slide_up.length() - result.motion.slide(up_direction).length() - last_travel.slide(up_direction).length()); + } + } + // Regular sliding, the last part of the test handle the case when you don't want to slide on the ceiling. + else if ((sliding_enabled || !on_floor) && (!on_ceiling || slide_on_ceiling || !vel_dir_facing_up)) { + Vector2 slide_motion = result.remainder.slide(result.collision_normal); + if (slide_motion.dot(linear_velocity) > 0.0) { + motion = slide_motion; + } else { + motion = Vector2(); + } + if (slide_on_ceiling && on_ceiling) { + // Apply slide only in the direction of the input motion, otherwise just stop to avoid jittering when moving against a wall. + if (vel_dir_facing_up) { + linear_velocity = linear_velocity.slide(result.collision_normal); + } else { + // Avoid acceleration in slope when falling. + linear_velocity = up_direction * up_direction.dot(linear_velocity); + } + } + } + // No sliding on first attempt to keep floor motion stable when possible. + else { + motion = result.remainder; + if (on_ceiling && !slide_on_ceiling && vel_dir_facing_up) { + linear_velocity = linear_velocity.slide(up_direction); + motion = motion.slide(up_direction); + } + } + last_travel = result.motion; + } + // When you move forward in a downward slope you don’t collide because you will be in the air. + // This test ensures that constant speed is applied, only if the player is still on the ground after the snap is applied. + else if (constant_speed_on_floor && first_slide && _on_floor_if_snapped(was_on_floor, vel_dir_facing_up)) { + can_apply_constant_speed = false; sliding_enabled = true; + Transform2D gt = get_global_transform(); + gt.elements[2] = prev_position; + set_global_transform(gt); + + Vector2 motion_slide_norm = motion.slide(prev_floor_normal).normalized(); + if (!motion_slide_norm.is_equal_approx(Vector2())) { + motion = motion_slide_norm * (motion_slide_up.length()); + found_collision = true; + } } - if (!found_collision || motion == Vector2()) { + can_apply_constant_speed = !can_apply_constant_speed && !sliding_enabled; + sliding_enabled = true; + first_slide = false; + + if (!found_collision || motion.is_equal_approx(Vector2())) { break; } } + _snap_on_floor(was_on_floor, vel_dir_facing_up); + if (!on_floor && !on_wall) { // Add last platform velocity when just left a moving platform. - linear_velocity += current_floor_velocity; + linear_velocity += current_platform_velocity; } - if (!was_on_floor || snap == Vector2()) { + // Reset the gravity accumulation when touching the ground. + if (on_floor && !vel_dir_facing_up) { + linear_velocity = linear_velocity.slide(up_direction); + } +} + +void CharacterBody2D::_snap_on_floor(bool was_on_floor, bool vel_dir_facing_up) { + if (Math::is_equal_approx(floor_snap_length, 0) || up_direction == Vector2() || on_floor || !was_on_floor || vel_dir_facing_up) { return; } - // Apply snap. Transform2D gt = get_global_transform(); PhysicsServer2D::MotionResult result; - if (move_and_collide(snap, infinite_inertia, result, margin, false, true, false)) { + if (move_and_collide(up_direction * -floor_snap_length, result, margin, true, false)) { bool apply = true; - if (up_direction != Vector2()) { - if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { - on_floor = true; - floor_normal = result.collision_normal; - on_floor_body = result.collider; - floor_velocity = result.collider_velocity; - if (stop_on_slope) { - // move and collide may stray the object a bit because of pre un-stucking, - // so only ensure that motion happens on floor direction in this case. - if (result.motion.length() > margin) { - result.motion = up_direction * up_direction.dot(result.motion); - } else { - result.motion = Vector2(); - } + float collision_angle = Math::acos(result.collision_normal.dot(up_direction)); + if (collision_angle <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { + on_floor = true; + floor_normal = result.collision_normal; + platform_velocity = result.collider_velocity; + _set_platform_data(result); + + if (stop_on_slope) { + // move and collide may stray the object a bit because of pre un-stucking, + // so only ensure that motion happens on floor direction in this case. + if (result.motion.length() > margin) { + result.motion = up_direction * up_direction.dot(result.motion); + } else { + result.motion = Vector2(); } - } else { - apply = false; } + } else { + apply = false; } if (apply) { @@ -1186,59 +1273,46 @@ void CharacterBody2D::move_and_slide() { } } -void CharacterBody2D::_set_collision_direction(const PhysicsServer2D::MotionResult &p_result) { - if (up_direction == Vector2()) { - //all is a wall - on_wall = true; - } else { - if (Math::acos(p_result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor - on_floor = true; - floor_normal = p_result.collision_normal; - on_floor_body = p_result.collider; - floor_velocity = p_result.collider_velocity; - } else if (Math::acos(p_result.collision_normal.dot(-up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling - on_ceiling = true; - } else { - on_wall = true; - on_floor_body = p_result.collider; - floor_velocity = p_result.collider_velocity; - } +bool CharacterBody2D::_on_floor_if_snapped(bool was_on_floor, bool vel_dir_facing_up) { + if (Math::is_equal_approx(floor_snap_length, 0) || up_direction == Vector2() || on_floor || !was_on_floor || vel_dir_facing_up) { + return false; } -} - -bool CharacterBody2D::separate_raycast_shapes(PhysicsServer2D::MotionResult &r_result) { - PhysicsServer2D::SeparationResult sep_res[8]; //max 8 rays - Transform2D gt = get_global_transform(); - - Vector2 recover; - int hits = PhysicsServer2D::get_singleton()->body_test_ray_separation(get_rid(), gt, infinite_inertia, recover, sep_res, 8, margin); - int deepest = -1; - real_t 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; + PhysicsServer2D::MotionResult result; + if (move_and_collide(up_direction * -floor_snap_length, result, margin, true, false)) { + if (Math::acos(result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { + return true; } } - gt.elements[2] += recover; - set_global_transform(gt); + return false; +} - if (deepest != -1) { - r_result.collider_id = sep_res[deepest].collider_id; - r_result.collider_metadata = sep_res[deepest].collider_metadata; - r_result.collider_shape = sep_res[deepest].collider_shape; - r_result.collider_velocity = sep_res[deepest].collider_velocity; - r_result.collision_point = sep_res[deepest].collision_point; - r_result.collision_normal = sep_res[deepest].collision_normal; - r_result.collision_local_shape = sep_res[deepest].collision_local_shape; - r_result.motion = recover; - r_result.remainder = Vector2(); +void CharacterBody2D::_set_collision_direction(const PhysicsServer2D::MotionResult &p_result) { + if (up_direction == Vector2()) { + return; + } - return true; + if (Math::acos(p_result.collision_normal.dot(up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor + on_floor = true; + floor_normal = p_result.collision_normal; + platform_velocity = p_result.collider_velocity; + _set_platform_data(p_result); + } else if (Math::acos(p_result.collision_normal.dot(-up_direction)) <= floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling + on_ceiling = true; } else { - return false; + on_wall = true; + platform_velocity = p_result.collider_velocity; + _set_platform_data(p_result); + } +} + +void CharacterBody2D::_set_platform_data(const PhysicsServer2D::MotionResult &p_result) { + platform_rid = p_result.collider; + platform_layer = 0; + CollisionObject2D *collision_object = Object::cast_to<CollisionObject2D>(ObjectDB::get_instance(p_result.collider_id)); + if (collision_object) { + platform_layer = collision_object->get_collision_layer(); } } @@ -1254,20 +1328,32 @@ bool CharacterBody2D::is_on_floor() const { return on_floor; } +bool CharacterBody2D::is_on_floor_only() const { + return on_floor && !on_wall && !on_ceiling; +} + bool CharacterBody2D::is_on_wall() const { return on_wall; } +bool CharacterBody2D::is_on_wall_only() const { + return on_wall && !on_floor && !on_ceiling; +} + bool CharacterBody2D::is_on_ceiling() const { return on_ceiling; } +bool CharacterBody2D::is_on_ceiling_only() const { + return on_ceiling && !on_floor && !on_wall; +} + Vector2 CharacterBody2D::get_floor_normal() const { return floor_normal; } -Vector2 CharacterBody2D::get_floor_velocity() const { - return floor_velocity; +Vector2 CharacterBody2D::get_platform_velocity() const { + return platform_velocity; } int CharacterBody2D::get_slide_count() const { @@ -1310,11 +1396,36 @@ void CharacterBody2D::set_stop_on_slope_enabled(bool p_enabled) { stop_on_slope = p_enabled; } -bool CharacterBody2D::is_infinite_inertia_enabled() const { - return infinite_inertia; +bool CharacterBody2D::is_constant_speed_on_floor_enabled() const { + return constant_speed_on_floor; +} + +void CharacterBody2D::set_constant_speed_on_floor_enabled(bool p_enabled) { + constant_speed_on_floor = p_enabled; } -void CharacterBody2D::set_infinite_inertia_enabled(bool p_enabled) { - infinite_inertia = p_enabled; + +bool CharacterBody2D::is_move_on_floor_only_enabled() const { + return move_on_floor_only; +} + +void CharacterBody2D::set_move_on_floor_only_enabled(bool p_enabled) { + move_on_floor_only = p_enabled; +} + +bool CharacterBody2D::is_slide_on_ceiling_enabled() const { + return slide_on_ceiling; +} + +void CharacterBody2D::set_slide_on_ceiling_enabled(bool p_enabled) { + slide_on_ceiling = p_enabled; +} + +uint32_t CharacterBody2D::get_exclude_body_layers() const { + return exclude_body_layers; +} + +void CharacterBody2D::set_exclude_body_layers(uint32_t p_exclude_layers) { + exclude_body_layers = p_exclude_layers; } int CharacterBody2D::get_max_slides() const { @@ -1322,7 +1433,7 @@ int CharacterBody2D::get_max_slides() const { } void CharacterBody2D::set_max_slides(int p_max_slides) { - ERR_FAIL_COND(p_max_slides > 0); + ERR_FAIL_COND(p_max_slides < 1); max_slides = p_max_slides; } @@ -1334,12 +1445,13 @@ void CharacterBody2D::set_floor_max_angle(real_t p_radians) { floor_max_angle = p_radians; } -const Vector2 &CharacterBody2D::get_snap() const { - return snap; +real_t CharacterBody2D::get_floor_snap_length() { + return floor_snap_length; } -void CharacterBody2D::set_snap(const Vector2 &p_snap) { - snap = p_snap; +void CharacterBody2D::set_floor_snap_length(real_t p_floor_snap_length) { + ERR_FAIL_COND(p_floor_snap_length < 0); + floor_snap_length = p_floor_snap_length; } const Vector2 &CharacterBody2D::get_up_direction() const { @@ -1355,11 +1467,11 @@ void CharacterBody2D::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { // Reset move_and_slide() data. on_floor = false; - on_floor_body = RID(); + platform_rid = RID(); on_ceiling = false; on_wall = false; motion_results.clear(); - floor_velocity = Vector2(); + platform_velocity = Vector2(); } break; } } @@ -1374,32 +1486,46 @@ void CharacterBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_safe_margin"), &CharacterBody2D::get_safe_margin); ClassDB::bind_method(D_METHOD("is_stop_on_slope_enabled"), &CharacterBody2D::is_stop_on_slope_enabled); ClassDB::bind_method(D_METHOD("set_stop_on_slope_enabled", "enabled"), &CharacterBody2D::set_stop_on_slope_enabled); - ClassDB::bind_method(D_METHOD("is_infinite_inertia_enabled"), &CharacterBody2D::is_infinite_inertia_enabled); - ClassDB::bind_method(D_METHOD("set_infinite_inertia_enabled", "enabled"), &CharacterBody2D::set_infinite_inertia_enabled); + ClassDB::bind_method(D_METHOD("set_constant_speed_on_floor_enabled", "enabled"), &CharacterBody2D::set_constant_speed_on_floor_enabled); + ClassDB::bind_method(D_METHOD("is_constant_speed_on_floor_enabled"), &CharacterBody2D::is_constant_speed_on_floor_enabled); + ClassDB::bind_method(D_METHOD("set_move_on_floor_only_enabled", "enabled"), &CharacterBody2D::set_move_on_floor_only_enabled); + ClassDB::bind_method(D_METHOD("is_move_on_floor_only_enabled"), &CharacterBody2D::is_move_on_floor_only_enabled); + ClassDB::bind_method(D_METHOD("set_slide_on_ceiling_enabled", "enabled"), &CharacterBody2D::set_slide_on_ceiling_enabled); + ClassDB::bind_method(D_METHOD("is_slide_on_ceiling_enabled"), &CharacterBody2D::is_slide_on_ceiling_enabled); + + ClassDB::bind_method(D_METHOD("set_exclude_body_layers", "exclude_layer"), &CharacterBody2D::set_exclude_body_layers); + ClassDB::bind_method(D_METHOD("get_exclude_body_layers"), &CharacterBody2D::get_exclude_body_layers); + ClassDB::bind_method(D_METHOD("get_max_slides"), &CharacterBody2D::get_max_slides); ClassDB::bind_method(D_METHOD("set_max_slides", "max_slides"), &CharacterBody2D::set_max_slides); ClassDB::bind_method(D_METHOD("get_floor_max_angle"), &CharacterBody2D::get_floor_max_angle); ClassDB::bind_method(D_METHOD("set_floor_max_angle", "radians"), &CharacterBody2D::set_floor_max_angle); - ClassDB::bind_method(D_METHOD("get_snap"), &CharacterBody2D::get_snap); - ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CharacterBody2D::set_snap); + ClassDB::bind_method(D_METHOD("get_floor_snap_length"), &CharacterBody2D::get_floor_snap_length); + ClassDB::bind_method(D_METHOD("set_floor_snap_length", "floor_snap_length"), &CharacterBody2D::set_floor_snap_length); ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody2D::get_up_direction); ClassDB::bind_method(D_METHOD("set_up_direction", "up_direction"), &CharacterBody2D::set_up_direction); ClassDB::bind_method(D_METHOD("is_on_floor"), &CharacterBody2D::is_on_floor); + ClassDB::bind_method(D_METHOD("is_on_floor_only"), &CharacterBody2D::is_on_floor_only); ClassDB::bind_method(D_METHOD("is_on_ceiling"), &CharacterBody2D::is_on_ceiling); + ClassDB::bind_method(D_METHOD("is_on_ceiling_only"), &CharacterBody2D::is_on_ceiling_only); ClassDB::bind_method(D_METHOD("is_on_wall"), &CharacterBody2D::is_on_wall); + ClassDB::bind_method(D_METHOD("is_on_wall_only"), &CharacterBody2D::is_on_wall_only); ClassDB::bind_method(D_METHOD("get_floor_normal"), &CharacterBody2D::get_floor_normal); - ClassDB::bind_method(D_METHOD("get_floor_velocity"), &CharacterBody2D::get_floor_velocity); + ClassDB::bind_method(D_METHOD("get_platform_velocity"), &CharacterBody2D::get_platform_velocity); ClassDB::bind_method(D_METHOD("get_slide_count"), &CharacterBody2D::get_slide_count); ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody2D::_get_slide_collision); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity"), "set_linear_velocity", "get_linear_velocity"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stop_on_slope"), "set_stop_on_slope_enabled", "is_stop_on_slope_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "infinite_inertia"), "set_infinite_inertia_enabled", "is_infinite_inertia_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides"), "set_max_slides", "get_max_slides"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_floor_max_angle", "get_floor_max_angle"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "snap"), "set_snap", "get_snap"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "constant_speed_on_floor"), "set_constant_speed_on_floor_enabled", "is_constant_speed_on_floor_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "move_on_floor_only"), "set_move_on_floor_only_enabled", "is_move_on_floor_only_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_ceiling"), "set_slide_on_ceiling_enabled", "is_slide_on_ceiling_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_RANGE, "1,8,1,or_greater"), "set_max_slides", "get_max_slides"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_max_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians"), "set_floor_max_angle", "get_floor_max_angle"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "floor_snap_length", PROPERTY_HINT_RANGE, "0,1000,0.1"), "set_floor_snap_length", "get_floor_snap_length"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "up_direction"), "set_up_direction", "get_up_direction"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "exclude_body_layers", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_exclude_body_layers", "get_exclude_body_layers"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin"); } |