kitgit

tirbofish/dropbear · diff

cb5364b · Thribhu K

fix: physics-based bug fixes

Unverified

diff --git a/crates/eucalyptus-core/src/debug.rs b/crates/eucalyptus-core/src/debug.rs
index 2390d52..b4bff93 100644
--- a/crates/eucalyptus-core/src/debug.rs
+++ b/crates/eucalyptus-core/src/debug.rs
@@ -3,6 +3,75 @@ use crate::scripting::result::DropbearNativeResult;
 use crate::types::{NColour, NQuaternion, NVector3};
 use dropbear_engine::graphics::SharedGraphicsContext;
 use glam::{Quat, Vec3};
+use dropbear_engine::debug::DebugDraw;
+use crate::physics::collider::ColliderShape;
+
+/// Extension traits for [`DebugDraw`](dropbear_engine::debug::DebugDraw)
+pub trait DebugDrawExt {
+    fn draw_collider(&mut self, shape: &ColliderShape, translation: glam::Vec3, scale: glam::Vec3, rotation: Quat, colour: [f32; 4]);
+}
+
+impl DebugDrawExt for DebugDraw {
+    fn draw_collider(&mut self, shape: &ColliderShape, translation: glam::Vec3, scale: glam::Vec3, rotation: Quat, colour: [f32; 4]) {
+        match &shape {
+            ColliderShape::Box { half_extents } => {
+                let he = glam::Vec3::new(
+                    half_extents.x as f32 * scale.x,
+                    half_extents.y as f32 * scale.y,
+                    half_extents.z as f32 * scale.z,
+                );
+                self.draw_obb(translation, he, rotation, colour);
+            }
+            ColliderShape::Sphere { radius } => {
+                let r = radius * scale.x.max(scale.y).max(scale.z);
+                self.draw_sphere(translation, r, colour);
+            }
+            ColliderShape::Capsule {
+                half_height,
+                radius,
+            } => {
+                let axis = rotation * glam::Vec3::Y;
+                let top = translation + axis * (half_height * scale.y);
+                let bottom = translation - axis * (half_height * scale.y);
+                self.draw_capsule(
+                    bottom,
+                    top,
+                    radius * scale.x.max(scale.z),
+                    colour,
+                );
+            }
+            ColliderShape::Cylinder {
+                half_height,
+                radius,
+            } => {
+                let axis = rotation * glam::Vec3::Y;
+                self.draw_cylinder(
+                    translation,
+                    half_height * scale.y,
+                    radius * scale.x.max(scale.z),
+                    axis,
+                    colour,
+                );
+            }
+            ColliderShape::Cone {
+                half_height,
+                radius,
+            } => {
+                let axis = rotation * glam::Vec3::Y;
+                let apex = translation + axis * (half_height * scale.y);
+                let height = 2.0 * half_height * scale.y;
+                let r = radius * scale.x.max(scale.z);
+                self.draw_cone(
+                    apex,
+                    -(rotation * glam::Vec3::Y),
+                    (r / height).atan(),
+                    height,
+                    colour,
+                );
+            }
+        }
+    }
+}
 
 macro_rules! with_debug {
     ($graphics:expr, |$dd:ident| $body:expr) => {
diff --git a/crates/eucalyptus-core/src/physics.rs b/crates/eucalyptus-core/src/physics.rs
index d52ef62..ade63ab 100644
--- a/crates/eucalyptus-core/src/physics.rs
+++ b/crates/eucalyptus-core/src/physics.rs
@@ -201,6 +201,10 @@ impl PhysicsState {
         }
         builder = builder.active_events(active_events);
 
+        if collider_component.is_sensor {
+            builder = builder.active_collision_types(ActiveCollisionTypes::all());
+        }
+
         builder = builder.translation(Vector::from_array(collider_component.translation));
 
         let rotation = UnitQuaternion::from_euler_angles(
diff --git a/crates/eucalyptus-core/src/physics/kcc.rs b/crates/eucalyptus-core/src/physics/kcc.rs
index 0754047..00786f1 100644
--- a/crates/eucalyptus-core/src/physics/kcc.rs
+++ b/crates/eucalyptus-core/src/physics/kcc.rs
@@ -392,7 +392,9 @@ fn move_character(
             *collider.position()
         };
 
-        let filter = QueryFilter::default().exclude_rigid_body(*rigid_body_handle);
+        let filter = QueryFilter::default()
+            .exclude_rigid_body(*rigid_body_handle)
+            .exclude_sensors();
         let query_pipeline = physics_state.broad_phase.as_query_pipeline(
             physics_state.narrow_phase.query_dispatcher(),
             &physics_state.bodies,
diff --git a/crates/eucalyptus-core/src/scene.rs b/crates/eucalyptus-core/src/scene.rs
index b2ea18b..3b622d5 100644
--- a/crates/eucalyptus-core/src/scene.rs
+++ b/crates/eucalyptus-core/src/scene.rs
@@ -5,7 +5,7 @@ pub mod scripting;
 
 use crate::camera::CameraComponent;
 use crate::component::{ComponentRegistry, SerializedComponent};
-use crate::hierarchy::{Children, Parent, SceneHierarchy};
+use crate::hierarchy::{Children, EntityTransformExt, Parent, SceneHierarchy};
 use crate::physics::PhysicsState;
 use crate::physics::collider::ColliderGroup;
 use crate::physics::kcc::KCC;
@@ -279,8 +279,6 @@ impl SceneConfig {
 
             let entity = world.spawn(builder.build());
 
-            self.register_physics_for_entity(world, entity);
-
             if let Some(previous) = label_to_entity.insert(label_for_map.clone(), entity) {
                 log::warn!(
                     "Duplicate entity label '{}' detected; previous entity {:?} will be overwritten in hierarchy mapping",
@@ -293,6 +291,10 @@ impl SceneConfig {
         }
 
         self.rebuild_hierarchy(world, &label_to_entity);
+
+        for &entity in label_to_entity.values() {
+            self.register_physics_for_entity(world, entity);
+        }
         self.ensure_default_light(world, graphics.clone(), progress_sender.as_ref())
             .await?;
 
@@ -304,6 +306,14 @@ impl SceneConfig {
     }
 
     fn register_physics_for_entity(&mut self, world: &mut hecs::World, entity: hecs::Entity) {
+        let entity_transform_copy: Option<EntityTransform> = world
+            .query_one::<&EntityTransform>(entity)
+            .get()
+            .ok()
+            .map(|t: &EntityTransform| *t);
+
+        let world_transform = entity_transform_copy.map(|t: EntityTransform| t.propagate(world, entity));
+
         if let Ok((label, e_trans, rigid, col_group, kcc)) = world
             .query_one::<(
                 &Label,
@@ -316,7 +326,8 @@ impl SceneConfig {
         {
             if let Some(body) = rigid {
                 body.entity = label.clone();
-                self.physics_state.register_rigidbody(body, e_trans.sync());
+                let transform = world_transform.unwrap_or_else(|| e_trans.sync());
+                self.physics_state.register_rigidbody(body, transform);
             }
 
             if let Some(group) = col_group {
diff --git a/crates/eucalyptus-editor/src/editor/scene.rs b/crates/eucalyptus-editor/src/editor/scene.rs
index 83adfdb..11ca9bd 100644
--- a/crates/eucalyptus-editor/src/editor/scene.rs
+++ b/crates/eucalyptus-editor/src/editor/scene.rs
@@ -17,7 +17,7 @@ use eucalyptus_core::billboard::BillboardComponent;
 use eucalyptus_core::component::KotlinComponentDecl;
 use eucalyptus_core::entity_status::EntityStatus;
 use eucalyptus_core::hierarchy::EntityTransformExt;
-use eucalyptus_core::physics::collider::{ColliderGroup, ColliderShape};
+use eucalyptus_core::physics::collider::{ColliderGroup};
 use eucalyptus_core::properties::CustomProperties;
 use eucalyptus_core::states::{Label, SCENES, WorldLoadingStatus};
 use eucalyptus_core::transform::OnRails;
@@ -36,6 +36,7 @@ use std::{
 };
 use winit::event::{MouseScrollDelta, TouchPhase};
 use winit::{event::WindowEvent, event_loop::ActiveEventLoop, keyboard::KeyCode};
+use eucalyptus_core::debug::DebugDrawExt;
 
 impl Scene for Editor {
     fn load(&mut self, graphics: Arc<SharedGraphicsContext>) {
@@ -1108,7 +1109,7 @@ impl Scene for Editor {
             if show_hitboxes {
                 puffin::profile_scope!("collider debug draw");
                 if let Some(debug_draw) = graphics.debug_draw.lock().as_mut() {
-                    let colour = [0.0, 1.0, 0.0, 1.0];
+                    let colour = [0.0, 1.0, 0.0, 1.0]; // green
                     let to_draw: Vec<_> = {
                         let mut q = self.world.query::<(Entity, &ColliderGroup)>();
                         q.iter().map(|(e, cg)| (e, cg.colliders.clone())).collect()
@@ -1128,63 +1129,7 @@ impl Scene for Editor {
                             let (scale, rotation, translation) =
                                 final_matrix.to_scale_rotation_translation();
 
-                            match &collider.shape {
-                                ColliderShape::Box { half_extents } => {
-                                    let he = glam::Vec3::new(
-                                        half_extents.x as f32 * scale.x,
-                                        half_extents.y as f32 * scale.y,
-                                        half_extents.z as f32 * scale.z,
-                                    );
-                                    debug_draw.draw_obb(translation, he, rotation, colour);
-                                }
-                                ColliderShape::Sphere { radius } => {
-                                    let r = radius * scale.x.max(scale.y).max(scale.z);
-                                    debug_draw.draw_sphere(translation, r, colour);
-                                }
-                                ColliderShape::Capsule {
-                                    half_height,
-                                    radius,
-                                } => {
-                                    let axis = rotation * glam::Vec3::Y;
-                                    let top = translation + axis * (half_height * scale.y);
-                                    let bottom = translation - axis * (half_height * scale.y);
-                                    debug_draw.draw_capsule(
-                                        bottom,
-                                        top,
-                                        radius * scale.x.max(scale.z),
-                                        colour,
-                                    );
-                                }
-                                ColliderShape::Cylinder {
-                                    half_height,
-                                    radius,
-                                } => {
-                                    let axis = rotation * glam::Vec3::Y;
-                                    debug_draw.draw_cylinder(
-                                        translation,
-                                        half_height * scale.y,
-                                        radius * scale.x.max(scale.z),
-                                        axis,
-                                        colour,
-                                    );
-                                }
-                                ColliderShape::Cone {
-                                    half_height,
-                                    radius,
-                                } => {
-                                    let axis = rotation * glam::Vec3::Y;
-                                    let apex = translation + axis * (half_height * scale.y);
-                                    let height = 2.0 * half_height * scale.y;
-                                    let r = radius * scale.x.max(scale.z);
-                                    debug_draw.draw_cone(
-                                        apex,
-                                        -(rotation * glam::Vec3::Y),
-                                        (r / height).atan(),
-                                        height,
-                                        colour,
-                                    );
-                                }
-                            }
+                            debug_draw.draw_collider(&collider.shape, translation, scale, rotation, colour);
                         }
                     }
                 }
diff --git a/crates/redback-runtime/src/scene.rs b/crates/redback-runtime/src/scene.rs
index d31e66f..2cb8e39 100644
--- a/crates/redback-runtime/src/scene.rs
+++ b/crates/redback-runtime/src/scene.rs
@@ -137,7 +137,9 @@ impl Scene for PlayMode {
                     1.0
                 };
 
-                let filter = QueryFilter::default().exclude_rigid_body(rigid_body_handle);
+                let filter = QueryFilter::default()
+                    .exclude_rigid_body(rigid_body_handle)
+                    .exclude_sensors();
                 let dispatcher = self.physics_state.narrow_phase.query_dispatcher();
 
                 let broad_phase = &mut self.physics_state.broad_phase;
diff --git a/scripting/commonMain/kotlin/com/dropbear/logging/Logger.kt b/scripting/commonMain/kotlin/com/dropbear/logging/Logger.kt
index 51e655c..f32db8c 100644
--- a/scripting/commonMain/kotlin/com/dropbear/logging/Logger.kt
+++ b/scripting/commonMain/kotlin/com/dropbear/logging/Logger.kt
@@ -77,4 +77,23 @@ object Logger {
     }
 }
 
-internal expect fun getCallerInfo(): String
\ No newline at end of file
+internal expect fun getCallerInfo(): String
+
+/**
+ * Extension function to log and return a value if the value is null.
+ *
+ * # Example
+ * ```
+ * val room1Sensor = engine
+ *     .getEntity("room1_sensor")
+ *     ?.getComponent(ColliderGroup)
+ *     ?.getColliders()
+ *     .orLogAndReturn("room1_sensor missing") { return } // returns if the value is null
+ * ```
+ */
+inline fun <T> T?.orLogAndReturn(msg: String, returnBlock: () -> Nothing): T {
+    return this ?: run {
+        Logger.warn(msg)
+        returnBlock()
+    }
+}
\ No newline at end of file