diff options
Diffstat (limited to 'scene/2d/physics_body_2d.h')
-rw-r--r-- | scene/2d/physics_body_2d.h | 344 |
1 files changed, 235 insertions, 109 deletions
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 2dc853b23b..7401fc7578 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -41,38 +41,29 @@ class KinematicCollision2D; class PhysicsBody2D : public CollisionObject2D { GDCLASS(PhysicsBody2D, CollisionObject2D); - uint32_t collision_layer = 1; - uint32_t collision_mask = 1; - protected: - void _notification(int p_what); - PhysicsBody2D(PhysicsServer2D::BodyMode p_mode); - static void _bind_methods(); + PhysicsBody2D(PhysicsServer2D::BodyMode p_mode); -public: - void set_collision_layer(uint32_t p_layer); - uint32_t get_collision_layer() const; - - void set_collision_mask(uint32_t p_mask); - uint32_t get_collision_mask() const; + Ref<KinematicCollision2D> motion_cache; - void set_collision_mask_bit(int p_bit, bool p_value); - bool get_collision_mask_bit(int p_bit) const; + Ref<KinematicCollision2D> _move(const Vector2 &p_distance, bool p_test_only = false, real_t p_margin = 0.08); - void set_collision_layer_bit(int p_bit, bool p_value); - bool get_collision_layer_bit(int p_bit) const; +public: + bool move_and_collide(const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult &r_result, bool p_test_only = false, bool p_cancel_sliding = true); + bool test_move(const Transform2D &p_from, const Vector2 &p_distance, const Ref<KinematicCollision2D> &r_collision = Ref<KinematicCollision2D>(), real_t p_margin = 0.08); TypedArray<PhysicsBody2D> get_collision_exceptions(); void add_collision_exception_with(Node *p_node); //must be physicsbody void remove_collision_exception_with(Node *p_node); - PhysicsBody2D(); + virtual ~PhysicsBody2D(); }; class StaticBody2D : public PhysicsBody2D { GDCLASS(StaticBody2D, PhysicsBody2D); +private: Vector2 constant_linear_velocity; real_t constant_angular_velocity = 0.0; @@ -91,22 +82,54 @@ public: Vector2 get_constant_linear_velocity() const; real_t get_constant_angular_velocity() const; - StaticBody2D(); - ~StaticBody2D(); + StaticBody2D(PhysicsServer2D::BodyMode p_mode = PhysicsServer2D::BODY_MODE_STATIC); private: void _reload_physics_characteristics(); }; -class RigidBody2D : public PhysicsBody2D { - GDCLASS(RigidBody2D, PhysicsBody2D); +class AnimatableBody2D : public StaticBody2D { + GDCLASS(AnimatableBody2D, StaticBody2D); + +private: + bool sync_to_physics = true; + + Transform2D last_valid_transform; + + static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state); + void _body_state_changed(PhysicsDirectBodyState2D *p_state); + +protected: + void _notification(int p_what); + static void _bind_methods(); public: - enum Mode { - MODE_RIGID, - MODE_STATIC, - MODE_CHARACTER, - MODE_KINEMATIC, + AnimatableBody2D(); + +private: + void _update_kinematic_motion(); + + void set_sync_to_physics(bool p_enable); + bool is_sync_to_physics_enabled() const; +}; + +class RigidDynamicBody2D : public PhysicsBody2D { + GDCLASS(RigidDynamicBody2D, PhysicsBody2D); + +public: + enum FreezeMode { + FREEZE_MODE_STATIC, + FREEZE_MODE_KINEMATIC, + }; + + enum CenterOfMassMode { + CENTER_OF_MASS_MODE_AUTO, + CENTER_OF_MASS_MODE_CUSTOM, + }; + + enum DampMode { + DAMP_MODE_COMBINE, + DAMP_MODE_REPLACE, }; enum CCDMode { @@ -117,14 +140,23 @@ public: private: bool can_sleep = true; - PhysicsDirectBodyState2D *state = nullptr; - Mode mode = MODE_RIGID; + bool lock_rotation = false; + bool freeze = false; + FreezeMode freeze_mode = FREEZE_MODE_STATIC; real_t mass = 1.0; + real_t inertia = 0.0; + CenterOfMassMode center_of_mass_mode = CENTER_OF_MASS_MODE_AUTO; + Vector2 center_of_mass; + Ref<PhysicsMaterial> physics_material_override; real_t gravity_scale = 1.0; - real_t linear_damp = -1.0; - real_t angular_damp = -1.0; + + DampMode linear_damp_mode = DAMP_MODE_COMBINE; + DampMode angular_damp_mode = DAMP_MODE_COMBINE; + + real_t linear_damp = 0.0; + real_t angular_damp = 0.0; Vector2 linear_velocity; real_t angular_velocity = 0.0; @@ -154,11 +186,13 @@ private: local_shape = p_ls; } }; - struct RigidBody2D_RemoveAction { + struct RigidDynamicBody2D_RemoveAction { + RID rid; ObjectID body_id; ShapePair pair; }; struct BodyState { + RID rid; //int rc; bool in_scene = false; VSet<ShapePair> shapes; @@ -166,25 +200,37 @@ private: struct ContactMonitor { bool locked = false; - Map<ObjectID, BodyState> body_map; + HashMap<ObjectID, BodyState> body_map; }; ContactMonitor *contact_monitor = nullptr; void _body_enter_tree(ObjectID p_id); void _body_exit_tree(ObjectID p_id); - void _body_inout(int p_status, ObjectID p_instance, int p_body_shape, int p_local_shape); - void _direct_state_changed(Object *p_state); + void _body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape); - bool _test_motion(const Vector2 &p_motion, bool p_infinite_inertia = true, real_t p_margin = 0.08, const Ref<PhysicsTestMotionResult2D> &p_result = Ref<PhysicsTestMotionResult2D>()); + static void _body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state); + void _body_state_changed(PhysicsDirectBodyState2D *p_state); protected: void _notification(int p_what); static void _bind_methods(); + virtual void _validate_property(PropertyInfo &property) const override; + + GDVIRTUAL1(_integrate_forces, PhysicsDirectBodyState2D *) + + void _apply_body_mode(); + public: - void set_mode(Mode p_mode); - Mode get_mode() const; + void set_lock_rotation_enabled(bool p_lock_rotation); + bool is_lock_rotation_enabled() const; + + void set_freeze_enabled(bool p_freeze); + bool is_freeze_enabled() const; + + void set_freeze_mode(FreezeMode p_freeze_mode); + FreezeMode get_freeze_mode() const; void set_mass(real_t p_mass); real_t get_mass() const; @@ -192,12 +238,24 @@ public: void set_inertia(real_t p_inertia); real_t get_inertia() const; + void set_center_of_mass_mode(CenterOfMassMode p_mode); + CenterOfMassMode get_center_of_mass_mode() const; + + void set_center_of_mass(const Vector2 &p_center_of_mass); + const Vector2 &get_center_of_mass() const; + void set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override); Ref<PhysicsMaterial> get_physics_material_override() const; void set_gravity_scale(real_t p_gravity_scale); real_t get_gravity_scale() const; + void set_linear_damp_mode(DampMode p_mode); + DampMode get_linear_damp_mode() const; + + void set_angular_damp_mode(DampMode p_mode); + DampMode get_angular_damp_mode() const; + void set_linear_damp(real_t p_linear_damp); real_t get_linear_damp() const; @@ -234,108 +292,177 @@ public: void apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position = Vector2()); void apply_torque_impulse(real_t p_torque); - void set_applied_force(const Vector2 &p_force); - Vector2 get_applied_force() const; + void apply_central_force(const Vector2 &p_force); + void apply_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()); + void apply_torque(real_t p_torque); - void set_applied_torque(const real_t p_torque); - real_t get_applied_torque() const; + void add_constant_central_force(const Vector2 &p_force); + void add_constant_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()); + void add_constant_torque(real_t p_torque); - void add_central_force(const Vector2 &p_force); - void add_force(const Vector2 &p_force, const Vector2 &p_position = Vector2()); - void add_torque(real_t p_torque); + void set_constant_force(const Vector2 &p_force); + Vector2 get_constant_force() const; + + void set_constant_torque(real_t p_torque); + real_t get_constant_torque() const; TypedArray<Node2D> get_colliding_bodies() const; //function for script - virtual String get_configuration_warning() const override; + virtual TypedArray<String> get_configuration_warnings() const override; - RigidBody2D(); - ~RigidBody2D(); + RigidDynamicBody2D(); + ~RigidDynamicBody2D(); private: void _reload_physics_characteristics(); }; -VARIANT_ENUM_CAST(RigidBody2D::Mode); -VARIANT_ENUM_CAST(RigidBody2D::CCDMode); +VARIANT_ENUM_CAST(RigidDynamicBody2D::FreezeMode); +VARIANT_ENUM_CAST(RigidDynamicBody2D::CenterOfMassMode); +VARIANT_ENUM_CAST(RigidDynamicBody2D::DampMode); +VARIANT_ENUM_CAST(RigidDynamicBody2D::CCDMode); -class KinematicBody2D : public PhysicsBody2D { - GDCLASS(KinematicBody2D, PhysicsBody2D); +class CharacterBody2D : public PhysicsBody2D { + GDCLASS(CharacterBody2D, PhysicsBody2D); public: - struct Collision { - Vector2 collision; - Vector2 normal; - Vector2 collider_vel; - ObjectID collider; - RID collider_rid; - int collider_shape = 0; - Variant collider_metadata; - Vector2 remainder; - Vector2 travel; - int local_shape = 0; + enum MotionMode { + MOTION_MODE_GROUNDED, + MOTION_MODE_FLOATING, }; + enum MovingPlatformApplyVelocityOnLeave { + PLATFORM_VEL_ON_LEAVE_ALWAYS, + PLATFORM_VEL_ON_LEAVE_UPWARD_ONLY, + PLATFORM_VEL_ON_LEAVE_NEVER, + }; + bool move_and_slide(); + + const Vector2 &get_velocity() const; + void set_velocity(const Vector2 &p_velocity); + + bool is_on_floor() const; + bool is_on_floor_only() const; + bool is_on_wall() const; + bool is_on_wall_only() const; + bool is_on_ceiling() const; + bool is_on_ceiling_only() const; + const Vector2 &get_last_motion() const; + Vector2 get_position_delta() const; + const Vector2 &get_floor_normal() const; + const Vector2 &get_wall_normal() const; + const Vector2 &get_real_velocity() const; + + real_t get_floor_angle(const Vector2 &p_up_direction = Vector2(0.0, -1.0)) const; + const Vector2 &get_platform_velocity() const; + + int get_slide_collision_count() const; + PhysicsServer2D::MotionResult get_slide_collision(int p_bounce) const; + + CharacterBody2D(); + ~CharacterBody2D(); private: - real_t margin; + real_t margin = 0.08; + MotionMode motion_mode = MOTION_MODE_GROUNDED; + MovingPlatformApplyVelocityOnLeave moving_platform_apply_velocity_on_leave = PLATFORM_VEL_ON_LEAVE_ALWAYS; + + bool floor_constant_speed = false; + bool floor_stop_on_slope = true; + bool floor_block_on_wall = true; + bool slide_on_ceiling = true; + int max_slides = 4; + int platform_layer = 0; + real_t floor_max_angle = Math::deg2rad((real_t)45.0); + real_t floor_snap_length = 1; + real_t wall_min_slide_angle = Math::deg2rad((real_t)15.0); + Vector2 up_direction = Vector2(0.0, -1.0); + uint32_t moving_platform_floor_layers = UINT32_MAX; + uint32_t moving_platform_wall_layers = 0; + Vector2 velocity; Vector2 floor_normal; - Vector2 floor_velocity; - RID on_floor_body; - bool on_floor; - bool on_ceiling; - bool on_wall; - bool sync_to_physics; - - Vector<Collision> colliders; + Vector2 platform_velocity; + Vector2 wall_normal; + Vector2 last_motion; + Vector2 previous_position; + Vector2 real_velocity; + + RID platform_rid; + ObjectID platform_object_id; + bool on_floor = false; + bool on_ceiling = false; + bool on_wall = false; + + Vector<PhysicsServer2D::MotionResult> motion_results; Vector<Ref<KinematicCollision2D>> slide_colliders; - Ref<KinematicCollision2D> motion_cache; - _FORCE_INLINE_ bool _ignores_mode(PhysicsServer2D::BodyMode) const; + void set_safe_margin(real_t p_margin); + real_t get_safe_margin() const; - Ref<KinematicCollision2D> _move(const Vector2 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false); - Ref<KinematicCollision2D> _get_slide_collision(int p_bounce); + bool is_floor_stop_on_slope_enabled() const; + void set_floor_stop_on_slope_enabled(bool p_enabled); - Transform2D last_valid_transform; - void _direct_state_changed(Object *p_state); + bool is_floor_constant_speed_enabled() const; + void set_floor_constant_speed_enabled(bool p_enabled); -protected: - void _notification(int p_what); - static void _bind_methods(); + bool is_floor_block_on_wall_enabled() const; + void set_floor_block_on_wall_enabled(bool p_enabled); -public: - bool move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes = true, bool p_test_only = false); + bool is_slide_on_ceiling_enabled() const; + void set_slide_on_ceiling_enabled(bool p_enabled); - bool test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia = true); + int get_max_slides() const; + void set_max_slides(int p_max_slides); - bool separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision); + real_t get_floor_max_angle() const; + void set_floor_max_angle(real_t p_radians); - void set_safe_margin(real_t p_margin); - real_t get_safe_margin() const; + real_t get_floor_snap_length(); + void set_floor_snap_length(real_t p_floor_snap_length); - Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_up_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, real_t p_floor_max_angle = Math::deg2rad((real_t)45.0), bool p_infinite_inertia = true); - Vector2 move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_up_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, real_t p_floor_max_angle = Math::deg2rad((real_t)45.0), bool p_infinite_inertia = true); - bool is_on_floor() const; - bool is_on_wall() const; - bool is_on_ceiling() const; - Vector2 get_floor_normal() const; - Vector2 get_floor_velocity() const; + real_t get_wall_min_slide_angle() const; + void set_wall_min_slide_angle(real_t p_radians); - int get_slide_count() const; - Collision get_slide_collision(int p_bounce) const; + uint32_t get_moving_platform_floor_layers() const; + void set_moving_platform_floor_layers(const uint32_t p_exclude_layer); - void set_sync_to_physics(bool p_enable); - bool is_sync_to_physics_enabled() const; + uint32_t get_moving_platform_wall_layers() const; + void set_moving_platform_wall_layers(const uint32_t p_exclude_layer); - KinematicBody2D(); - ~KinematicBody2D(); + void set_motion_mode(MotionMode p_mode); + MotionMode get_motion_mode() const; + + void set_moving_platform_apply_velocity_on_leave(MovingPlatformApplyVelocityOnLeave p_on_leave_velocity); + MovingPlatformApplyVelocityOnLeave get_moving_platform_apply_velocity_on_leave() const; + + void _move_and_slide_floating(double p_delta); + void _move_and_slide_grounded(double p_delta, bool p_was_on_floor); + + Ref<KinematicCollision2D> _get_slide_collision(int p_bounce); + Ref<KinematicCollision2D> _get_last_slide_collision(); + const Vector2 &get_up_direction() const; + bool _on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_facing_up); + void set_up_direction(const Vector2 &p_up_direction); + void _set_collision_direction(const PhysicsServer2D::MotionResult &p_result); + void _set_platform_data(const PhysicsServer2D::MotionResult &p_result); + void _snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up, bool p_wall_as_floor = false); + +protected: + void _notification(int p_what); + static void _bind_methods(); + virtual void _validate_property(PropertyInfo &property) const override; }; -class KinematicCollision2D : public Reference { - GDCLASS(KinematicCollision2D, Reference); +VARIANT_ENUM_CAST(CharacterBody2D::MotionMode); +VARIANT_ENUM_CAST(CharacterBody2D::MovingPlatformApplyVelocityOnLeave); - KinematicBody2D *owner; - friend class KinematicBody2D; - KinematicBody2D::Collision collision; +class KinematicCollision2D : public RefCounted { + GDCLASS(KinematicCollision2D, RefCounted); + + PhysicsBody2D *owner = nullptr; + friend class PhysicsBody2D; + friend class CharacterBody2D; + PhysicsServer2D::MotionResult result; protected: static void _bind_methods(); @@ -345,15 +472,14 @@ 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; + RID get_collider_rid() const; Object *get_collider_shape() const; int get_collider_shape_index() const; Vector2 get_collider_velocity() const; - Variant get_collider_metadata() const; - - KinematicCollision2D(); }; #endif // PHYSICS_BODY_2D_H |