diff --git a/doc/classes/KinematicBody.xml b/doc/classes/KinematicBody.xml index 6fa93ee0cfd..464369d197c 100644 --- a/doc/classes/KinematicBody.xml +++ b/doc/classes/KinematicBody.xml @@ -23,6 +23,13 @@ Returns [code]true[/code] if the specified [code]axis[/code] is locked. See also [member move_lock_x], [member move_lock_y] and [member move_lock_z]. + + + + + Returns the floor's collision angle at the last collision point according to [code]up_direction[/code], which is [code]Vector3.UP[/code] by default. This value is always positive and only valid after calling [method move_and_slide] and when [method is_on_floor] returns [code]true[/code]. + + @@ -35,6 +42,12 @@ Returns the linear velocity of the floor at the last collision point. Only valid after calling [method move_and_slide] or [method move_and_slide_with_snap] and when [method is_on_floor] returns [code]true[/code]. + + + + Returns a [KinematicCollision], which contains information about the latest collision that occurred during the last call to [method move_and_slide]. + + diff --git a/doc/classes/KinematicBody2D.xml b/doc/classes/KinematicBody2D.xml index 7f2e446432c..c61f89bcc63 100644 --- a/doc/classes/KinematicBody2D.xml +++ b/doc/classes/KinematicBody2D.xml @@ -15,6 +15,13 @@ https://godotengine.org/asset-library/asset/120 + + + + + Returns the floor's collision angle at the last collision point according to [code]up_direction[/code], which is [code]Vector2.UP[/code] by default. This value is always positive and only valid after calling [method move_and_slide] and when [method is_on_floor] returns [code]true[/code]. + + @@ -27,6 +34,12 @@ Returns the linear velocity of the floor at the last collision point. Only valid after calling [method move_and_slide] or [method move_and_slide_with_snap] and when [method is_on_floor] returns [code]true[/code]. + + + + Returns a [KinematicCollision2D], which contains information about the latest collision that occurred during the last call to [method move_and_slide]. + + diff --git a/doc/classes/KinematicCollision.xml b/doc/classes/KinematicCollision.xml index 17be68c071d..2e118adf025 100644 --- a/doc/classes/KinematicCollision.xml +++ b/doc/classes/KinematicCollision.xml @@ -10,6 +10,13 @@ + + + + + The collision angle according to [code]up_direction[/code], which is [code]Vector3.UP[/code] by default. This value is always positive. + + diff --git a/doc/classes/KinematicCollision2D.xml b/doc/classes/KinematicCollision2D.xml index d70d53e6c00..90dd0af0def 100644 --- a/doc/classes/KinematicCollision2D.xml +++ b/doc/classes/KinematicCollision2D.xml @@ -10,6 +10,13 @@ + + + + + The collision angle according to [code]up_direction[/code], which is [code]Vector2.UP[/code] by default. This value is always positive. + + diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index f382334a979..2acf3d49f4f 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1281,6 +1281,11 @@ Vector2 KinematicBody2D::get_floor_normal() const { return floor_normal; } +real_t KinematicBody2D::get_floor_angle(const Vector2 &p_up_direction) const { + ERR_FAIL_COND_V(p_up_direction == Vector2(), 0); + return Math::acos(floor_normal.dot(p_up_direction)); +} + Vector2 KinematicBody2D::get_floor_velocity() const { return floor_velocity; } @@ -1323,6 +1328,13 @@ Ref KinematicBody2D::_get_slide_collision(int p_bounce) { return slide_colliders[p_bounce]; } +Ref KinematicBody2D::_get_last_slide_collision() { + if (colliders.size() == 0) { + return Ref(); + } + return _get_slide_collision(colliders.size() - 1); +} + void KinematicBody2D::set_sync_to_physics(bool p_enable) { if (sync_to_physics == p_enable) { return; @@ -1396,6 +1408,7 @@ void KinematicBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody2D::is_on_ceiling); ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody2D::is_on_wall); ClassDB::bind_method(D_METHOD("get_floor_normal"), &KinematicBody2D::get_floor_normal); + ClassDB::bind_method(D_METHOD("get_floor_angle", "up_direction"), &KinematicBody2D::get_floor_angle, DEFVAL(Vector2(0.0, -1.0))); ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody2D::get_floor_velocity); ClassDB::bind_method(D_METHOD("set_safe_margin", "pixels"), &KinematicBody2D::set_safe_margin); @@ -1403,6 +1416,7 @@ void KinematicBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_slide_count"), &KinematicBody2D::get_slide_count); ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &KinematicBody2D::_get_slide_collision); + ClassDB::bind_method(D_METHOD("get_last_slide_collision"), &KinematicBody2D::_get_last_slide_collision); ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &KinematicBody2D::set_sync_to_physics); ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &KinematicBody2D::is_sync_to_physics_enabled); @@ -1448,6 +1462,12 @@ Vector2 KinematicCollision2D::get_travel() const { Vector2 KinematicCollision2D::get_remainder() const { return collision.remainder; } + +real_t KinematicCollision2D::get_angle(const Vector2 &p_up_direction) const { + ERR_FAIL_COND_V(p_up_direction == Vector2(), 0); + return collision.get_angle(p_up_direction); +} + Object *KinematicCollision2D::get_local_shape() const { if (!owner) { return nullptr; @@ -1496,6 +1516,7 @@ void KinematicCollision2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_normal"), &KinematicCollision2D::get_normal); ClassDB::bind_method(D_METHOD("get_travel"), &KinematicCollision2D::get_travel); ClassDB::bind_method(D_METHOD("get_remainder"), &KinematicCollision2D::get_remainder); + ClassDB::bind_method(D_METHOD("get_angle", "up_direction"), &KinematicCollision2D::get_angle, DEFVAL(Vector2(0.0, -1.0))); ClassDB::bind_method(D_METHOD("get_local_shape"), &KinematicCollision2D::get_local_shape); ClassDB::bind_method(D_METHOD("get_collider"), &KinematicCollision2D::get_collider); ClassDB::bind_method(D_METHOD("get_collider_id"), &KinematicCollision2D::get_collider_id); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index a4daefb1e77..02c2de53ea0 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -280,6 +280,10 @@ public: Vector2 remainder; Vector2 travel; int local_shape; + + real_t get_angle(const Vector2 &p_up_direction) const { + return Math::acos(normal.dot(p_up_direction)); + } }; private: @@ -299,6 +303,7 @@ private: Ref _move(const Vector2 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false); Ref _get_slide_collision(int p_bounce); + Ref _get_last_slide_collision(); Transform2D last_valid_transform; void _direct_state_changed(Object *p_state); @@ -325,6 +330,7 @@ public: bool is_on_wall() const; bool is_on_ceiling() const; Vector2 get_floor_normal() const; + real_t get_floor_angle(const Vector2 &p_up_direction = Vector2(0.0, -1.0)) const; Vector2 get_floor_velocity() const; int get_slide_count() const; @@ -352,6 +358,7 @@ public: Vector2 get_normal() const; Vector2 get_travel() const; Vector2 get_remainder() const; + real_t get_angle(const Vector2 &p_up_direction = Vector2(0.0, -1.0)) const; Object *get_local_shape() const; Object *get_collider() const; ObjectID get_collider_id() const; diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 1deda54a665..035928e5ec1 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -1242,6 +1242,11 @@ Vector3 KinematicBody::get_floor_normal() const { return floor_normal; } +real_t KinematicBody::get_floor_angle(const Vector3 &p_up_direction) const { + ERR_FAIL_COND_V(p_up_direction == Vector3(), 0); + return Math::acos(floor_normal.dot(p_up_direction)); +} + Vector3 KinematicBody::get_floor_velocity() const { return floor_velocity; } @@ -1328,6 +1333,13 @@ Ref KinematicBody::_get_slide_collision(int p_bounce) { return slide_colliders[p_bounce]; } +Ref KinematicBody::_get_last_slide_collision() { + if (colliders.size() == 0) { + return Ref(); + } + return _get_slide_collision(colliders.size() - 1); +} + void KinematicBody::set_sync_to_physics(bool p_enable) { if (sync_to_physics == p_enable) { return; @@ -1404,6 +1416,7 @@ void KinematicBody::_bind_methods() { ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody::is_on_ceiling); ClassDB::bind_method(D_METHOD("is_on_wall"), &KinematicBody::is_on_wall); ClassDB::bind_method(D_METHOD("get_floor_normal"), &KinematicBody::get_floor_normal); + ClassDB::bind_method(D_METHOD("get_floor_angle", "up_direction"), &KinematicBody::get_floor_angle, DEFVAL(Vector3(0.0, 1.0, 0.0))); ClassDB::bind_method(D_METHOD("get_floor_velocity"), &KinematicBody::get_floor_velocity); ClassDB::bind_method(D_METHOD("set_axis_lock", "axis", "lock"), &KinematicBody::set_axis_lock); @@ -1414,6 +1427,7 @@ 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); + ClassDB::bind_method(D_METHOD("get_last_slide_collision"), &KinematicBody::_get_last_slide_collision); ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &KinematicBody::set_sync_to_physics); ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &KinematicBody::is_sync_to_physics_enabled); @@ -1463,6 +1477,12 @@ Vector3 KinematicCollision::get_travel() const { Vector3 KinematicCollision::get_remainder() const { return collision.remainder; } + +real_t KinematicCollision::get_angle(const Vector3 &p_up_direction) const { + ERR_FAIL_COND_V(p_up_direction == Vector3(), 0); + return collision.get_angle(p_up_direction); +} + Object *KinematicCollision::get_local_shape() const { if (!owner) { return nullptr; @@ -1511,6 +1531,7 @@ void KinematicCollision::_bind_methods() { ClassDB::bind_method(D_METHOD("get_normal"), &KinematicCollision::get_normal); ClassDB::bind_method(D_METHOD("get_travel"), &KinematicCollision::get_travel); ClassDB::bind_method(D_METHOD("get_remainder"), &KinematicCollision::get_remainder); + ClassDB::bind_method(D_METHOD("get_angle", "up_direction"), &KinematicCollision::get_angle, DEFVAL(Vector3(0.0, 1.0, 0.0))); ClassDB::bind_method(D_METHOD("get_local_shape"), &KinematicCollision::get_local_shape); ClassDB::bind_method(D_METHOD("get_collider"), &KinematicCollision::get_collider); ClassDB::bind_method(D_METHOD("get_collider_id"), &KinematicCollision::get_collider_id); diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 40e8e9d3629..47636c3a1b9 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -275,6 +275,10 @@ public: Vector3 remainder; Vector3 travel; int local_shape; + + real_t get_angle(const Vector3 &p_up_direction) const { + return Math::acos(normal.dot(p_up_direction)); + } }; private: @@ -295,6 +299,7 @@ private: Ref _move(const Vector3 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false); Ref _get_slide_collision(int p_bounce); + Ref _get_last_slide_collision(); Transform last_valid_transform; void _direct_state_changed(Object *p_state); @@ -324,6 +329,7 @@ public: bool is_on_wall() const; bool is_on_ceiling() const; Vector3 get_floor_normal() const; + real_t get_floor_angle(const Vector3 &p_up_direction = Vector3(0.0, 1.0, 0.0)) const; Vector3 get_floor_velocity() const; int get_slide_count() const; @@ -351,6 +357,7 @@ public: Vector3 get_normal() const; Vector3 get_travel() const; Vector3 get_remainder() const; + real_t get_angle(const Vector3 &p_up_direction = Vector3(0.0, 1.0, 0.0)) const; Object *get_local_shape() const; Object *get_collider() const; ObjectID get_collider_id() const;