From 9cae03e3ac29be333609d80abee6fd8e54f413af Mon Sep 17 00:00:00 2001 From: Denis Avvakumov Date: Sun, 2 Nov 2025 14:59:16 +0200 Subject: [PATCH 1/2] Update to Bevy 0.17 --- .github/workflows/main.yml | 4 +- .vscode/tasks.json | 2 +- bevy_rapier2d/Cargo.toml | 28 ++-- .../examples/custom_system_setup2.rs | 4 +- bevy_rapier2d/examples/events2.rs | 4 +- bevy_rapier2d/examples/player_movement2.rs | 2 +- bevy_rapier2d/examples/serialization2.rs | 2 +- bevy_rapier2d/examples/testbed2.rs | 30 ++-- bevy_rapier2d/examples/voxels2_no_collider.rs | 119 ++++++++++++++++ bevy_rapier3d/Cargo.toml | 18 +-- .../examples/character_controller3.rs | 6 +- .../examples/custom_system_setup3.rs | 4 +- bevy_rapier3d/examples/despawn3.rs | 2 +- bevy_rapier3d/examples/events3.rs | 4 +- bevy_rapier3d/examples/joints_despawn3.rs | 2 +- bevy_rapier3d/examples/picking3.rs | 24 ++-- .../examples/rapier_context_component.rs | 2 +- bevy_rapier3d/examples/static_trimesh3.rs | 2 +- bevy_rapier3d/examples/testbed3.rs | 30 ++-- bevy_rapier_benches3d/Cargo.toml | 4 +- ci/Cargo.toml | 2 +- src/dynamics/rigid_body.rs | 12 +- src/geometry/collider_impl.rs | 2 +- src/geometry/shape_views/voxels.rs | 87 +++++++++--- src/geometry/to_bevy_mesh.rs | 33 ++--- src/picking_backend/mod.rs | 19 ++- src/pipeline/events.rs | 15 +- src/plugin/context/mod.rs | 12 +- .../rapier_context_systemparam.rs | 4 +- src/plugin/narrow_phase.rs | 4 +- src/plugin/plugin.rs | 52 +++---- src/plugin/systems/collider.rs | 8 +- src/plugin/systems/mod.rs | 16 +-- src/plugin/systems/remove.rs | 8 +- src/plugin/systems/rigid_body.rs | 4 +- src/plugin/systems/writeback.rs | 2 +- src/reflect/mod.rs | 130 +++++++++++++++++- src/render/mod.rs | 4 +- 38 files changed, 508 insertions(+), 199 deletions(-) create mode 100644 bevy_rapier2d/examples/voxels2_no_collider.rs diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ec064eb4..a0b69042 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,7 +31,7 @@ jobs: - uses: Swatinem/rust-cache@v2 with: prefix-key: ${{ env.RUST_CACHE_KEY }} - - run: sudo apt update && sudo apt-get install pkg-config libx11-dev libasound2-dev libudev-dev + - run: sudo apt update && sudo apt-get install pkg-config libx11-dev libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev - name: Cargo doc run: cargo doc --no-deps test: @@ -46,7 +46,7 @@ jobs: - uses: Swatinem/rust-cache@v2 with: prefix-key: ${{ env.RUST_CACHE_KEY }} - - run: sudo apt update && sudo apt-get install pkg-config libx11-dev libasound2-dev libudev-dev + - run: sudo apt update && sudo apt-get install pkg-config libx11-dev libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev - run: cargo install cargo-all-features - name: Clippy for bevy_rapier2d run: cargo clippy --verbose -p bevy_rapier2d --examples diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 353fdeeb..faf5ff73 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -48,4 +48,4 @@ } } ] -} \ No newline at end of file +} diff --git a/bevy_rapier2d/Cargo.toml b/bevy_rapier2d/Cargo.toml index 702ad705..62c0b894 100644 --- a/bevy_rapier2d/Cargo.toml +++ b/bevy_rapier2d/Cargo.toml @@ -64,27 +64,37 @@ async-collider = [ to-bevy-mesh = ["bevy/bevy_render", "bevy/bevy_asset"] [dependencies] -bevy = { version = "0.16.0", default-features = false, features = ["std"] } -nalgebra = { version = "0.33", features = ["convert-glam029"] } -rapier2d = "0.27.0-beta.0" -bitflags = "2.4" +bevy = { version = "0.17.2", default-features = false, features = ["std"] } +nalgebra = { version = "0.34.1", features = ["convert-glam030"] } +rapier2d = "0.30.1" +bitflags = "2.10.0" log = "0.4" serde = { version = "1", features = ["derive"], optional = true } [dev-dependencies] -bevy = { version = "0.16.0", default-features = false, features = [ +bevy = { version = "0.17.2", default-features = false, features = [ "x11", "bevy_state", "bevy_window", "bevy_debug_stepping", "bevy_log", + "bevy_text", + "default_font", + "bevy_winit", + "bevy_render", + "bevy_core_pipeline", + "bevy_sprite", + "bevy_sprite_render", + "bevy_gizmos", + "bevy_color", + "bevy_camera", ] } oorandom = "11" approx = "0.5.1" -glam = { version = "0.29", features = ["approx"] } -bevy-inspector-egui = "0.31" -bevy_egui = "0.34" -bevy_mod_debugdump = "0.13" +glam = { version = "0.30.9", features = ["approx"] } +bevy-inspector-egui = "0.35.0" +bevy_egui = "0.38.0" +bevy_mod_debugdump = "0.14.0" serde_json = "1.0" [package.metadata.docs.rs] diff --git a/bevy_rapier2d/examples/custom_system_setup2.rs b/bevy_rapier2d/examples/custom_system_setup2.rs index 2fefc7b4..26a8e0ab 100644 --- a/bevy_rapier2d/examples/custom_system_setup2.rs +++ b/bevy_rapier2d/examples/custom_system_setup2.rs @@ -1,4 +1,4 @@ -use bevy::{diagnostic::FrameCount, prelude::*, transform::TransformSystem}; +use bevy::{diagnostic::FrameCount, prelude::*}; use bevy_rapier2d::prelude::*; fn main() { @@ -24,7 +24,7 @@ fn main() { PhysicsSet::Writeback, ) .chain() - .before(TransformSystem::TransformPropagate), + .before(TransformSystems::Propagate), ); app.add_systems( diff --git a/bevy_rapier2d/examples/events2.rs b/bevy_rapier2d/examples/events2.rs index bb93c249..195e06bf 100644 --- a/bevy_rapier2d/examples/events2.rs +++ b/bevy_rapier2d/examples/events2.rs @@ -23,8 +23,8 @@ pub fn setup_graphics(mut commands: Commands) { } pub fn display_events( - mut collision_events: EventReader, - mut contact_force_events: EventReader, + mut collision_events: MessageReader, + mut contact_force_events: MessageReader, ) { for collision_event in collision_events.read() { println!("Received collision event: {collision_event:?}"); diff --git a/bevy_rapier2d/examples/player_movement2.rs b/bevy_rapier2d/examples/player_movement2.rs index f122310a..1c10bc8f 100644 --- a/bevy_rapier2d/examples/player_movement2.rs +++ b/bevy_rapier2d/examples/player_movement2.rs @@ -6,7 +6,7 @@ fn main() { .add_plugins(( DefaultPlugins.set(WindowPlugin { primary_window: Some(Window { - resolution: WindowResolution::new(1000., 1000.), + resolution: WindowResolution::new(1000, 1000), title: "Player Movement Example".to_string(), ..default() }), diff --git a/bevy_rapier2d/examples/serialization2.rs b/bevy_rapier2d/examples/serialization2.rs index 73accb7c..47997b35 100644 --- a/bevy_rapier2d/examples/serialization2.rs +++ b/bevy_rapier2d/examples/serialization2.rs @@ -35,6 +35,6 @@ pub fn print_physics(_context: ReadRapierContext) { panic!("Example 'serialization' should be run with '--features serde-serialize'."); } -fn quit(mut exit_event: EventWriter) { +fn quit(mut exit_event: MessageWriter) { exit_event.write(AppExit::Success); } diff --git a/bevy_rapier2d/examples/testbed2.rs b/bevy_rapier2d/examples/testbed2.rs index af9088b3..29373938 100644 --- a/bevy_rapier2d/examples/testbed2.rs +++ b/bevy_rapier2d/examples/testbed2.rs @@ -14,6 +14,7 @@ mod rope_joint2; mod voxels2; use bevy::{ + camera::visibility::RenderLayers, ecs::world::error::{EntityDespawnError, EntityMutableFetchError}, prelude::*, }; @@ -67,9 +68,7 @@ fn main() { app.init_resource::() .add_plugins(( DefaultPlugins, - EguiPlugin { - enable_multipass_for_primary_context: false, - }, + EguiPlugin::default(), RapierPhysicsPlugin::::pixels_per_meter(10.0), RapierDebugRenderPlugin::default(), WorldInspectorPlugin::new(), @@ -92,6 +91,17 @@ fn main() { (Examples::PlayerMovement2, "PlayerMovement2").into(), ])) .init_resource::() + .add_systems(PreStartup, |mut commands: Commands| { + commands.spawn(( + Camera2d, + bevy_egui::PrimaryEguiContext, + Camera { + order: 999, + ..Default::default() + }, + RenderLayers::none(), + )); + }) // //boxes2 .add_systems( @@ -254,17 +264,21 @@ fn main() { } fn init(world: &mut World) { - //save all entities that are in the world before setting up any example + // save all entities that are in the world before setting up any example // to be able to always return to this state when switching from one example to the other - world.resource_mut::().entities_before = - world.iter_entities().map(|e| e.id()).collect::>(); + world.resource_mut::().entities_before = world + .query::() + .iter(world) + .map(|e| e.id()) + .collect::>(); } fn cleanup(world: &mut World) { let keep_alive = world.resource::().entities_before.clone(); let remove = world - .iter_entities() + .query::() + .iter(world) .filter_map(|e| (!keep_alive.contains(&e.id())).then_some(e.id())) .collect::>(); @@ -290,7 +304,7 @@ fn ui_example_system( mut current_example: ResMut, examples_available: Res, ) { - egui::Window::new("Testbed").show(contexts.ctx_mut(), |ui| { + egui::Window::new("Testbed").show(contexts.ctx_mut().unwrap(), |ui| { let mut changed = false; egui::ComboBox::from_label("example") .width(150.0) diff --git a/bevy_rapier2d/examples/voxels2_no_collider.rs b/bevy_rapier2d/examples/voxels2_no_collider.rs new file mode 100644 index 00000000..67e8b9bf --- /dev/null +++ b/bevy_rapier2d/examples/voxels2_no_collider.rs @@ -0,0 +1,119 @@ +use bevy::prelude::*; +use bevy_rapier2d::geometry::RapierColliderHandle; +use bevy_rapier2d::prelude::*; + +fn main() { + App::new() + .insert_resource(ClearColor(Color::srgb( + 0xF9 as f32 / 255.0, + 0xF9 as f32 / 255.0, + 0xFF as f32 / 255.0, + ))) + .add_plugins(( + DefaultPlugins, + RapierPhysicsPlugin::::pixels_per_meter(10.0), + RapierDebugRenderPlugin::default(), + )) + .add_systems(Startup, setup) + .add_systems(Update, (check_collisions, check_collider_enabled)) + .run(); +} + +fn setup(mut commands: Commands) { + // 2D camera + commands.spawn((Camera2d, Transform::from_xyz(0.0, 20.0, 0.0))); + + let scale = 15f32; + + let nx = 50; + for i in 0..nx { + for j in 0..10 { + let falling_objects = (j + i) % 3; + let ball_radius = 0.5 * scale; + + let collider = match falling_objects { + 0 => Collider::ball(ball_radius), + 1 => Collider::cuboid(ball_radius, ball_radius), + 2 => Collider::capsule_y(ball_radius, ball_radius), + _ => unreachable!(), + }; + + commands + .spawn(( + Transform::from_xyz( + (i as f32 * 2.0 - nx as f32 / 2.0) * scale, + (20.0 + j as f32 * 2.0) * scale, + 0.0, + ), + RigidBody::Dynamic, + AdditionalMassProperties::Mass(1.0), + )) + .with_children(|parent| { + parent.spawn((collider, ColliderDisabled)); + }); + } + } + + let polyline = [ + Vec2::new(0.0, 0.0), + Vec2::new(0.0, 10.0), + Vec2::new(7.0, 4.0), + Vec2::new(14.0, 10.0), + Vec2::new(14.0, 0.0), + Vec2::new(13.0, 7.0), + Vec2::new(7.0, 2.0), + Vec2::new(1.0, 7.0), + ] + .iter() + .map(|p| p * scale) + .collect::>(); + let indices: Vec<_> = (0..polyline.len() as u32) + .map(|i| [i, (i + 1) % polyline.len() as u32]) + .collect(); + + commands.spawn(( + Transform::from_xyz(-20.0 * scale, -10.0 * scale, 0.0), + Collider::voxelized_mesh(&polyline, &indices, 0.2 * scale, FillMode::default()), + ColliderDisabled, + )); + + let voxel_size = Vec2::new(scale, scale); + let voxels: Vec<_> = (0..300) + .map(|i| { + let y = (i as f32 / 20.0).sin().clamp(-0.5, 0.5) * 20.0; + Vec2::new((i as f32 - 125.0) * voxel_size.x / 2.0, y * voxel_size.y) + }) + .collect(); + commands.spawn(( + Transform::from_xyz(0.0, 0.0, 0.0), + Collider::voxels_from_points(voxel_size, &voxels), + )); +} + +fn check_collisions(mut collision_events: MessageReader) { + for event in collision_events.read() { + info!("Collision event: {:?}", event); + } +} + +fn check_collider_enabled( + rapier_context: ReadRapierContext, + query: Query<&RapierColliderHandle, With>, +) { + let context = match rapier_context.single() { + Ok(c) => c, + Err(_) => return, + }; + + for rapier_handle in &query { + let handle = rapier_handle.0; + if let Some(col) = context.colliders.colliders.get(handle) { + if col.is_enabled() { + info!( + "FIX ME: Voxel collider should NOT be enabled: {}", + col.is_enabled() + ); + } + } + } +} diff --git a/bevy_rapier3d/Cargo.toml b/bevy_rapier3d/Cargo.toml index 93a16cfd..12b4db41 100644 --- a/bevy_rapier3d/Cargo.toml +++ b/bevy_rapier3d/Cargo.toml @@ -65,15 +65,15 @@ async-collider = [ to-bevy-mesh = ["bevy/bevy_render", "bevy/bevy_asset"] [dependencies] -bevy = { version = "0.16.0", default-features = false, features = ["std"] } -nalgebra = { version = "0.33", features = ["convert-glam029"] } -rapier3d = "0.27.0-beta.0" -bitflags = "2.4" +bevy = { version = "0.17.2", default-features = false, features = ["std"] } +nalgebra = { version = "0.34.1", features = ["convert-glam030"] } +rapier3d = "0.30.1" +bitflags = "2.10.0" log = "0.4" serde = { version = "1", features = ["derive"], optional = true } [dev-dependencies] -bevy = { version = "0.16.0", default-features = false, features = [ +bevy = { version = "0.17.2", default-features = false, features = [ "bevy_window", "x11", "tonemapping_luts", @@ -85,10 +85,10 @@ bevy = { version = "0.16.0", default-features = false, features = [ "bevy_log", ] } approx = "0.5.1" -glam = { version = "0.29", features = ["approx"] } -bevy-inspector-egui = "0.31" -bevy_egui = "0.34" -bevy_mod_debugdump = "0.13" +glam = { version = "0.30.9", features = ["approx"] } +bevy-inspector-egui = "0.35.0" +bevy_egui = "0.38.0" +bevy_mod_debugdump = "0.14.0" [package.metadata.docs.rs] # Enable all the features when building the docs on docs.rs diff --git a/bevy_rapier3d/examples/character_controller3.rs b/bevy_rapier3d/examples/character_controller3.rs index 03c842c5..f1eed068 100644 --- a/bevy_rapier3d/examples/character_controller3.rs +++ b/bevy_rapier3d/examples/character_controller3.rs @@ -1,5 +1,5 @@ use bevy::{ - input::{mouse::MouseMotion, InputSystem}, + input::{mouse::MouseMotion, InputSystems}, prelude::*, }; use bevy_rapier3d::{control::KinematicCharacterController, prelude::*}; @@ -25,7 +25,7 @@ fn main() { RapierDebugRenderPlugin::default(), )) .add_systems(Startup, (setup_player, setup_map)) - .add_systems(PreUpdate, handle_input.after(InputSystem)) + .add_systems(PreUpdate, handle_input.after(InputSystems)) .add_systems(Update, player_look) .add_systems(FixedUpdate, player_movement) .run(); @@ -112,7 +112,7 @@ fn handle_input( keyboard: Res>, mut movement: ResMut, mut look: ResMut, - mut mouse_events: EventReader, + mut mouse_events: MessageReader, ) { if keyboard.pressed(KeyCode::KeyW) { movement.z -= 1.0; diff --git a/bevy_rapier3d/examples/custom_system_setup3.rs b/bevy_rapier3d/examples/custom_system_setup3.rs index 8d7eaba5..2fb61bd4 100644 --- a/bevy_rapier3d/examples/custom_system_setup3.rs +++ b/bevy_rapier3d/examples/custom_system_setup3.rs @@ -1,4 +1,4 @@ -use bevy::{diagnostic::FrameCount, prelude::*, transform::TransformSystem}; +use bevy::{diagnostic::FrameCount, prelude::*}; use bevy_rapier3d::prelude::*; fn main() { @@ -24,7 +24,7 @@ fn main() { PhysicsSet::Writeback, ) .chain() - .before(TransformSystem::TransformPropagate), + .before(TransformSystems::Propagate), ); app.add_systems( diff --git a/bevy_rapier3d/examples/despawn3.rs b/bevy_rapier3d/examples/despawn3.rs index e6eb717e..b841e973 100644 --- a/bevy_rapier3d/examples/despawn3.rs +++ b/bevy_rapier3d/examples/despawn3.rs @@ -95,7 +95,7 @@ pub fn despawn( mut despawn: ResMut, query: Query>, ) { - if despawn.timer.tick(time.delta()).finished() { + if despawn.timer.tick(time.delta()).is_finished() { for entity in &query { println!("Despawning ground entity"); commands.entity(entity).despawn(); diff --git a/bevy_rapier3d/examples/events3.rs b/bevy_rapier3d/examples/events3.rs index 9f1a23e8..bd56214d 100644 --- a/bevy_rapier3d/examples/events3.rs +++ b/bevy_rapier3d/examples/events3.rs @@ -26,8 +26,8 @@ pub fn setup_graphics(mut commands: Commands) { } pub fn display_events( - mut collision_events: EventReader, - mut contact_force_events: EventReader, + mut collision_events: MessageReader, + mut contact_force_events: MessageReader, ) { for collision_event in collision_events.read() { println!("Received collision event: {collision_event:?}"); diff --git a/bevy_rapier3d/examples/joints_despawn3.rs b/bevy_rapier3d/examples/joints_despawn3.rs index cb858428..573f4a36 100644 --- a/bevy_rapier3d/examples/joints_despawn3.rs +++ b/bevy_rapier3d/examples/joints_despawn3.rs @@ -273,7 +273,7 @@ pub fn despawn( mut despawn: ResMut, query: Query>, ) { - if despawn.timer.tick(time.delta()).finished() { + if despawn.timer.tick(time.delta()).is_finished() { for entity in &query { println!("Despawning joint entity"); commands.entity(entity).despawn(); diff --git a/bevy_rapier3d/examples/picking3.rs b/bevy_rapier3d/examples/picking3.rs index 13a462e1..8c003526 100644 --- a/bevy_rapier3d/examples/picking3.rs +++ b/bevy_rapier3d/examples/picking3.rs @@ -45,15 +45,13 @@ pub fn setup_physics(mut commands: Commands) { }, )) .observe(on_click_spawn_cube) + .observe(|out: On>, mut texts: Query<&mut TextColor>| { + let mut text_color = texts.get_mut(out.event().entity).unwrap(); + text_color.0 = Color::WHITE; + }) .observe( - |out: Trigger>, mut texts: Query<&mut TextColor>| { - let mut text_color = texts.get_mut(out.target()).unwrap(); - text_color.0 = Color::WHITE; - }, - ) - .observe( - |over: Trigger>, mut texts: Query<&mut TextColor>| { - let mut color = texts.get_mut(over.target()).unwrap(); + |over: On>, mut texts: Query<&mut TextColor>| { + let mut color = texts.get_mut(over.event().entity).unwrap(); color.0 = bevy::color::palettes::tailwind::CYAN_400.into(); }, ); @@ -67,11 +65,7 @@ pub fn setup_physics(mut commands: Commands) { )); } -fn on_click_spawn_cube( - _click: Trigger>, - mut commands: Commands, - mut num: Local, -) { +fn on_click_spawn_cube(_click: On>, mut commands: Commands, mut num: Local) { let rad = 0.25; let colors = [ Hsla::hsl(220.0, 1.0, 0.3), @@ -92,8 +86,8 @@ fn on_click_spawn_cube( *num += 1; } -fn on_drag_rotate(drag: Trigger>, mut transforms: Query<&mut Transform>) { - if let Ok(mut transform) = transforms.get_mut(drag.target()) { +fn on_drag_rotate(drag: On>, mut transforms: Query<&mut Transform>) { + if let Ok(mut transform) = transforms.get_mut(drag.event().entity) { transform.rotate_y(drag.delta.x * 0.02); transform.rotate_x(drag.delta.y * 0.02); } diff --git a/bevy_rapier3d/examples/rapier_context_component.rs b/bevy_rapier3d/examples/rapier_context_component.rs index 3f4056f0..45263216 100644 --- a/bevy_rapier3d/examples/rapier_context_component.rs +++ b/bevy_rapier3d/examples/rapier_context_component.rs @@ -19,7 +19,7 @@ fn main() { /// Demonstrates how to access a more specific component of [`RapierContext`] fn display_nb_colliders( query_context: Query<&RapierContextColliders, With>, - mut exit: EventWriter, + mut exit: MessageWriter, ) -> Result<()> { let nb_colliders = query_context.single()?.colliders.len(); println!("There are {nb_colliders} colliders."); diff --git a/bevy_rapier3d/examples/static_trimesh3.rs b/bevy_rapier3d/examples/static_trimesh3.rs index 5bc41382..fdff1780 100644 --- a/bevy_rapier3d/examples/static_trimesh3.rs +++ b/bevy_rapier3d/examples/static_trimesh3.rs @@ -123,7 +123,7 @@ pub fn ball_spawner(mut commands: Commands, time: Res