diff --git a/bevy_rapier2d/Cargo.toml b/bevy_rapier2d/Cargo.toml index ddce9481..d6749f7b 100644 --- a/bevy_rapier2d/Cargo.toml +++ b/bevy_rapier2d/Cargo.toml @@ -59,6 +59,8 @@ bevy = { version = "0.14", default-features = false, features = [ oorandom = "11" approx = "0.5.1" glam = { version = "0.27", features = ["approx"] } +bevy-inspector-egui = "0.25.1" +bevy_egui = "0.28.0" [package.metadata.docs.rs] # Enable all the features when building the docs on docs.rs diff --git a/bevy_rapier2d/examples/testbed2.rs b/bevy_rapier2d/examples/testbed2.rs index e7a52a97..89c1c003 100644 --- a/bevy_rapier2d/examples/testbed2.rs +++ b/bevy_rapier2d/examples/testbed2.rs @@ -12,9 +12,11 @@ mod player_movement2; mod rope_joint2; use bevy::prelude::*; +use bevy_egui::{egui, EguiContexts, EguiPlugin}; +use bevy_inspector_egui::quick::WorldInspectorPlugin; use bevy_rapier2d::prelude::*; -#[derive(Debug, Clone, Eq, PartialEq, Default, Hash, States)] +#[derive(Debug, Reflect, Clone, Copy, Eq, PartialEq, Default, Hash, States)] pub enum Examples { #[default] None, @@ -25,25 +27,61 @@ pub enum Examples { Events2, Joints2, JointsDespawn2, - LockedRotation2, + LockedRotations2, MultipleColliders2, PlayerMovement2, } -#[derive(Resource, Default)] +#[derive(Resource, Default, Reflect)] struct ExamplesRes { entities_before: Vec, } +#[derive(Resource, Debug, Default, Reflect)] +struct ExampleSelected(pub usize); + +#[derive(Debug, Reflect)] +struct ExampleDefinition { + pub state: Examples, + pub name: &'static str, +} + +impl From<(Examples, &'static str)> for ExampleDefinition { + fn from((state, name): (Examples, &'static str)) -> Self { + Self { state, name } + } +} + +#[derive(Resource, Debug, Reflect)] +struct ExampleSet(pub Vec); + fn main() { let mut app = App::new(); - app.init_state::() - .init_resource::() + app.init_resource::() .add_plugins(( DefaultPlugins, + EguiPlugin, RapierPhysicsPlugin::::pixels_per_meter(10.0), RapierDebugRenderPlugin::default(), + WorldInspectorPlugin::new(), )) + .register_type::() + .register_type::() + .register_type::() + .init_state::() + .insert_resource(ExampleSet(vec![ + (Examples::Boxes2, "Boxes3").into(), + (Examples::RopeJoint2, "RopeJoint2").into(), + (Examples::DebugDespawn2, "DebugDespawn2").into(), + (Examples::Despawn2, "Despawn3").into(), + (Examples::Events2, "Events3").into(), + (Examples::Joints2, "Joints3").into(), + (Examples::JointsDespawn2, "JointsDespawn3").into(), + (Examples::LockedRotations2, "LockedRotations3").into(), + (Examples::MultipleColliders2, "MultipleColliders3").into(), + (Examples::PlayerMovement2, "PlayerMovement2").into(), + ])) + .init_resource::() // //boxes2 .add_systems( @@ -116,13 +154,13 @@ fn main() { // //locked rotations .add_systems( - OnEnter(Examples::LockedRotation2), + OnEnter(Examples::LockedRotations2), ( locked_rotations2::setup_graphics, locked_rotations2::setup_physics, ), ) - .add_systems(OnExit(Examples::LockedRotation2), cleanup) + .add_systems(OnExit(Examples::LockedRotations2), cleanup) // //multiple colliders .add_systems( @@ -162,7 +200,14 @@ fn main() { }, ) .add_systems(OnExit(Examples::None), init) - .add_systems(Update, check_toggle); + .add_systems( + Update, + ( + ui_example_system, + change_example.run_if(resource_changed::), + ) + .chain(), + ); app.run(); } @@ -187,25 +232,34 @@ fn cleanup(world: &mut World) { } } -fn check_toggle( - state: Res>, +fn change_example( + example_selected: Res, + examples_available: Res, mut next_state: ResMut>, - mouse_input: Res>, ) { - if mouse_input.just_pressed(MouseButton::Left) { - let next = match *state.get() { - Examples::None => Examples::Boxes2, - Examples::Boxes2 => Examples::RopeJoint2, - Examples::RopeJoint2 => Examples::DebugDespawn2, - Examples::DebugDespawn2 => Examples::Despawn2, - Examples::Despawn2 => Examples::Events2, - Examples::Events2 => Examples::Joints2, - Examples::Joints2 => Examples::JointsDespawn2, - Examples::JointsDespawn2 => Examples::LockedRotation2, - Examples::LockedRotation2 => Examples::MultipleColliders2, - Examples::MultipleColliders2 => Examples::PlayerMovement2, - Examples::PlayerMovement2 => Examples::Boxes2, - }; - next_state.set(next); - } + next_state.set(examples_available.0[example_selected.0].state); +} + +fn ui_example_system( + mut contexts: EguiContexts, + mut current_example: ResMut, + examples_available: Res, +) { + egui::Window::new("Testbed").show(contexts.ctx_mut(), |ui| { + let mut changed = false; + egui::ComboBox::from_label("example") + .width(150.0) + .selected_text(examples_available.0[current_example.0].name) + .show_ui(ui, |ui| { + for (id, value) in examples_available.0.iter().enumerate() { + changed = ui + .selectable_value(&mut current_example.0, id, value.name) + .changed() + || changed; + } + }); + if ui.button("Next").clicked() { + current_example.0 = (current_example.0 + 1) % examples_available.0.len(); + } + }); } diff --git a/bevy_rapier3d/Cargo.toml b/bevy_rapier3d/Cargo.toml index 58690f76..11b0a43a 100644 --- a/bevy_rapier3d/Cargo.toml +++ b/bevy_rapier3d/Cargo.toml @@ -60,6 +60,8 @@ bevy = { version = "0.14", default-features = false, features = [ ] } approx = "0.5.1" glam = { version = "0.27", features = ["approx"] } +bevy-inspector-egui = "0.25.1" +bevy_egui = "0.28.0" divan = "0.1" bevy_rapier_benches3d = { version = "0.1", path = "../bevy_rapier_benches3d" } diff --git a/bevy_rapier3d/examples/testbed3.rs b/bevy_rapier3d/examples/testbed3.rs index 1d3e3db1..a8f18a48 100644 --- a/bevy_rapier3d/examples/testbed3.rs +++ b/bevy_rapier3d/examples/testbed3.rs @@ -11,9 +11,11 @@ mod ray_casting3; mod static_trimesh3; use bevy::prelude::*; +use bevy_egui::{egui, EguiContexts, EguiPlugin}; +use bevy_inspector_egui::quick::WorldInspectorPlugin; use bevy_rapier3d::prelude::*; -#[derive(Debug, Clone, Eq, PartialEq, Default, Hash, States)] +#[derive(Debug, Reflect, Clone, Copy, Eq, PartialEq, Default, Hash, States)] pub enum Examples { #[default] None, @@ -28,20 +30,55 @@ pub enum Examples { StaticTrimesh3, } -#[derive(Resource, Default)] +#[derive(Resource, Default, Reflect)] struct ExamplesRes { entities_before: Vec, } +#[derive(Resource, Debug, Default, Reflect)] +struct ExampleSelected(pub usize); + +#[derive(Debug, Reflect)] +struct ExampleDefinition { + pub state: Examples, + pub name: &'static str, +} + +impl From<(Examples, &'static str)> for ExampleDefinition { + fn from((state, name): (Examples, &'static str)) -> Self { + Self { state, name } + } +} + +#[derive(Resource, Debug, Reflect)] +struct ExampleSet(pub Vec); + fn main() { let mut app = App::new(); - app.init_state::() - .init_resource::() + app.init_resource::() .add_plugins(( DefaultPlugins, + EguiPlugin, RapierPhysicsPlugin::::default(), RapierDebugRenderPlugin::default(), + WorldInspectorPlugin::new(), )) + .register_type::() + .register_type::() + .register_type::() + .init_state::() + .insert_resource(ExampleSet(vec![ + (Examples::Boxes3, "Boxes3").into(), + (Examples::Despawn3, "Despawn3").into(), + (Examples::Events3, "Events3").into(), + (Examples::Joints3, "Joints3").into(), + (Examples::JointsDespawn3, "JointsDespawn3").into(), + (Examples::LockedRotations3, "LockedRotations3").into(), + (Examples::MultipleColliders3, "MultipleColliders3").into(), + (Examples::Raycasting3, "Raycasting3").into(), + (Examples::StaticTrimesh3, "StaticTrimesh3").into(), + ])) + .init_resource::() // //boxes2 .add_systems( @@ -149,7 +186,14 @@ fn main() { }, ) .add_systems(OnExit(Examples::None), init) - .add_systems(Update, check_toggle); + .add_systems( + Update, + ( + ui_example_system, + change_example.run_if(resource_changed::), + ) + .chain(), + ); app.run(); } @@ -174,24 +218,34 @@ fn cleanup(world: &mut World) { } } -fn check_toggle( - state: Res>, +fn change_example( + example_selected: Res, + examples_available: Res, mut next_state: ResMut>, - mouse_input: Res>, ) { - if mouse_input.just_pressed(MouseButton::Left) { - let next = match *state.get() { - Examples::None => Examples::Boxes3, - Examples::Boxes3 => Examples::Despawn3, - Examples::Despawn3 => Examples::Events3, - Examples::Events3 => Examples::Joints3, - Examples::Joints3 => Examples::JointsDespawn3, - Examples::JointsDespawn3 => Examples::LockedRotations3, - Examples::LockedRotations3 => Examples::MultipleColliders3, - Examples::MultipleColliders3 => Examples::Raycasting3, - Examples::Raycasting3 => Examples::StaticTrimesh3, - Examples::StaticTrimesh3 => Examples::Boxes3, - }; - next_state.set(next); - } + next_state.set(examples_available.0[example_selected.0].state); +} + +fn ui_example_system( + mut contexts: EguiContexts, + mut current_example: ResMut, + examples_available: Res, +) { + egui::Window::new("Testbed").show(contexts.ctx_mut(), |ui| { + let mut changed = false; + egui::ComboBox::from_label("example") + .width(150.0) + .selected_text(examples_available.0[current_example.0].name) + .show_ui(ui, |ui| { + for (id, value) in examples_available.0.iter().enumerate() { + changed = ui + .selectable_value(&mut current_example.0, id, value.name) + .changed() + || changed; + } + }); + if ui.button("Next").clicked() { + current_example.0 = (current_example.0 + 1) % examples_available.0.len(); + } + }); }