diff --git a/src/bodies/rapier_body_2d.rs b/src/bodies/rapier_body_2d.rs index cd59ba78..93be9a65 100644 --- a/src/bodies/rapier_body_2d.rs +++ b/src/bodies/rapier_body_2d.rs @@ -183,7 +183,13 @@ impl RapierBody2D { pub fn set_force_integration_callback(&mut self, callable: Callable, udata: Variant) { } - pub fn get_direct_state(&self) -> Option> { + pub fn get_direct_state(&self) -> &Option> { + if self.direct_state.is_none() { + let direct_space_state = RapierDirectBodyState2D::new_alloc(); + direct_space_state.set_body(self.rid); + self.direct_state = Some(direct_space_state.upcast()); + } + &self.direct_state } pub fn add_area(&mut self, area: Rid) { diff --git a/src/bodies/rapier_collision_object_2d.rs b/src/bodies/rapier_collision_object_2d.rs index f3d2b4c5..268a8d18 100644 --- a/src/bodies/rapier_collision_object_2d.rs +++ b/src/bodies/rapier_collision_object_2d.rs @@ -1,6 +1,6 @@ use std::{cell::RefCell, rc::Rc}; use godot::{builtin::{real, Rid, Transform2D, Vector2}, engine::{native::ObjectId, physics_server_2d}, obj::InstanceId}; -use crate::{rapier2d::{body::{body_get_angle, body_get_position, body_set_transform}, collider::{collider_create_sensor, collider_create_solid, collider_destroy, Material}, handle::{invalid_handle, is_handle_valid, Handle}, user_data::UserData, vector::Vector}, servers::rapier_physics_singleton_2d::physics_singleton, shapes::rapier_shape_2d::IRapierShape2D, spaces::rapier_space_2d::RapierSpace2D}; +use crate::{rapier2d::{body::{body_get_angle, body_get_position, body_set_transform}, collider::{collider_create_sensor, collider_create_solid, collider_destroy, Material}, handle::{invalid_handle, is_handle_valid, Handle}, shape::ShapeInfo, user_data::UserData, vector::Vector}, servers::rapier_physics_singleton_2d::physics_singleton, shapes::rapier_shape_2d::IRapierShape2D, spaces::rapier_space_2d::RapierSpace2D}; pub trait IRapierCollisionObject2D { fn get_base(&self) -> &RapierCollisionObject2D; @@ -143,8 +143,8 @@ impl RapierCollisionObject2D { shape: shape.shape.get_rapier_shape(), position, angle, - skew: shape.xform.get_skew(), - scale: Vector::new(shape.xform.get_scale().x, shape.xform.get_scale().y), + skew: shape.xform.skew, + scale: Vector::new(shape.xform.scale.x, shape.xform.scale.y), }; collider_set_transform(space_handle, shape.collider_handle, shape_info); } diff --git a/src/bodies/rapier_direct_body_state_2d.rs b/src/bodies/rapier_direct_body_state_2d.rs index 6e8fe01b..9ddd5a81 100644 --- a/src/bodies/rapier_direct_body_state_2d.rs +++ b/src/bodies/rapier_direct_body_state_2d.rs @@ -1,5 +1,9 @@ use godot::{engine::{IPhysicsDirectBodyState2DExtension, PhysicsDirectBodyState2DExtension, PhysicsDirectSpaceState2D}, prelude::*}; +use crate::servers::rapier_physics_singleton_2d::physics_singleton; + +use super::{rapier_body_2d::RapierBody2D, rapier_collision_object_2d::CollisionObjectType}; + #[derive(GodotClass)] #[class(base=PhysicsDirectBodyState2DExtension)] pub struct RapierDirectBodyState2D { @@ -8,7 +12,9 @@ pub struct RapierDirectBodyState2D { base: Base, } +#[godot_api] impl RapierDirectBodyState2D { + #[func] pub fn set_body(&mut self, body: Rid) { self.body = body; } @@ -24,7 +30,15 @@ impl IPhysicsDirectBodyState2DExtension for RapierDirectBodyState2D { } fn get_total_gravity(&self,) -> Vector2 { - Vector2::default() + physics_singleton() + if (body.using_area_gravity) { + return body->total_gravity; + } else { + ERR_FAIL_COND_V(!body->get_space(), Vector2()); + real_t default_gravity = body->get_space()->get_default_area_param(PhysicsServer2D::AREA_PARAM_GRAVITY); + Vector2 default_gravity_vector = body->get_space()->get_default_area_param(PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR); + return body->gravity_scale * default_gravity_vector * default_gravity; + } } fn get_total_linear_damp(&self,) -> f32 { diff --git a/src/servers/rapier_physics_singleton_2d.rs b/src/servers/rapier_physics_singleton_2d.rs index 0e7fc000..38942568 100644 --- a/src/servers/rapier_physics_singleton_2d.rs +++ b/src/servers/rapier_physics_singleton_2d.rs @@ -1,8 +1,11 @@ -use crate::bodies::rapier_collision_object_2d::IRapierCollisionObject2D; +use crate::bodies::rapier_area_2d::RapierArea2D; +use crate::bodies::rapier_body_2d::RapierBody2D; +use crate::bodies::rapier_collision_object_2d::{CollisionObjectType, IRapierCollisionObject2D}; use crate::fluids::rapier_fluid_2d::RapierFluid2D; use crate::joints::rapier_joint_2d::IRapierJoint2D; use crate::rapier2d::handle::Handle; -use crate::shapes::rapier_shape_2d::IRapierShape2D; +use crate::shapes::rapier_circle_shape_2d::RapierCircleShape2D; +use crate::shapes::rapier_shape_2d::{IRapierShape2D}; use crate::spaces::rapier_space_2d::RapierSpace2D; use godot::builtin::Rid; use std::collections::HashMap; @@ -34,3 +37,68 @@ pub fn physics_singleton() -> &'static Mutex { static HOLDER: OnceLock> = OnceLock::new(); HOLDER.get_or_init(|| Mutex::new(RapierPhysicsSingleton2D::new())) } + +pub fn get_shape(rid: Rid) -> &'static IRapierShape2D { + let lock = physics_singleton().lock().unwrap(); + let shape = lock.shapes.get(&rid); + if let Some(shape) = shape { + return shape; + } + return &RapierCircleShape2D::new(Rid::Invalid); +} + +pub fn get_space(rid: Rid) -> &'static RapierSpace2D { + let lock = physics_singleton().lock().unwrap(); + let space = lock.spaces.get(&rid); + if let Some(space) = space { + return space; + } + return &RapierSpace2D::new(Rid::Invalid); +} + +pub fn get_collision_object(rid: Rid) -> &'static IRapierCollisionObject2D { + let lock = physics_singleton().lock().unwrap(); + let collision_object = lock.collision_objects.get(&rid); + if let Some(collision_object) = collision_object { + return collision_object; + } + return &RapierBody2D::new(Rid::Invalid); +} + +pub fn get_body(rid: Rid) -> &'static RapierBody2D { + let body = get_collision_object(rid); + if let Some(body) = body { + if body.get_base().get_type() == CollisionObjectType::Body { + return body as &RapierBody2D; + } + } + return &RapierBody2D::new(Rid::Invalid); +} + +pub fn get_area(rid: Rid) -> &'static RapierArea2D { + let area = get_collision_object(rid); + if let Some(area) = area { + if area.get_base().get_type() == CollisionObjectType::Area { + return area as &RapierArea2D; + } + } + return &RapierArea2D::new(Rid::Invalid); +} + +pub fn get_joint(rid: Rid) -> &'static IRapierJoint2D { + let lock = physics_singleton().lock().unwrap(); + let joint = lock.joints.get(&rid); + if let Some(joint) = joint { + return joint; + } + return &RapierBody2D::new(Rid::Invalid); +} + +pub fn get_fluid(rid: Rid) -> &'static RapierFluid2D { + let lock = physics_singleton().lock().unwrap(); + let fluid = lock.fluids.get(&rid); + if let Some(fluid) = fluid { + return fluid; + } + return &RapierFluid2D::new(Rid::Invalid); +} diff --git a/src/spaces/rapier_space_2d.rs b/src/spaces/rapier_space_2d.rs index c6571297..93b9a9e8 100644 --- a/src/spaces/rapier_space_2d.rs +++ b/src/spaces/rapier_space_2d.rs @@ -1,27 +1,26 @@ -use std::{collections::HashMap, sync::{Arc, Mutex}}; -use godot::{engine::{native::ObjectId, physics_server_2d, PhysicsDirectSpaceState2D, ProjectSettings}, prelude::*}; -use crate::{bodies::{rapier_area_2d::RapierArea2D, rapier_body_2d::RapierBody2D, rapier_collision_object_2d::{CollisionObjectType, IRapierCollisionObject2D, RapierCollisionObject2D}}, rapier2d::{handle::{invalid_handle, Handle}, physics_hooks::{CollisionFilterInfo, OneWayDirection}, physics_world::{world_create, world_set_active_body_callback, world_set_body_collision_filter_callback, world_set_collision_event_callback, world_set_contact_force_event_callback, world_set_contact_point_callback, world_set_modify_contacts_callback, world_set_sensor_collision_filter_callback, ActiveBodyInfo, CollisionEventInfo, ContactForceEventInfo, ContactPointInfo}, query::QueryExcludedInfo, settings::default_world_settings, user_data::{is_user_data_valid, UserData}}, servers::{rapier_physics_singleton_2d::physics_singleton, rapier_project_settings::RapierProjectSettings}}; - -use super::rapier_direct_space_state_2d::RapierDirectSpaceState2D; - -const TEST_MOTION_MARGIN: real = 0.0001; - -struct RemovedColliderInfo { - rid: Rid, - instance_id: InstanceId, - shape_index: u32, - collision_object_type: CollisionObjectType, +use std::collections::HashMap; +use godot::{engine::{native::{ObjectId, PhysicsServer2DExtensionMotionResult}, physics_server_2d, PhysicsDirectSpaceState2D, ProjectSettings}, prelude::*}; +use crate::{bodies::{rapier_area_2d::RapierArea2D, rapier_body_2d::RapierBody2D, rapier_collision_object_2d::{CollisionObjectType, IRapierCollisionObject2D, RapierCollisionObject2D}}, rapier2d::{handle::{invalid_handle, Handle}, physics_hooks::{CollisionFilterInfo, OneWayDirection}, physics_world::{world_create, world_set_active_body_callback, world_set_body_collision_filter_callback, world_set_collision_event_callback, world_set_contact_force_event_callback, world_set_contact_point_callback, world_set_modify_contacts_callback, world_set_sensor_collision_filter_callback, ActiveBodyInfo, CollisionEventInfo, ContactForceEventInfo, ContactPointInfo}, query::{PointHitInfo, QueryExcludedInfo}, settings::default_world_settings, user_data::{is_user_data_valid, UserData}}, servers::{rapier_physics_singleton_2d::physics_singleton, rapier_project_settings::RapierProjectSettings}}; +use crate::spaces::rapier_direct_space_state_2d::RapierDirectSpaceState2D; + +const TEST_MOTION_MARGIN: real = 1e-4; + +pub struct RemovedColliderInfo { + pub rid: Rid, + pub instance_id: InstanceId, + pub shape_index: u32, + pub collision_object_type: CollisionObjectType, } -struct CollidersInfo { - shape1: u32, - object1: Option, - shape2: u32, - object2: Option, +pub struct CollidersInfo { + pub shape1: u32, + pub object1: Option, + pub shape2: u32, + pub object2: Option, } pub struct RapierSpace2D { - direct_access: Option>, + direct_access: Gd, rid: Rid, handle: Handle, removed_colliders: HashMap, @@ -58,7 +57,7 @@ impl RapierSpace2D { let project_settings = ProjectSettings::singleton(); let physics_fps = project_settings.get_setting_with_override("physics/common/physics_ticks_per_second".into()); - let mut last_step = 0.001; + let mut last_step = 1e-3; if !physics_fps.is_nil() { last_step = 1.0 / (physics_fps.to::() as f32); } @@ -87,7 +86,7 @@ impl RapierSpace2D { world_set_contact_force_event_callback(handle, Some(RapierSpace2D::contact_force_event_callback)); world_set_contact_point_callback(handle, Some(RapierSpace2D::contact_point_callback)); Self { - direct_access: None, + direct_access, rid, handle, removed_colliders: HashMap::new(), @@ -227,11 +226,11 @@ impl RapierSpace2D { false } - static Object *_get_object_instance_hack(uint64_t p_object_id) { - return reinterpret_cast((GodotObject *)(internal::gdextension_interface_object_get_instance_from_id(p_object_id))); + pub fn _get_object_instance_hack(instance_id: InstanceId) -> &'static Object{ + return &Gd::from_instance_id(instance_id); } - pub fn get_handle(&self) -> Handle { return handle; } + pub fn get_handle(&self) -> Handle { return self.handle; } pub fn set_rid(&mut self, p_rid: Rid) { self.rid = p_rid; } @@ -338,20 +337,13 @@ impl RapierSpace2D { return self.contact_debug_count } - pub fn get_direct_state(&mut self) -> Option> { - if self.direct_access.is_none() { - let direct_space_state = RapierDirectSpaceState2D::new_alloc(); - self.direct_access = Some(direct_space_state.upcast()); - } - self.direct_access.clone() + pub fn get_direct_state(&mut self) -> Gd { + self.direct_access.upcast() } - pub fn test_body_motion(&self, body: Rid, from: Transform2D, motion: Vector2, margin: double, collide_separation_ray: bool, recovery_as_collision: bool, result: &PhysicsServer2DExtensionMotionResult) -> bool { - + pub fn test_body_motion(&self, body: Rid, from: Transform2D, motion: Vector2, margin: f64, collide_separation_ray: bool, recovery_as_collision: bool, result: &PhysicsServer2DExtensionMotionResult) -> bool { } pub fn rapier_intersect_aabb(&self, aabb: Rect2, collision_mask: u32, collide_with_bodies: bool, collide_with_areas: bool, results: &PointHitInfo, max_results: i32, result_count: &i32, exclude_body: Rid) -> i32 { - } - }