diff --git a/.github/workflows/runner.yml b/.github/workflows/runner.yml index 41d0245f..b702fe75 100644 --- a/.github/workflows/runner.yml +++ b/.github/workflows/runner.yml @@ -6,6 +6,10 @@ on: branches: - "main" +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + jobs: static-checks: name: 📊 Static checks diff --git a/.github/workflows/test_checks.yml b/.github/workflows/test_checks.yml index 46376edc..1ec0edd6 100644 --- a/.github/workflows/test_checks.yml +++ b/.github/workflows/test_checks.yml @@ -3,8 +3,28 @@ on: workflow_call: jobs: - run-tests-2d: - name: Run Tests + run-unit-tests-2d: + name: Run Unit Tests 2D + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Run Unit Tests for 2D Build + shell: sh + run: | + cargo test --all-targets --features="build2d,test" --no-default-features + run-unit-tests-3d: + name: Run Unit Tests 3D + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Run Unit Tests for 3D Build + shell: sh + run: | + cargo test --all-targets --features="build3d,test" --no-default-features + run-integration-tests-2d: + name: Run Integration Tests 2D runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -15,17 +35,12 @@ jobs: version: 4.3.0 use-dotnet: false include-templates: true - - name: Run Unit Tests for 2D Build - shell: sh - run: | - cargo test --all-targets --features="build2d,test" --no-default-features - name: Run Integration Tests for 2D Build shell: sh - # Skip this for now - if: false run: | return ./scripts/build-dev-2d.sh + ls bin2d/addons/godot-rapier2d/bin godot --headless --path ./bin2d test.tscn --quit-after 1000 > output.log 2>&1 echo "---------------------" grep "ERROR:" output.log @@ -40,8 +55,8 @@ jobs: exit 1 fi - run-tests-3d: - name: Run Tests + run-integration-tests-3d: + name: Run Integration Tests 3D runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -51,16 +66,12 @@ jobs: version: 4.3.0 use-dotnet: false include-templates: true - - name: Run Unit Tests for 3D Build - shell: sh - run: | - cargo test --all-targets --features="build3d,test" --no-default-features - name: Run Integration Tests for 3D Build - # Skip this for now - if: false shell: sh run: | + return ./scripts/build-dev-3d.sh + ls bin3d/addons/godot-rapier3d/bin godot --headless --path ./bin3d test.tscn --quit-after 1000 > output.log 2>&1 echo "---------------------" grep "ERROR:" output.log diff --git a/bin2d/addons/godot-rapier2d/fluid_2d_renderer.gd b/bin2d/addons/godot-rapier2d/fluid_2d_renderer.gd index 19788819..c45a7206 100644 --- a/bin2d/addons/godot-rapier2d/fluid_2d_renderer.gd +++ b/bin2d/addons/godot-rapier2d/fluid_2d_renderer.gd @@ -4,7 +4,7 @@ extends MultiMeshInstance2D @export var fluid: Fluid2D @export var color: Color = Color(0.8, 0.8, 0.8, 0.3) - +@export var mesh_scale: Vector2 = Vector2(5,5) func _ready(): if multimesh == null: @@ -23,7 +23,7 @@ func _process(_delta): var points = fluid.points for i in points.size(): var point = points[i] - var new_transform: Transform2D = Transform2D(0, Vector2(5, 5), 0, point) + var new_transform: Transform2D = Transform2D(0, mesh_scale, 0, point) multimesh.set_instance_transform_2d(index, new_transform) multimesh.set_instance_color(index, color) index += 1 diff --git a/bin2d/addons/godot-rapier2d/fluid_2d_shader_renderer.gd b/bin2d/addons/godot-rapier2d/fluid_2d_shader_renderer.gd index 30bfabad..62ce5601 100644 --- a/bin2d/addons/godot-rapier2d/fluid_2d_shader_renderer.gd +++ b/bin2d/addons/godot-rapier2d/fluid_2d_shader_renderer.gd @@ -8,6 +8,7 @@ extends CanvasLayer update_configuration_warnings() @export var camera: Camera2D @export var water_material: Material = load("res://addons/godot-rapier2d/water_shader.tres") +@export var mesh_scale: Vector2 = Vector2(5,5) var fluid_renderer: Fluid2DRenderer var inside_camera: Camera2D: set(value): @@ -46,6 +47,7 @@ func _create_fluid_renderer(): fluid_renderer = Fluid2DRenderer.new() fluid_renderer.name = "Fluid2DRenderer" fluid_renderer.color = Color(255,0,255) + fluid_renderer.mesh_scale = mesh_scale fluid_renderer.fluid = fluid sub_viewport.add_child(fluid_renderer) diff --git a/bin2d/test.tscn b/bin2d/test.tscn index 32ac721d..f3cd43fb 100644 --- a/bin2d/test.tscn +++ b/bin2d/test.tscn @@ -1,9 +1,12 @@ -[gd_scene load_steps=3 format=3 uid="uid://cn4jscixu2bmf"] +[gd_scene load_steps=4 format=3 uid="uid://cn4jscixu2bmf"] [ext_resource type="Script" path="res://test.gd" id="1_fs1uw"] [sub_resource type="CircleShape2D" id="CircleShape2D_01opr"] +[sub_resource type="RectangleShape2D" id="RectangleShape2D_vkitq"] +size = Vector2(365, 37) + [node name="Test2D" type="Node2D"] script = ExtResource("1_fs1uw") @@ -12,3 +15,12 @@ position = Vector2(-18, -4) [node name="CollisionShape2D" type="CollisionShape2D" parent="RigidBody2D"] shape = SubResource("CircleShape2D_01opr") + +[node name="StaticBody2D" type="StaticBody2D" parent="."] + +[node name="CollisionShape2D" type="CollisionShape2D" parent="StaticBody2D"] +position = Vector2(10.5, 96.5) +shape = SubResource("RectangleShape2D_vkitq") + +[node name="Camera2D" type="Camera2D" parent="."] +zoom = Vector2(4, 4) diff --git a/bin3d/test.gd b/bin3d/test.gd index 4d6ff991..f6ed4a3f 100644 --- a/bin3d/test.gd +++ b/bin3d/test.gd @@ -14,40 +14,25 @@ func _ready() -> void: get_tree().quit() func test_capsule_shape(): - RapierCapsuleShapeTests.test_allows_one_way_collision() RapierCapsuleShapeTests.test_create() - RapierCapsuleShapeTests.test_get_data() - RapierCapsuleShapeTests.test_get_type() RapierCapsuleShapeTests.test_set_data_from_array() RapierCapsuleShapeTests.test_set_data_from_dictionary() RapierCapsuleShapeTests.test_set_data_from_vector2() func test_circle_shape(): - RapierCircleShapeTests.test_allows_one_way_collision() RapierCircleShapeTests.test_create() - RapierCircleShapeTests.test_get_data() - RapierCircleShapeTests.test_get_type() RapierCircleShapeTests.test_set_data() func test_concave_polygon_shape(): - RapierConcavePolygonShapeTests.test_allows_one_way_collision() RapierConcavePolygonShapeTests.test_create() - RapierConcavePolygonShapeTests.test_get_data() - RapierConcavePolygonShapeTests.test_get_type() RapierConcavePolygonShapeTests.test_set_data() func test_convex_polygon_shape(): # New function for convex polygon shape - RapierConvexPolygonShapeTests.test_allows_one_way_collision() RapierConvexPolygonShapeTests.test_create() - RapierConvexPolygonShapeTests.test_get_data() - RapierConvexPolygonShapeTests.test_get_type() RapierConvexPolygonShapeTests.test_set_data() func test_cylinder_shape(): RapierCylinderShape3DTests.test_create() - RapierCylinderShape3DTests.test_get_type() - RapierCylinderShape3DTests.test_allows_one_way_collision() RapierCylinderShape3DTests.test_set_data_array() RapierCylinderShape3DTests.test_set_data_vector2() RapierCylinderShape3DTests.test_set_data_dictionary() - RapierCylinderShape3DTests.test_get_data() diff --git a/src/bodies/rapier_body.rs b/src/bodies/rapier_body.rs index 1396744e..18e1f6de 100644 --- a/src/bodies/rapier_body.rs +++ b/src/bodies/rapier_body.rs @@ -1574,6 +1574,7 @@ impl RapierBody { if p_mode.ord() >= BodyMode::RIGID.ord() { self.mass_properties_changed(physics_engine, physics_spaces, physics_rids); } + self.set_space_after(physics_engine, physics_spaces, physics_rids); } pub fn set_state( @@ -1956,7 +1957,7 @@ impl RapierBody { &mut self, physics_engine: &mut PhysicsEngine, physics_spaces: &mut PhysicsSpaces, - physics_rids: &mut PhysicsRids, + physics_rids: &PhysicsRids, ) { if self.base.is_space_valid() && self.base.mode.ord() >= BodyMode::KINEMATIC.ord() { if self.get_force_integration_callback().is_some() { diff --git a/src/rapier_wrapper/physics_world.rs b/src/rapier_wrapper/physics_world.rs index 026f2d3c..1464ac9a 100644 --- a/src/rapier_wrapper/physics_world.rs +++ b/src/rapier_wrapper/physics_world.rs @@ -259,7 +259,8 @@ impl PhysicsWorld { + collider1.contact_skin() + collider2.contact_skin() { - continue; + // TODO comment this out for now since it might miss out events + //continue; } let collider_pos_1 = collider1.position() * contact_point.local_p1; let collider_pos_2 = collider2.position() * contact_point.local_p2; diff --git a/src/rapier_wrapper/query.rs b/src/rapier_wrapper/query.rs index 8fe682a6..11cc5bf6 100644 --- a/src/rapier_wrapper/query.rs +++ b/src/rapier_wrapper/query.rs @@ -415,23 +415,30 @@ impl PhysicsEngine { let shared_shape2 = scale_shape(raw_shared_shape2, shape_info2); let shape_transform1 = shape_info1.transform; let shape_transform2 = shape_info2.transform; - if let Ok(Some(contact)) = parry::query::contact( + match parry::query::contact( &shape_transform1, shared_shape1.as_ref(), &shape_transform2, shared_shape2.as_ref(), prediction, ) { - // the distance is negative if there is intersection - // and positive if the objects are separated by distance less than margin - result.pixel_distance = contact.dist; - result.within_margin = contact.dist > 0.0; - result.collided = true; - result.normal1 = contact.normal1.into_inner(); - result.normal2 = contact.normal2.into_inner(); - result.pixel_point1 = (contact.point1 + contact.normal1.mul(prediction)).coords; - result.pixel_point2 = contact.point2.coords; - return result; + Ok(None) => {} + Ok(Some(contact)) => { + // the distance is negative if there is intersection + // and positive if the objects are separated by distance less than margin + result.pixel_distance = contact.dist; + result.within_margin = contact.dist > 0.0; + result.collided = true; + result.normal1 = contact.normal1.into_inner(); + result.normal2 = contact.normal2.into_inner(); + result.pixel_point1 = + (contact.point1 + contact.normal1.mul(prediction)).coords; + result.pixel_point2 = contact.point2.coords; + return result; + } + Err(err) => { + godot_error!("Shape Contact Error: {:?}", err); + } } } } diff --git a/src/servers/mod.rs b/src/servers/mod.rs index 01a65ecc..4a5a31f4 100644 --- a/src/servers/mod.rs +++ b/src/servers/mod.rs @@ -1,6 +1,7 @@ use godot::prelude::*; use crate::servers::rapier_project_settings::RapierProjectSettings; +pub mod rapier_math; #[cfg(feature = "dim2")] pub mod rapier_physics_server_2d; #[cfg(feature = "dim3")] diff --git a/src/servers/rapier_math.rs b/src/servers/rapier_math.rs new file mode 100644 index 00000000..7fa2f3b6 --- /dev/null +++ b/src/servers/rapier_math.rs @@ -0,0 +1,97 @@ +use godot::prelude::*; +use rapier::na::ComplexField; +#[derive(GodotClass)] +#[class(base=Object, init)] +/// Contains Rapier Deterministic Math functions. +pub struct RapierMath { + base: Base, +} +#[godot_api] +impl RapierMath { + #[func] + /// Deterministically compute acos. + fn acos(x: real) -> real { + ComplexField::acos(x) + } + + #[func] + /// Deterministically compute acosh. + fn acosh(x: real) -> real { + ComplexField::acosh(x) + } + + #[func] + /// Deterministically compute asin. + fn asin(x: real) -> real { + ComplexField::asin(x) + } + + #[func] + /// Deterministically compute asinh. + fn asinh(x: real) -> real { + ComplexField::asinh(x) + } + + #[func] + /// Deterministically compute atan. + fn atan(x: real) -> real { + ComplexField::atan(x) + } + + #[func] + /// Deterministically compute atanh. + fn atanh(x: real) -> real { + ComplexField::atanh(x) + } + + #[func] + /// Deterministically compute cos. + fn cos(x: real) -> real { + ComplexField::cos(x) + } + + #[func] + /// Deterministically compute cosh. + fn cosh(x: real) -> real { + ComplexField::cosh(x) + } + + #[func] + /// Deterministically compute log. + fn log(x: real) -> real { + ComplexField::ln(x) + } + + #[func] + /// Deterministically compute sin. + fn sin(x: real) -> real { + ComplexField::sin(x) + } + + #[func] + /// Deterministically compute sinh. + fn sinh(x: real) -> real { + ComplexField::sinh(x) + } + + #[func] + /// Deterministically compute tan. + fn tan(x: real) -> real { + ComplexField::tan(x) + } + + #[func] + /// Deterministically compute tanh. + fn tanh(x: real) -> real { + ComplexField::tanh(x) + } + + #[func] + /// Deterministically compute sqrt. + fn sqrt(x: real) -> real { + if let Some(result) = ComplexField::try_sqrt(x) { + return result; + } + real::NAN + } +} diff --git a/src/servers/rapier_physics_server_extra.rs b/src/servers/rapier_physics_server_extra.rs index 2afd7695..4af6b8cc 100644 --- a/src/servers/rapier_physics_server_extra.rs +++ b/src/servers/rapier_physics_server_extra.rs @@ -7,31 +7,41 @@ use crate::bodies::rapier_collision_object::IRapierCollisionObject; use crate::fluids::rapier_fluid::RapierFluid; use crate::servers::RapierPhysicsServer; use crate::types::*; -#[derive(GodotConvert, Var, Export, Debug)] -#[godot(via = GString)] pub enum RapierBodyParam { ContactSkin, } +impl RapierBodyParam { + fn from_i32(value: i32) -> RapierBodyParam { + match value { + 0 => RapierBodyParam::ContactSkin, + _ => RapierBodyParam::ContactSkin, + } + } +} #[godot_api] impl RapierPhysicsServer { #[func] - /// Set an extra parameter for a body. See [RapierBodyParam] for available params. - fn body_set_extra_param(body: Rid, param: RapierBodyParam, value: Variant) { + /// Set an extra parameter for a body. + fn body_set_extra_param(body: Rid, param: i32, value: Variant) { let physics_data = physics_data(); if let Some(body) = physics_data.collision_objects.get_mut(&body) { if let Some(body) = body.get_mut_body() { - body.set_extra_param(param, value, &mut physics_data.physics_engine); + body.set_extra_param( + RapierBodyParam::from_i32(param), + value, + &mut physics_data.physics_engine, + ); } } } #[func] - /// Get an extra parameter for a body. See [RapierBodyParam] for available params. - fn body_get_extra_param(body: Rid, param: RapierBodyParam) -> Variant { + /// Get an extra parameter for a body. + fn body_get_extra_param(body: Rid, param: i32) -> Variant { let physics_data = physics_data(); if let Some(body) = physics_data.collision_objects.get(&body) { if let Some(body) = body.get_body() { - return body.get_extra_param(param); + return body.get_extra_param(RapierBodyParam::from_i32(param)); } } 0.0.to_variant() @@ -380,10 +390,4 @@ impl RapierPhysicsServer { array.set(1, handle.1 as i64); array } - - #[func] - fn noop() {} - - #[func] - fn noop_binded(&self) {} } diff --git a/src/shapes/rapier_convex_polygon_shape.rs b/src/shapes/rapier_convex_polygon_shape.rs index d39e8933..6c0a1356 100644 --- a/src/shapes/rapier_convex_polygon_shape.rs +++ b/src/shapes/rapier_convex_polygon_shape.rs @@ -207,9 +207,10 @@ mod tests { .try_to() .unwrap(); assert_eq!(data.len(), 3); - assert_eq!(data[0], Vector::splat(0.0)); - assert_eq!(data[1], Vector3::new(1.0, 0.0, 0.0)); - assert_eq!(data[2], Vector3::new(2.0, 2.0, 2.0)); + // Order is changed on points + assert_eq!(data[1], Vector::splat(0.0)); + assert_eq!(data[2], Vector3::new(1.0, 0.0, 0.0)); + assert_eq!(data[0], Vector3::new(2.0, 2.0, 2.0)); assert!(convex_shape.get_base().is_valid()); convex_shape .get_mut_base()