From ce863d093be3366bdafc7f21cc7374adfdfbb14b Mon Sep 17 00:00:00 2001 From: doomy <2640792-_doomy@users.noreply.gitlab.com> Date: Wed, 13 Dec 2023 03:25:05 -0500 Subject: [PATCH] fixed some glaring issues, disabled camera logic for now, added separate mouse sensitivity, fixed inverted y axis, added controller support to the menu --- Cargo.lock | 11 +++++ Cargo.toml | 1 + assets/default.settings.ron | 7 +-- src/main.rs | 2 + src/plugins/camera.rs | 86 +++++++++++++++++++------------------ src/plugins/levels.rs | 19 +++++--- src/plugins/mod.rs | 44 ++++++++++--------- src/plugins/ui.rs | 45 ++++++++++++++++--- src/resources/settings.rs | 3 +- 9 files changed, 140 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e213361..d60c3be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -375,6 +375,16 @@ dependencies = [ "bevy_internal", ] +[[package]] +name = "bevy-egui-kbgp" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5f335d3d7ef96a0a5aa9b389693f007fd24927553bc812a4b119be8a58a2f0" +dependencies = [ + "bevy", + "bevy_egui", +] + [[package]] name = "bevy-inspector-egui" version = "0.21.0" @@ -553,6 +563,7 @@ name = "bevy_blast_ultra" version = "0.1.0" dependencies = [ "bevy", + "bevy-egui-kbgp", "bevy-inspector-egui", "bevy_asset_loader", "bevy_common_assets", diff --git a/Cargo.toml b/Cargo.toml index 8b6e1d8..0d9b0d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,3 +25,4 @@ leafwing-input-manager = "0.11.1" serde = "1.0.193" image = { version = "0.24", features = ["png"] } bevy_wasm_window_resize = "0.2.1" +bevy-egui-kbgp = "0.16.0" diff --git a/assets/default.settings.ron b/assets/default.settings.ron index c57fe47..8146535 100644 --- a/assets/default.settings.ron +++ b/assets/default.settings.ron @@ -10,11 +10,12 @@ SettingsAsset( influence_radius: 5.0, ), camera: ( - sensitivity: (3.0, 1.5), + controller_sensitivity: (3.0, 1.5), + mouse_sensitivity: (5.0, 5.0), fov: 90, fov_multiplier_range: RangeInclusive( start: 1.2, end: 0.9 ), - angle_range: RangeInclusive( start: 160, end: 80 ), - distance: 7, + angle_range: RangeInclusive( start: 200, end: 270 ), + distance: 7.0, ) ), ui: ( diff --git a/src/main.rs b/src/main.rs index b7ef892..26ff51d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ use bevy::{prelude::*, window::WindowMode}; use bevy_blast_ultra::prelude::*; use bevy_easings::EasingsPlugin; use bevy_egui::EguiPlugin; +use bevy_egui_kbgp::KbgpPlugin; use bevy_inspector_egui::quick::WorldInspectorPlugin; use bevy_wasm_window_resize::WindowResizePlugin; use bevy_xpbd_3d::prelude::*; @@ -25,6 +26,7 @@ fn main() { PhysicsDebugPlugin::default(), WorldInspectorPlugin::new().run_if(|debug: Res| *debug == DebugMode::On), WindowResizePlugin, + KbgpPlugin, )) .insert_resource(DebugMode::Off) .insert_resource(bevy_xpbd_3d::resources::Gravity(Vec3::NEG_Z * 50f32)) diff --git a/src/plugins/camera.rs b/src/plugins/camera.rs index 946f8fa..81f7220 100644 --- a/src/plugins/camera.rs +++ b/src/plugins/camera.rs @@ -1,8 +1,5 @@ use bevy::{input::mouse::MouseMotion, prelude::*}; -use bevy_xpbd_3d::{ - components::CollisionLayers, - plugins::spatial_query::{SpatialQuery, SpatialQueryFilter}, -}; +use bevy_xpbd_3d::prelude::*; use leafwing_input_manager::prelude::*; use crate::prelude::*; @@ -68,17 +65,20 @@ fn orbit_camera_input( if let Ok((mut orbit_camera, mut projection)) = camera.get_single_mut() { if let Projection::Perspective(projection) = projection.as_mut() { if let Some(look) = actions.clamped_axis_pair(Action::Look) { - orbit_camera.add_view_angle_normalized( - look.y() * camera_settings.sensitivity.y * time.delta_seconds(), - ); - orbit_camera.add_view_angle_normalized( - mouse_motion.y.to_radians() * camera_settings.sensitivity.y, - ); - - orbit_camera.rotation -= - look.x() * camera_settings.sensitivity.x * time.delta_seconds(); - orbit_camera.rotation -= - mouse_motion.x.to_radians() * camera_settings.sensitivity.x; + let sensitivity = if mouse_motion == Vec2::ZERO { + camera_settings.controller_sensitivity + } else { + camera_settings.mouse_sensitivity + }; + + orbit_camera + .add_view_angle_normalized(look.y() * sensitivity.y * time.delta_seconds()); + orbit_camera + .add_view_angle_normalized(-mouse_motion.y.to_radians() * sensitivity.y); + + orbit_camera.rotation -= look.x() * sensitivity.x * time.delta_seconds(); + + orbit_camera.rotation -= mouse_motion.x.to_radians() * sensitivity.x; } } } @@ -96,11 +96,13 @@ fn orbit_camera_movement( if let (Ok(focus_transform), Ok((camera_entity, camera_transform, orbit_camera))) = (focus.get_single(), camera.get_single()) { - // We have the focus translation, so we need the desired camera - // translation. Then, we will find the direction from the focus to the - // camera, and cast a ray. If the ray intersects with anything before - // the desired length, the camera will instead be placed there as to - // avoid clipping into things + // // TODO: Camera casting logic is probably hurting more than helping. Can + // // we instead fade objects in and out nicely when they're close to the camera? + // // We have the focus translation, so we need the desired camera + // // translation. Then, we will find the direction from the focus to the + // // camera, and cast a ray. If the ray intersects with anything before + // // the desired length, the camera will instead be placed there as to + // // avoid clipping into things let mut cast = *focus_transform; cast.rotation = Quat::from_axis_angle(Vec3::Z, orbit_camera.rotation); cast.rotate_local_y( @@ -110,28 +112,28 @@ fn orbit_camera_movement( ); let mut new_camera_position = cast.forward(); - // Cast a ray to the camera - if let Some(hit) = spatial.cast_ray( - cast.translation, - cast.forward(), - camera_settings.distance, - true, - SpatialQueryFilter::default().with_masks([Layer::Environment]), - ) { - // Ensure we are not in a solid object - // TODO: This is not working :(((((( - if hit.time_of_impact != 0.0 { - new_camera_position *= hit.time_of_impact; - // take off a little distance to keep the camera from intersecting - // the floor - // TODO: shape cast and take the middle so that this is not necessary - new_camera_position *= 0.80f32; - } else { - new_camera_position *= camera_settings.distance; - } - } else { - new_camera_position *= camera_settings.distance; - } + // // Cast a ray to the camera + // if let Some(hit) = spatial.cast_shape( + // &Collider::ball(0.1), + // cast.translation, + // default(), + // cast.forward(), + // camera_settings.distance, + // false, + // SpatialQueryFilter::default().with_masks([Layer::Environment]), + // ) { + // // Ensure we are not in a solid object + // // TODO: This is not working :(((((( + // if hit.time_of_impact != 0.0 { + // new_camera_position *= hit.time_of_impact; + // } else { + // new_camera_position *= camera_settings.distance; + // } + // } else { + // new_camera_position *= camera_settings.distance; + // } + + new_camera_position *= camera_settings.distance; let mut camera_transform = *focus_transform; camera_transform.translation += new_camera_position; diff --git a/src/plugins/levels.rs b/src/plugins/levels.rs index 76501af..8b8d01a 100644 --- a/src/plugins/levels.rs +++ b/src/plugins/levels.rs @@ -130,6 +130,9 @@ fn spawn( composite_mode: BloomCompositeMode::Additive, ..default() }, + ScreenSpaceAmbientOcclusionSettings { + quality_level: ScreenSpaceAmbientOcclusionQualityLevel::High, + }, )); // Get the map to spawn @@ -219,8 +222,12 @@ fn process_colliders( children: Query<&Children>, mut cmd: Commands, mut proxy_colliders: Query< - (Entity, &Collider, &Name, &mut Visibility), - (Without, Added, Without), + (Entity, &blender::Collider, &Name, &mut Visibility), + ( + Without, + Added, + Without, + ), >, ) { // Replace physics entities @@ -236,21 +243,21 @@ fn process_colliders( let mut xpbd_collider: XpbdCollider; match collider_proxy { - Collider::Ball(radius) => { + blender::Collider::Ball(radius) => { xpbd_collider = XpbdCollider::ball(*radius); cmd.entity(entity) .insert((xpbd_collider, collision_layers, friction)) //.insert(ActiveEvents::COLLISION_EVENTS) // FIXME: this is just for demo purposes (also is there something like that in xpbd ?) !!! ; } - Collider::Cuboid(size) => { + blender::Collider::Cuboid(size) => { xpbd_collider = XpbdCollider::cuboid(size.x, size.y, size.z); cmd.entity(entity) .insert((xpbd_collider, collision_layers, friction)) //.insert(ActiveEvents::COLLISION_EVENTS) // FIXME: this is just for demo purposes (also is there something like that in xpbd ?) !!! ; } - Collider::Capsule(a, b, radius) => { + blender::Collider::Capsule(a, b, radius) => { // FIXME: temp let height = Vec3::distance(*a, *b); xpbd_collider = XpbdCollider::capsule(height, *radius); @@ -260,7 +267,7 @@ fn process_colliders( //.insert(ActiveEvents::COLLISION_EVENTS) // FIXME: this is just for demo purposes (also is there something like that in xpbd ?) !!! ; } - Collider::Mesh => { + blender::Collider::Mesh => { for (_, collider_mesh) in Mesh::search_in_children(entity, &children, &meshes, &mesh_handles) { diff --git a/src/plugins/mod.rs b/src/plugins/mod.rs index 730a6c6..750b18c 100644 --- a/src/plugins/mod.rs +++ b/src/plugins/mod.rs @@ -52,8 +52,8 @@ impl Plugin for InitPlugin { fn build(&self, app: &mut App) { app.add_state::() // Register all types intended to be used either in Blender or to be saved .register_type::() - .register_type::() - .register_type::() + .register_type::() + .register_type::() .register_type::() .register_type::() .register_type::() @@ -72,23 +72,27 @@ impl Plugin for InitPlugin { } } -/// Marker component for Blender compatibility. Replaced via [`physics_replace_proxies`]. -#[derive(Component, Reflect, Default, Debug)] -#[reflect(Component)] -pub enum Collider { - Ball(f32), - Cuboid(Vec3), - Capsule(Vec3, Vec3, f32), - #[default] - Mesh, -} +pub(crate) mod blender { + use super::*; + + /// Marker component for Blender compatibility. Replaced via [`physics_replace_proxies`]. + #[derive(Component, Reflect, Default, Debug)] + #[reflect(Component)] + pub enum Collider { + Ball(f32), + Cuboid(Vec3), + Capsule(Vec3, Vec3, f32), + #[default] + Mesh, + } -/// Marker component for Blender compatibility. Replaced via [`physics_replace_proxies`]. -#[derive(Component, Reflect, Default, Debug)] -#[reflect(Component)] -pub enum AutoCollider { - #[default] - Cuboid, - Ball, - Capsule, + /// Marker component for Blender compatibility. Replaced via [`physics_replace_proxies`]. + #[derive(Component, Reflect, Default, Debug)] + #[reflect(Component)] + pub enum AutoCollider { + #[default] + Cuboid, + Ball, + Capsule, + } } diff --git a/src/plugins/ui.rs b/src/plugins/ui.rs index 4880b8d..3f4bf63 100644 --- a/src/plugins/ui.rs +++ b/src/plugins/ui.rs @@ -3,6 +3,7 @@ use bevy_egui::{ egui::{self, epaint::Shadow, Color32, FontId, Frame, Stroke}, EguiContexts, EguiSettings, }; +use bevy_egui_kbgp::prelude::*; use bevy_gltf_blueprints::GameWorldTag; use bevy_xpbd_3d::plugins::debug::PhysicsDebugConfig; use leafwing_input_manager::action_state::ActionState; @@ -13,6 +14,11 @@ use super::input::Action; pub struct UiPlugin; +#[derive(Clone)] +pub enum UiActions { + ToggleMenu, +} + impl Plugin for UiPlugin { fn build(&self, app: &mut App) { app.add_systems(Update, toggle_debug) @@ -23,7 +29,18 @@ impl Plugin for UiPlugin { ) .add_systems(Update, (game_ui,).run_if(in_state(GameState::Main))) .add_systems(Update, post_game_ui.run_if(in_state(GameState::Post))) - .add_systems(Update, pause_menu_ui.run_if(in_state(GameState::Pause))); + .add_systems(Update, pause_menu_ui.run_if(in_state(GameState::Pause))) + .insert_resource(KbgpSettings { + bindings: { + bevy_egui_kbgp::KbgpNavBindings::default() + .with_wasd_navigation() + .with_arrow_keys_navigation() + .with_gamepad_dpad_navigation_and_south_button_activation() + .with_key(KeyCode::Escape, KbgpNavCommand::user(UiActions::ToggleMenu)) + // .with_gamepad_button(GamepadButtonType::Start, KbgpNavCommand::user(UiActions::Menu)) + }, + ..default() + }); } } @@ -127,12 +144,18 @@ fn menu_ui( selected_level.0 == i, format!("Level {i}"), )) + .kbgp_navigation() .clicked() { selected_level.0 = i } }); - if ui.button("Start").clicked() { + if ui + .button("Start") + .kbgp_navigation() + .kbgp_initial_focus() + .clicked() + { cmd.insert_resource(CurrentLevelIndex(selected_level.0)); state.set(GameState::LevelTransition { level: level_paths[selected_level.0].clone(), @@ -244,7 +267,12 @@ fn post_game_ui( .font(FontId::proportional(font.size_title())) .color(Color32::GREEN), ); - if ui.button("Next level").clicked() { + if ui + .button("Next level") + .kbgp_navigation() + .kbgp_initial_focus() + .clicked() + { current_level.0 += 1; state.set(GameState::LevelTransition { level: level.clone(), @@ -296,17 +324,22 @@ fn pause_menu_ui( ), |ui| { ui.vertical_centered_justified(|ui| { - if ui.button("Resume").clicked() { + if ui + .button("Resume") + .kbgp_navigation() + .kbgp_initial_focus() + .clicked() + { state.set(GameState::Main); } - if ui.button("Restart level").clicked() { + if ui.button("Restart level").kbgp_navigation().clicked() { state.set(GameState::LevelTransition { level: assets.levels[current_level.0].clone(), }); } - if ui.button("Main menu").clicked() { + if ui.button("Main menu").kbgp_navigation().clicked() { state.set(GameState::Menu); } }) diff --git a/src/resources/settings.rs b/src/resources/settings.rs index 922cb57..a25c45e 100644 --- a/src/resources/settings.rs +++ b/src/resources/settings.rs @@ -24,7 +24,8 @@ pub struct CameraSettings { /// Permitted camera angles in degrees pub angle_range: RangeInclusive, pub distance: f32, - pub sensitivity: Vec2, + pub mouse_sensitivity: Vec2, + pub controller_sensitivity: Vec2, pub fov: f32, pub fov_multiplier_range: RangeInclusive, }