diff --git a/crates/rust4d_audio/src/lib.rs b/crates/rust4d_audio/src/lib.rs index 3771a39..0e913c1 100644 --- a/crates/rust4d_audio/src/lib.rs +++ b/crates/rust4d_audio/src/lib.rs @@ -266,7 +266,7 @@ impl AudioEngine4D { /// Set the volume of a specific bus pub fn set_bus_volume(&mut self, bus: AudioBus, volume: f32) { if let Some(track) = self.bus_tracks.get_mut(&bus) { - let _ = track.set_volume(Volume::Amplitude(volume.clamp(0.0, 1.0) as f64), Tween::default()); + track.set_volume(Volume::Amplitude(volume.clamp(0.0, 1.0) as f64), Tween::default()); log::debug!("Set {:?} bus volume to {:.2}", bus, volume); } } diff --git a/crates/rust4d_game/src/tween.rs b/crates/rust4d_game/src/tween.rs index 0d3f4ab..c015b20 100644 --- a/crates/rust4d_game/src/tween.rs +++ b/crates/rust4d_game/src/tween.rs @@ -104,6 +104,7 @@ impl EasingFunction { /// /// If you need `FromStr` for integration with other Rust APIs (e.g., serde, clap), /// you can use the [`std::str::FromStr`] implementation which wraps this method. + #[allow(clippy::should_implement_trait)] // FromStr IS implemented; this is the documented Option-returning convenience pub fn from_str(s: &str) -> Option { match s.to_lowercase().as_str() { "linear" => Some(Self::Linear), diff --git a/crates/rust4d_math/src/hyperplane.rs b/crates/rust4d_math/src/hyperplane.rs index ed93cea..2ff6cab 100644 --- a/crates/rust4d_math/src/hyperplane.rs +++ b/crates/rust4d_math/src/hyperplane.rs @@ -209,7 +209,7 @@ mod tests { // 4x4 grid = 16 cells, each with 16 vertices assert_eq!(plane.vertices().len(), 16 * 16); - assert!(plane.tetrahedra().len() > 0); + assert!(!plane.tetrahedra().is_empty()); } #[test] diff --git a/crates/rust4d_math/src/mat4.rs b/crates/rust4d_math/src/mat4.rs index f92ed39..7698254 100644 --- a/crates/rust4d_math/src/mat4.rs +++ b/crates/rust4d_math/src/mat4.rs @@ -239,6 +239,7 @@ pub fn scale(s: Vec4) -> Mat4 { /// The algorithm: /// 1. Normalize each column /// 2. Remove mutual projections between columns +#[allow(clippy::needless_range_loop)] // index pairs (i, j) into mt are clearest here pub fn ortho_iterate(mut m: Mat4) -> Mat4 { // Normalize columns @@ -261,7 +262,7 @@ pub fn ortho_iterate(mut m: Mat4) -> Mat4 { for j in 0..4 { if i != j { let col_j = get_column(m, j); - sum = sum + col_j * (-0.5 * mt[i][j]); + sum += col_j * (-0.5 * mt[i][j]); } } // Re-normalize after projection removal to ensure unit-length columns diff --git a/crates/rust4d_math/src/rotor4.rs b/crates/rust4d_math/src/rotor4.rs index 6f246fb..6220976 100644 --- a/crates/rust4d_math/src/rotor4.rs +++ b/crates/rust4d_math/src/rotor4.rs @@ -604,6 +604,7 @@ mod tests { } #[test] + #[allow(clippy::needless_range_loop)] // pairwise (i, j) column checks fn test_rotation_matrix_is_orthogonal() { // An orthogonal matrix has M * M^T = I let r = Rotor4::from_plane_angle(RotationPlane::XZ, 0.7) diff --git a/crates/rust4d_math/src/tesseract.rs b/crates/rust4d_math/src/tesseract.rs index 501d7fa..6659576 100644 --- a/crates/rust4d_math/src/tesseract.rs +++ b/crates/rust4d_math/src/tesseract.rs @@ -163,7 +163,7 @@ mod tests { fn test_tesseract_tetrahedron_count() { let t = Tesseract4D::new(2.0); // Should have some reasonable number of tetrahedra - assert!(t.tetrahedra().len() > 0); + assert!(!t.tetrahedra().is_empty()); assert!(t.tetrahedra().len() <= 120); // Max: 24 * 5 before deduplication } diff --git a/crates/rust4d_physics/src/material.rs b/crates/rust4d_physics/src/material.rs index 6338069..e1cb19c 100644 --- a/crates/rust4d_physics/src/material.rs +++ b/crates/rust4d_physics/src/material.rs @@ -97,6 +97,7 @@ mod tests { } #[test] + #[allow(clippy::assertions_on_constants)] // deliberate sanity checks on preset values fn test_preset_constants() { // Test that presets have expected properties assert!(PhysicsMaterial::ICE.friction < 0.1); diff --git a/crates/rust4d_physics/src/world.rs b/crates/rust4d_physics/src/world.rs index 68db301..566018b 100644 --- a/crates/rust4d_physics/src/world.rs +++ b/crates/rust4d_physics/src/world.rs @@ -957,14 +957,13 @@ impl PhysicsWorld { // Emit exit events for pairs that are no longer overlapping for &(body_key, trigger_idx) in &self.active_triggers { - if !current_overlaps.contains(&(body_key, trigger_idx)) { - if self.bodies.contains_key(body_key) { + if !current_overlaps.contains(&(body_key, trigger_idx)) + && self.bodies.contains_key(body_key) { self.collision_events.push(CollisionEvent { kind: CollisionEventKind::TriggerExit { body: body_key, trigger_index: trigger_idx }, contact: None, }); } - } } self.active_triggers = current_overlaps; @@ -2046,7 +2045,7 @@ mod tests { let ray = Ray4D::new(Vec4::new(0.0, 5.0, 0.0, 0.0), -Vec4::Y); let hits = world.raycast(&ray, 100.0, CollisionLayer::ALL); - assert!(hits.len() >= 1); + assert!(!hits.is_empty()); match hits[0].target { RayTarget::Static(0) => {} _ => panic!("Expected static hit at index 0"), @@ -2619,7 +2618,7 @@ mod tests { #[test] fn test_line_of_sight_clear() { - let mut world = PhysicsWorld::with_config(PhysicsConfig::new(0.0)); + let world = PhysicsWorld::with_config(PhysicsConfig::new(0.0)); // No obstacles let clear = world.line_of_sight( diff --git a/crates/rust4d_physics/tests/edge_cases.rs b/crates/rust4d_physics/tests/edge_cases.rs index afc3cc2..81bc692 100644 --- a/crates/rust4d_physics/tests/edge_cases.rs +++ b/crates/rust4d_physics/tests/edge_cases.rs @@ -671,12 +671,9 @@ fn collision_events_report_correct_keys() { // key_c should not appear in any events for event in &events { - match event.kind { - CollisionEventKind::BodyVsBody { body_a, body_b } => { - assert_ne!(body_a, key_c); - assert_ne!(body_b, key_c); - } - _ => {} + if let CollisionEventKind::BodyVsBody { body_a, body_b } = event.kind { + assert_ne!(body_a, key_c); + assert_ne!(body_b, key_c); } } } diff --git a/crates/rust4d_render/src/particle/emitter.rs b/crates/rust4d_render/src/particle/emitter.rs index d00f348..e0cf486 100644 --- a/crates/rust4d_render/src/particle/emitter.rs +++ b/crates/rust4d_render/src/particle/emitter.rs @@ -304,8 +304,8 @@ mod tests { let v2: f32 = rng.gen_range(0.0..1.0); // Values should be in [0, 1) - assert!(v1 >= 0.0 && v1 < 1.0); - assert!(v2 >= 0.0 && v2 < 1.0); + assert!((0.0..1.0).contains(&v1)); + assert!((0.0..1.0).contains(&v2)); // Values should be different assert!((v1 - v2).abs() > 0.0001); diff --git a/crates/rust4d_render/src/particle/system.rs b/crates/rust4d_render/src/particle/system.rs index f64f8c4..5dd2f8f 100644 --- a/crates/rust4d_render/src/particle/system.rs +++ b/crates/rust4d_render/src/particle/system.rs @@ -127,11 +127,9 @@ impl ParticleSystem { /// Update all particles and emitters pub fn update(&mut self, dt: f32) { // Update all emitters and collect new particles - for emitter_opt in &mut self.emitters { - if let Some(emitter) = emitter_opt { - let new_particles = emitter.update(dt); - self.particles.extend(new_particles); - } + for emitter in self.emitters.iter_mut().flatten() { + let new_particles = emitter.update(dt); + self.particles.extend(new_particles); } // Remove dead emitters and free their slots diff --git a/crates/rust4d_render/src/particle/types.rs b/crates/rust4d_render/src/particle/types.rs index 12f55d0..c3865e8 100644 --- a/crates/rust4d_render/src/particle/types.rs +++ b/crates/rust4d_render/src/particle/types.rs @@ -35,6 +35,7 @@ pub struct Particle { impl Particle { /// Create a new particle with the given parameters + #[allow(clippy::too_many_arguments)] // construction site is the emitter; a builder adds no clarity pub fn new( position: Vec4, velocity: Vec4, @@ -77,10 +78,10 @@ impl Particle { // Apply drag let drag_factor = (1.0 - self.drag * dt).max(0.0); - self.velocity = self.velocity * drag_factor; + self.velocity *= drag_factor; // Apply velocity to position - self.position = self.position + self.velocity * dt; + self.position += self.velocity * dt; // Interpolate size and color based on lifetime ratio let life_ratio = self.lifetime / self.max_lifetime; diff --git a/crates/rust4d_render/src/pipeline/lookup_tables.rs b/crates/rust4d_render/src/pipeline/lookup_tables.rs index 3021d62..17695e3 100644 --- a/crates/rust4d_render/src/pipeline/lookup_tables.rs +++ b/crates/rust4d_render/src/pipeline/lookup_tables.rs @@ -263,6 +263,7 @@ mod tests { } #[test] + #[allow(clippy::needless_range_loop)] // index used across two tables fn test_tetra_tri_indices_valid() { for case_idx in 0..16 { let edge_mask = TETRA_EDGE_TABLE[case_idx]; diff --git a/crates/rust4d_scripting/src/bindings/math.rs b/crates/rust4d_scripting/src/bindings/math.rs index ce51dd1..73fa0d5 100644 --- a/crates/rust4d_scripting/src/bindings/math.rs +++ b/crates/rust4d_scripting/src/bindings/math.rs @@ -348,7 +348,7 @@ impl LuaUserData for LuaTransform4D { // Translate by offset methods.add_method_mut("translate", |_, this, offset: LuaVec4| { - this.position = this.position + offset.0; + this.position += offset.0; Ok(()) }); diff --git a/crates/rust4d_scripting/src/bindings/physics.rs b/crates/rust4d_scripting/src/bindings/physics.rs index 7dad896..1cb5bbc 100644 --- a/crates/rust4d_scripting/src/bindings/physics.rs +++ b/crates/rust4d_scripting/src/bindings/physics.rs @@ -607,8 +607,10 @@ mod tests { let lua = Lua::new(); // Set up a custom PhysicsConfig with non-default gravity - let mut config = PhysicsConfig::default(); - config.gravity = -9.81; // Earth gravity instead of default -20 + let config = PhysicsConfig { + gravity: -9.81, // Earth gravity instead of default -20 + ..Default::default() + }; lua.set_app_data(config); // Register bindings diff --git a/crates/rust4d_scripting/src/hot_reload.rs b/crates/rust4d_scripting/src/hot_reload.rs index 92b8d27..30d5787 100644 --- a/crates/rust4d_scripting/src/hot_reload.rs +++ b/crates/rust4d_scripting/src/hot_reload.rs @@ -282,7 +282,7 @@ mod tests { std::fs::write(&path, "test_value = 1").unwrap(); // Load it initially - lua.load(&std::fs::read_to_string(&path).unwrap()) + lua.load(std::fs::read_to_string(&path).unwrap()) .exec() .unwrap(); let val: i64 = lua.load("return test_value").eval().unwrap(); diff --git a/examples/01_hello_tesseract.rs b/examples/01_hello_tesseract.rs index 17f505b..4c87903 100644 --- a/examples/01_hello_tesseract.rs +++ b/examples/01_hello_tesseract.rs @@ -34,6 +34,7 @@ struct App { render_context: Option, slice_pipeline: Option, render_pipeline: Option, + #[allow(dead_code)] // keeps ECS world alive alongside its derived GPU geometry world: World, geometry: RenderableGeometry, camera: Camera4D, diff --git a/examples/02_multiple_shapes.rs b/examples/02_multiple_shapes.rs index 0cfc216..629047c 100644 --- a/examples/02_multiple_shapes.rs +++ b/examples/02_multiple_shapes.rs @@ -55,6 +55,7 @@ struct App { render_context: Option, slice_pipeline: Option, render_pipeline: Option, + #[allow(dead_code)] // keeps ECS world alive alongside its derived GPU geometry world: World, geometry: RenderableGeometry, camera: Camera4D, diff --git a/examples/03_physics_demo.rs b/examples/03_physics_demo.rs index c1d0b0f..dbcbc30 100644 --- a/examples/03_physics_demo.rs +++ b/examples/03_physics_demo.rs @@ -198,13 +198,12 @@ impl ApplicationHandler for App { match event { WindowEvent::CloseRequested => event_loop.exit(), - WindowEvent::KeyboardInput { event, .. } => { - if event.state == ElementState::Pressed { + WindowEvent::KeyboardInput { event, .. } + if event.state == ElementState::Pressed => { if let PhysicalKey::Code(KeyCode::Escape) = event.physical_key { event_loop.exit(); } } - } WindowEvent::Resized(size) => { if let Some(ctx) = &mut self.render_context { diff --git a/examples/04_camera_exploration.rs b/examples/04_camera_exploration.rs index 17e6b83..723cefe 100644 --- a/examples/04_camera_exploration.rs +++ b/examples/04_camera_exploration.rs @@ -52,6 +52,7 @@ struct App { render_context: Option, slice_pipeline: Option, render_pipeline: Option, + #[allow(dead_code)] // keeps ECS world alive alongside its derived GPU geometry world: World, geometry: RenderableGeometry, camera: Camera4D,