diff --git a/CHANGELOG.md b/CHANGELOG.md index 936daff..470adf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +- Bevy 0.6 - Rust 2021 edition - Clippy extra restrictions diff --git a/Cargo.toml b/Cargo.toml index 10eb59d..e7b6de2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,16 +19,36 @@ debug = ["bevy_prototype_debug_lines"] [dependencies] [dependencies.bevy] -version = "0.5" +version = "0.6" default-features = false [dependencies.bevy_prototype_debug_lines] -version = "0.3" +version = "0.6" optional = true [dev-dependencies] [dev-dependencies.bevy] -version = "0.5" -features = ["render", "bevy_winit", "png", "x11", "bevy_wgpu"] -default-features = false \ No newline at end of file +version = "0.6" +features = ["render", "bevy_winit", "x11"] +default-features = false + +[[example]] +name = "2d_cloth" +required-features = ["debug"] + +[[example]] +name = "2d_cloth_cutter" +required-features = ["debug"] + +[[example]] +name = "2d_line" +required-features = ["debug"] + +[[example]] +name = "3d_cloth" +required-features = ["debug"] + +[[example]] +name = "3d_line" +required-features = ["debug"] \ No newline at end of file diff --git a/README.md b/README.md index 9563340..4196d0c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# bevy_verlet +# Verlet Integration for Bevy [![workflow](https://github.com/ManevilleF/bevy_verlet/actions/workflows/rust.yml/badge.svg)](https://github.com/ManevilleF/bevy_verlet/actions/workflows/rust.yml) @@ -8,7 +8,7 @@ [![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/) [![Crates.io](https://img.shields.io/crates/v/bevy_verlet.svg)](https://crates.io/crates/bevy_verlet) [![Docs.rs](https://docs.rs/bevy_verlet/badge.svg)](https://docs.rs/bevy_verlet) -[![dependency status](https://deps.rs/crate/bevy_verlet/0.1.0/status.svg)](https://deps.rs/crate/bevy_verlet) +[![dependency status](https://deps.rs/crate/bevy_verlet/0.1.1/status.svg)](https://deps.rs/crate/bevy_verlet) Simple Verlet points and sticks implementation for bevy. @@ -28,7 +28,7 @@ Customize *friction* and *gravity* with the `VerletConfig` resource. 1. `debug` -This feature will add a *system* drawing debug lines for every stick using [bevy_prototype_debug_lines](https://crates.io/crates/bevy_prototype_debug_lines) +This feature will add a *system* drawing debug lines for every stick using [`bevy_prototype_debug_lines`](https://crates.io/crates/bevy_prototype_debug_lines) diff --git a/examples/2d_cloth.rs b/examples/2d_cloth.rs index 62e5001..6245158 100644 --- a/examples/2d_cloth.rs +++ b/examples/2d_cloth.rs @@ -2,7 +2,7 @@ use bevy::prelude::*; use bevy_verlet::{BevyVerletPlugin, VerletLocked, VerletPoint, VerletStick}; fn main() { - App::build() + App::new() .insert_resource(WindowDescriptor { title: "2D cloth".to_string(), width: 1000., @@ -11,14 +11,12 @@ fn main() { }) .add_plugins(DefaultPlugins) .add_plugin(BevyVerletPlugin::default()) - .add_startup_system(setup.system()) + .add_startup_system(setup) .run(); } -fn setup(mut commands: Commands, mut materials: ResMut>) { +fn setup(mut commands: Commands) { commands.spawn_bundle(OrthographicCameraBundle::new_2d()); - let material = materials.add(Color::WHITE.into()); - let fixed_material = materials.add(Color::RED.into()); let stick_length: f32 = 35.; let (origin_x, origin_y) = (-450., 350.); let (points_x_count, points_y_count) = (30, 15); @@ -26,8 +24,11 @@ fn setup(mut commands: Commands, mut materials: ResMut>) { for j in 0..points_y_count { for i in 0..points_x_count { let mut cmd = commands.spawn_bundle(SpriteBundle { - sprite: Sprite::new(Vec2::splat(10.)), - material: material.clone(), + sprite: Sprite { + color: if j == 0 { Color::RED } else { Color::WHITE }, + custom_size: Some(Vec2::splat(10.)), + ..Default::default() + }, transform: Transform::from_xyz( origin_x + (30. * i as f32), origin_y + (-30. * (j + i / 3) as f32), @@ -38,7 +39,7 @@ fn setup(mut commands: Commands, mut materials: ResMut>) { cmd.insert(VerletPoint::default()) .insert(Name::new(format!("Point {}", i))); if j == 0 { - cmd.insert(VerletLocked {}).insert(fixed_material.clone()); + cmd.insert(VerletLocked); } entities.push(cmd.id()); } diff --git a/examples/2d_cloth_cutter.rs b/examples/2d_cloth_cutter.rs index cb086cd..f6906df 100644 --- a/examples/2d_cloth_cutter.rs +++ b/examples/2d_cloth_cutter.rs @@ -4,7 +4,7 @@ use bevy_verlet::{ }; fn main() { - App::build() + App::new() .insert_resource(VerletConfig { parallel_processing_batch_size: Some(1000), sticks_computation_depth: 2, @@ -18,8 +18,8 @@ fn main() { }) .add_plugins(DefaultPlugins) .add_plugin(BevyVerletPlugin::default()) - .add_startup_system(setup.system()) - .add_system(cut_sticks.system()) + .add_startup_system(setup) + .add_system(cut_sticks) .run(); } @@ -41,7 +41,7 @@ fn setup(mut commands: Commands) { .insert(VerletPoint::default()) .insert(Name::new(format!("Point {}", i))); if j == 0 && i % 2 == 0 { - cmd.insert(VerletLocked {}); + cmd.insert(VerletLocked); } entities.push(cmd.id()); } diff --git a/examples/2d_line.rs b/examples/2d_line.rs index eca1a82..957e7d9 100644 --- a/examples/2d_line.rs +++ b/examples/2d_line.rs @@ -2,7 +2,7 @@ use bevy::prelude::*; use bevy_verlet::{BevyVerletPlugin, VerletLocked, VerletPoint, VerletStick}; fn main() { - App::build() + App::new() .insert_resource(WindowDescriptor { title: "2D line".to_string(), width: 1000., @@ -11,9 +11,9 @@ fn main() { }) .add_plugins(DefaultPlugins) .add_plugin(BevyVerletPlugin::default()) - .add_startup_system(setup_camera.system()) - .add_startup_system(setup_free_line.system()) - .add_startup_system(setup_fixed_line.system()) + .add_startup_system(setup_camera) + .add_startup_system(setup_free_line) + .add_startup_system(setup_fixed_line) .run(); } @@ -21,21 +21,17 @@ fn setup_camera(mut commands: Commands) { commands.spawn_bundle(OrthographicCameraBundle::new_2d()); } -fn setup_free_line(mut commands: Commands, mut materials: ResMut>) { - let material = materials.add(Color::WHITE.into()); - let fixed_material = materials.add(Color::RED.into()); +fn setup_free_line(mut commands: Commands) { let stick_length: f32 = 50.; let points_count = 10; let mut previous_entity = None; for i in 0..=points_count { - let mut cmd = commands.spawn_bundle(sprite_bundle( - material.clone(), - Vec2::new(50. * i as f32, 300.), - )); + let mut cmd = + commands.spawn_bundle(sprite_bundle(Color::WHITE, Vec2::new(50. * i as f32, 300.))); cmd.insert(VerletPoint::default()) .insert(Name::new(format!("Point {}", i))); if previous_entity.is_none() { - cmd.insert(VerletLocked {}).insert(fixed_material.clone()); + cmd.insert(VerletLocked); } let entity = cmd.id(); if let Some(e) = previous_entity { @@ -52,22 +48,20 @@ fn setup_free_line(mut commands: Commands, mut materials: ResMut>) { - let material = materials.add(Color::WHITE.into()); - let fixed_material = materials.add(Color::RED.into()); +fn setup_fixed_line(mut commands: Commands) { let stick_length: f32 = 35.; let points_count = 20; let start_pos = -450.; let mut previous_entity = None; for i in 0..=points_count { let mut cmd = commands.spawn_bundle(sprite_bundle( - material.clone(), + Color::WHITE, Vec2::new(start_pos + 30. * i as f32, 0.), )); cmd.insert(VerletPoint::default()) .insert(Name::new(format!("Point {}", i))); if previous_entity.is_none() || i == points_count { - cmd.insert(VerletLocked {}).insert(fixed_material.clone()); + cmd.insert(VerletLocked); } let entity = cmd.id(); if let Some(e) = previous_entity { @@ -84,10 +78,13 @@ fn setup_fixed_line(mut commands: Commands, mut materials: ResMut, pos: Vec2) -> SpriteBundle { +fn sprite_bundle(color: Color, pos: Vec2) -> SpriteBundle { SpriteBundle { - sprite: Sprite::new(Vec2::splat(10.)), - material, + sprite: Sprite { + color, + custom_size: Some(Vec2::splat(10.)), + ..Default::default() + }, transform: Transform::from_xyz(pos.x, pos.y, 0.), ..Default::default() } diff --git a/examples/3d_cloth.rs b/examples/3d_cloth.rs index b9bfc56..083f716 100644 --- a/examples/3d_cloth.rs +++ b/examples/3d_cloth.rs @@ -2,7 +2,7 @@ use bevy::prelude::*; use bevy_verlet::{BevyVerletPlugin, VerletConfig, VerletLocked, VerletPoint, VerletStick}; fn main() { - App::build() + App::new() .insert_resource(WindowDescriptor { title: "3D cloth".to_string(), width: 1000., @@ -11,7 +11,7 @@ fn main() { }) .add_plugins(DefaultPlugins) .add_plugin(BevyVerletPlugin::default()) - .add_startup_system(setup.system()) + .add_startup_system(setup) .insert_resource(VerletConfig { sticks_computation_depth: 5, ..Default::default() @@ -50,7 +50,7 @@ fn setup( cmd.insert(VerletPoint::default()) .insert(Name::new(format!("Point {}", i))); if j == 0 { - cmd.insert(VerletLocked {}).insert(fixed_material.clone()); + cmd.insert(VerletLocked).insert(fixed_material.clone()); } entities.push(cmd.id()); } diff --git a/examples/3d_line.rs b/examples/3d_line.rs index 52001d9..28f59d3 100644 --- a/examples/3d_line.rs +++ b/examples/3d_line.rs @@ -2,7 +2,7 @@ use bevy::prelude::*; use bevy_verlet::{BevyVerletPlugin, VerletConfig, VerletLocked, VerletPoint, VerletStick}; fn main() { - App::build() + App::new() .insert_resource(WindowDescriptor { title: "3D line".to_string(), width: 1000., @@ -11,9 +11,9 @@ fn main() { }) .add_plugins(DefaultPlugins) .add_plugin(BevyVerletPlugin::default()) - .add_startup_system(setup_camera.system()) - .add_startup_system(setup_free_line.system()) - .add_startup_system(setup_fixed_line.system()) + .add_startup_system(setup_camera) + .add_startup_system(setup_free_line) + .add_startup_system(setup_fixed_line) .insert_resource(VerletConfig { sticks_computation_depth: 5, ..Default::default() @@ -48,7 +48,7 @@ fn setup_free_line( cmd.insert(VerletPoint::default()) .insert(Name::new(format!("Point {}", i))); if previous_entity.is_none() { - cmd.insert(VerletLocked {}).insert(fixed_material.clone()); + cmd.insert(VerletLocked).insert(fixed_material.clone()); } let entity = cmd.id(); if let Some(e) = previous_entity { @@ -86,7 +86,7 @@ fn setup_fixed_line( cmd.insert(VerletPoint::default()) .insert(Name::new(format!("Point {}", i))); if previous_entity.is_none() || i == points_count { - cmd.insert(VerletLocked {}).insert(fixed_material.clone()); + cmd.insert(VerletLocked).insert(fixed_material.clone()); } let entity = cmd.id(); if let Some(e) = previous_entity { diff --git a/src/components/locked.rs b/src/components/locked.rs index fa7b1e1..528110e 100644 --- a/src/components/locked.rs +++ b/src/components/locked.rs @@ -1,5 +1,7 @@ +use bevy::prelude::{Component, Reflect}; + /// Component preventing application of [`VerletPoint`][VerletPoint] physics. /// /// [VerletPoint]: struct.VerletPoint.html -#[derive(Debug, Copy, Clone)] -pub struct VerletLocked {} +#[derive(Debug, Copy, Clone, Component, Reflect)] +pub struct VerletLocked; diff --git a/src/components/point.rs b/src/components/point.rs index bf181cc..3fb05a4 100644 --- a/src/components/point.rs +++ b/src/components/point.rs @@ -1,14 +1,8 @@ -use bevy::math::Vec3; +use bevy::prelude::{Component, Reflect, Vec3}; /// Main verlet physics component. /// Any entity with this component will have physics applied to it -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Component, Default, Reflect)] pub struct VerletPoint { pub(crate) old_position: Option, } - -impl Default for VerletPoint { - fn default() -> Self { - Self { old_position: None } - } -} diff --git a/src/components/stick.rs b/src/components/stick.rs index 2584a2c..6598018 100644 --- a/src/components/stick.rs +++ b/src/components/stick.rs @@ -1,9 +1,9 @@ -use bevy::prelude::Entity; +use bevy::prelude::{Component, Entity, Reflect}; /// Constraint component between two [`VerletPoint`][VerletPoint]. /// /// [VerletPoint]: struct.VerletPoint.html -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Component, Reflect)] pub struct VerletStick { /// Start `VerletPoint` entity pub point_a_entity: Entity, diff --git a/src/components/stick_max_tension.rs b/src/components/stick_max_tension.rs index c666131..62a17ee 100644 --- a/src/components/stick_max_tension.rs +++ b/src/components/stick_max_tension.rs @@ -1,3 +1,5 @@ +use bevy::prelude::{Component, Reflect}; + /// Component adding a maximum tension to a [`VerletStick`][VerletStick] /// /// The stick will break when its size becomes bigger than its `length` multiplied by this factor @@ -6,5 +8,5 @@ /// If you set it to `2.0` the stick will break when stretched to twice its `length` /// /// [VerletStick]: struct.VerletStick.html -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Component, Reflect)] pub struct VerletStickMaxTension(pub f32); diff --git a/src/lib.rs b/src/lib.rs index 78a1fab..ca8f301 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -//! # Bevy Verlet +//! # Verlet Integration for Bevy //! //! [![workflow](https://github.com/ManevilleF/bevy_verlet/actions/workflows/rust.yml/badge.svg)](https://github.com/ManevilleF/bevy_verlet/actions/workflows/rust.yml) //! @@ -31,16 +31,16 @@ #![forbid(missing_docs)] #![forbid(unsafe_code)] #![warn( - clippy::all, - clippy::correctness, - clippy::suspicious, - clippy::style, - clippy::complexity, - clippy::perf, clippy::nursery, - nonstandard_style + clippy::pedantic, + nonstandard_style, + rustdoc::broken_intra_links +)] +#![allow( + clippy::default_trait_access, + clippy::module_name_repetitions, + clippy::redundant_pub_crate )] -#![allow(clippy::module_name_repetitions, clippy::redundant_pub_crate)] pub use {components::*, resources::*}; @@ -62,20 +62,15 @@ pub struct BevyVerletPlugin { } impl Plugin for BevyVerletPlugin { - fn build(&self, app: &mut AppBuilder) { + fn build(&self, app: &mut App) { let system_set = SystemSet::new() .with_system( systems::points::update_points - .system() .label("points") .after("sticks"), ) - .with_system(systems::sticks::update_sticks.system().label("sticks")) - .with_system( - systems::sticks::handle_stick_constraints - .system() - .after("sticks"), - ); + .with_system(systems::sticks::update_sticks.label("sticks")) + .with_system(systems::sticks::handle_stick_constraints.after("sticks")); let system_set = if let Some(step) = self.time_step { app.insert_resource(VerletTimeStep::FixedDeltaTime(step)); system_set.with_run_criteria(FixedTimestep::step(step)) @@ -86,9 +81,13 @@ impl Plugin for BevyVerletPlugin { app.add_system_set(system_set); #[cfg(feature = "debug")] { - app.add_plugin(DebugLinesPlugin); - app.add_system(systems::debug::debug_draw_sticks.system()); + app.add_plugin(DebugLinesPlugin::default()); + app.add_system(systems::debug::debug_draw_sticks); } + app.register_type::() + .register_type::() + .register_type::() + .register_type::(); log::info!("Loaded verlet plugin"); } } @@ -103,6 +102,8 @@ impl Default for BevyVerletPlugin { impl BevyVerletPlugin { /// Instantiates a new plugin with a custom time step + #[must_use] + #[inline] pub const fn new(time_step: f64) -> Self { Self { time_step: Some(time_step), diff --git a/src/resources/config.rs b/src/resources/config.rs index 95b581d..80a7b3a 100644 --- a/src/resources/config.rs +++ b/src/resources/config.rs @@ -1,4 +1,4 @@ -use bevy::math::{Vec2, Vec3}; +use bevy::math::{Vec2, Vec3, Vec3Swizzles}; /// Verlet physics configuration #[derive(Debug, Copy, Clone)] @@ -26,12 +26,16 @@ impl Default for VerletConfig { } impl VerletConfig { + #[must_use] + #[inline] pub(crate) fn friction_coefficient(&self) -> f32 { 1.0 - self.friction } /// Retrieves the `gravity` field without the `z` axis + #[must_use] + #[inline] pub fn gravity_2d(&self) -> Vec2 { - Vec2::new(self.gravity.x, self.gravity.y) + self.gravity.xy() } } diff --git a/src/systems/debug.rs b/src/systems/debug.rs index f25e7c5..8c6d35b 100644 --- a/src/systems/debug.rs +++ b/src/systems/debug.rs @@ -15,7 +15,6 @@ macro_rules! get_point_debug { }; } -#[cfg(feature = "debug")] fn draw_stick( stick: &VerletStick, points_query: &Query<&Transform, With>, @@ -25,7 +24,7 @@ fn draw_stick( Some((transform_a.translation, transform_b.translation)) } -#[cfg(feature = "debug")] +#[allow(clippy::needless_pass_by_value)] pub fn debug_draw_sticks( mut lines: ResMut, sticks_query: Query<&VerletStick>, diff --git a/src/systems/points.rs b/src/systems/points.rs index 0685574..d507fa1 100644 --- a/src/systems/points.rs +++ b/src/systems/points.rs @@ -11,7 +11,7 @@ fn update_point(transform: &mut Transform, point: &mut VerletPoint, gravity: Vec point.old_position = Some(position); } -#[allow(clippy::cast_possible_truncation)] +#[allow(clippy::needless_pass_by_value, clippy::cast_possible_truncation)] pub fn update_points( time_step: Res, mut points_query: Query<(&mut Transform, &mut VerletPoint), Without>, diff --git a/src/systems/sticks.rs b/src/systems/sticks.rs index eee2f9b..2282ccc 100644 --- a/src/systems/sticks.rs +++ b/src/systems/sticks.rs @@ -6,7 +6,7 @@ use bevy::prelude::*; macro_rules! get_point { ($res:expr) => { match $res { - Ok((p, locked)) => (p, locked.is_some()), + Ok((p, locked)) => (p.translation, locked.is_some()), Err(e) => { log::error!("Could not find point entity for stick: {}", e); continue; @@ -15,34 +15,37 @@ macro_rules! get_point { }; } -#[allow(clippy::type_complexity)] +#[allow( + clippy::type_complexity, + clippy::needless_pass_by_value, + clippy::similar_names +)] pub fn update_sticks( config: Option>, sticks_query: Query<&VerletStick>, mut points_query: QuerySet<( - Query<(&Transform, Option<&VerletLocked>), With>, - Query<&mut Transform, With>, + QueryState<(&Transform, Option<&VerletLocked>), With>, + QueryState<&mut Transform, With>, )>, ) { let config = config.map(|g| *g).unwrap_or_default(); for _ in 0..=config.sticks_computation_depth { for stick in sticks_query.iter() { - let (point_a, a_locked) = get_point!(points_query.q0().get(stick.point_a_entity)); - let (point_b, b_locked) = get_point!(points_query.q0().get(stick.point_b_entity)); + let (coords_a, a_locked) = get_point!(points_query.q0().get(stick.point_a_entity)); + let (coords_b, b_locked) = get_point!(points_query.q0().get(stick.point_b_entity)); if a_locked && b_locked { continue; } - let center: Vec3 = (point_a.translation + point_b.translation) / 2.; - let direction: Vec3 = (point_a.translation - point_b.translation).normalize(); + let center: Vec3 = (coords_a + coords_b) / 2.; + let direction: Vec3 = (coords_a - coords_b).normalize(); + let mut q1 = points_query.q1(); if !a_locked { - let mut point_a_transform = - points_query.q1_mut().get_mut(stick.point_a_entity).unwrap(); + let mut point_a_transform = q1.get_mut(stick.point_a_entity).unwrap(); point_a_transform.translation = center + direction * stick.length / 2.; } if !b_locked { - let mut point_b_transform = - points_query.q1_mut().get_mut(stick.point_b_entity).unwrap(); + let mut point_b_transform = q1.get_mut(stick.point_b_entity).unwrap(); point_b_transform.translation = center - direction * stick.length / 2.; } } @@ -77,6 +80,7 @@ fn handle_stick_constraint( } } +#[allow(clippy::needless_pass_by_value)] pub fn handle_stick_constraints( mut commands: Commands, sticks_query: Query<(Entity, &VerletStick, &VerletStickMaxTension)>,