diff --git a/src/input/gamepad.rs b/src/input/gamepad.rs index 819833d..daa252d 100644 --- a/src/input/gamepad.rs +++ b/src/input/gamepad.rs @@ -21,9 +21,8 @@ pub fn sample_gamepad(pad: &Gamepad, input_map: &BaseInputMap) -> FighterInputFr // Digital buttons driving movement isn't used by the // default bindings (the stick covers that), but stay // consistent with the keyboard backend if one is added. - InputMapAction::MovementXDir(sign) if pressed => movement.x += sign as f32, - InputMapAction::MovementYDir(sign) if pressed => movement.y += sign as f32, - _ => {} + InputMapAction::MovementXDir(sign) => if pressed { movement.x += sign as f32 }, + InputMapAction::MovementYDir(sign) => if pressed { movement.y += sign as f32 }, } } // gamepad does not have a separate axis for left and right, so sign here should be 1 diff --git a/src/input/keyboard.rs b/src/input/keyboard.rs index dffa7b6..34edd92 100644 --- a/src/input/keyboard.rs +++ b/src/input/keyboard.rs @@ -33,6 +33,7 @@ pub fn sample_keyboard(key: &ButtonInput, input_map: &BaseInputMap) -> InputMapAction::Jump => input_frame.jump = action_strength != FGi32::ZERO, InputMapAction::Shield => input_frame.shield = action_strength != FGi32::ZERO, InputMapAction::Attack => input_frame.attack = action_strength != FGi32::ZERO, + } } diff --git a/src/input/map.rs b/src/input/map.rs index 92487cd..81fe3cf 100644 --- a/src/input/map.rs +++ b/src/input/map.rs @@ -19,6 +19,15 @@ pub enum InputMapAction { Attack, } +#[derive(Debug)] +pub enum MenuInputMapAction { + MovementXDir(i32), + MovementYDir(i32), + Accept, + Back, + Start, +} + #[derive(Debug)] pub struct KeyboardInputMapElement { pub key: KeyCode, @@ -37,8 +46,26 @@ pub struct GamepadInputMapElement { pub action: InputMapAction, } +#[derive(Debug)] +pub struct MenuKeyboardInputMapElement { + pub key: KeyCode, + pub action: MenuInputMapAction, +} + +#[derive(Debug)] +pub struct MenuGamepadInputMapElement { + pub binding: GamepadBinding, + pub action: MenuInputMapAction, +} + #[derive(Resource)] pub struct BaseInputMap { pub keyboard: Vec, pub gamepad: Vec, } + +#[derive(Resource)] +pub struct MenuInputMap { + pub keyboard: Vec, + pub gamepad: Vec, +} diff --git a/src/input/mod.rs b/src/input/mod.rs index 90df781..d509ab3 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -18,7 +18,8 @@ pub use buffer::{FighterCommands, FighterInput}; pub use frame::FighterInputFrame; pub use map::{ BaseInputMap, GamepadBinding, GamepadInputMapElement, InputActionState, InputMapAction, - KeyboardInputMapElement, + KeyboardInputMapElement, MenuGamepadInputMapElement, MenuInputMap, MenuInputMapAction, + MenuKeyboardInputMapElement, }; #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -91,6 +92,9 @@ impl Plugin for FighterInputPlugin { key: KeyCode::KeyJ, action: InputMapAction::Attack, }, + + + // Menu ], gamepad: vec![ // left stick @@ -121,6 +125,33 @@ impl Plugin for FighterInputPlugin { binding: GamepadBinding::Button(GamepadButton::East), action: InputMapAction::Attack, }, + + ], + }) + .insert_resource(MenuInputMap { + keyboard: vec![ + MenuKeyboardInputMapElement { key: KeyCode::ArrowUp, action: MenuInputMapAction::MovementYDir(1) }, + MenuKeyboardInputMapElement { key: KeyCode::ArrowDown, action: MenuInputMapAction::MovementYDir(-1) }, + MenuKeyboardInputMapElement { key: KeyCode::ArrowLeft, action: MenuInputMapAction::MovementXDir(-1) }, + MenuKeyboardInputMapElement { key: KeyCode::ArrowRight, action: MenuInputMapAction::MovementXDir(1) }, + MenuKeyboardInputMapElement { key: KeyCode::Enter, action: MenuInputMapAction::Accept }, + MenuKeyboardInputMapElement { key: KeyCode::Escape, action: MenuInputMapAction::Back }, + MenuKeyboardInputMapElement { key: KeyCode::Space, action: MenuInputMapAction::Start }, + MenuKeyboardInputMapElement { key: KeyCode::KeyW, action: MenuInputMapAction::MovementYDir(1) }, + MenuKeyboardInputMapElement { key: KeyCode::KeyS, action: MenuInputMapAction::MovementYDir(-1) }, + MenuKeyboardInputMapElement { key: KeyCode::KeyA, action: MenuInputMapAction::MovementXDir(-1) }, + MenuKeyboardInputMapElement { key: KeyCode::KeyD, action: MenuInputMapAction::MovementXDir(1) }, + ], + gamepad: vec![ + MenuGamepadInputMapElement { binding: GamepadBinding::Button(GamepadButton::DPadUp), action: MenuInputMapAction::MovementYDir(1) }, + MenuGamepadInputMapElement { binding: GamepadBinding::Button(GamepadButton::DPadDown), action: MenuInputMapAction::MovementYDir(-1) }, + MenuGamepadInputMapElement { binding: GamepadBinding::Button(GamepadButton::DPadLeft), action: MenuInputMapAction::MovementXDir(-1) }, + MenuGamepadInputMapElement { binding: GamepadBinding::Button(GamepadButton::DPadRight), action: MenuInputMapAction::MovementXDir(1) }, + MenuGamepadInputMapElement { binding: GamepadBinding::Axis(GamepadAxis::LeftStickX, 1), action: MenuInputMapAction::MovementXDir(1) }, + MenuGamepadInputMapElement { binding: GamepadBinding::Axis(GamepadAxis::LeftStickY, 1), action: MenuInputMapAction::MovementYDir(1) }, + MenuGamepadInputMapElement { binding: GamepadBinding::Button(GamepadButton::South), action: MenuInputMapAction::Accept }, + MenuGamepadInputMapElement { binding: GamepadBinding::Button(GamepadButton::West), action: MenuInputMapAction::Back }, + MenuGamepadInputMapElement { binding: GamepadBinding::Button(GamepadButton::Start), action: MenuInputMapAction::Start }, ], }) .init_resource::() diff --git a/src/menus/button.rs b/src/menus/button.rs index 824e70e..2b4f228 100644 --- a/src/menus/button.rs +++ b/src/menus/button.rs @@ -1,4 +1,4 @@ -use bevy::{input_focus::InputFocus, prelude::*, text::FontSourceTemplate, ui::auto_directional_navigation::AutoDirectionalNavigation}; +use bevy::{input_focus::InputFocus, picking::{hover::PickingInteraction, Pickable}, prelude::*, text::FontSourceTemplate, ui::auto_directional_navigation::AutoDirectionalNavigation}; use crate::{game_settings::CommonAssets, menus::style::{FGUiButtonType, FGUiStyle}}; @@ -24,6 +24,7 @@ pub fn menu_button(label: &str) -> impl Scene { BackgroundColor(Color::srgb(0.15, 0.15, 0.15)) AutoDirectionalNavigation::default() Children [( + Pickable::IGNORE Text(label) TextFont { font: FontSourceTemplate::Handle("fonts/roboto.ttf"), @@ -43,14 +44,14 @@ pub fn button_setup(query: Query<(Entity, &FGUiButton, &mut Node), Added>, common_assets: Res, styles: Res>, mut commands: Commands) { +pub fn button_style_system(query: Query<(Entity, &FGUiButton, &PickingInteraction, &mut Node), Changed>, common_assets: Res, styles: Res>, mut commands: Commands) { let styles = styles.get(&common_assets.ui_style).expect("UI styles should be loaded"); for (entity, button, interaction, mut node) in query { let button_style_to_use = match interaction { - Interaction::Pressed => &styles.button_styles[&button.button_type].press, - Interaction::Hovered => &styles.button_styles[&button.button_type].hover, - Interaction::None => &styles.button_styles[&button.button_type].normal, + PickingInteraction::Pressed => &styles.button_styles[&button.button_type].press, + PickingInteraction::Hovered => &styles.button_styles[&button.button_type].hover, + PickingInteraction::None => &styles.button_styles[&button.button_type].normal, }; button_style_to_use.apply(&mut commands, entity, &mut node); } @@ -78,4 +79,4 @@ pub fn button_focus_style_system(query: Query<(Entity, &FGUiButton)>, focus: Res } } } -} \ No newline at end of file +} diff --git a/src/menus/character_select/character_box.rs b/src/menus/character_select/character_box.rs index f4fe230..3bd02af 100644 --- a/src/menus/character_select/character_box.rs +++ b/src/menus/character_select/character_box.rs @@ -1,4 +1,4 @@ -use bevy::{prelude::*, text::FontSourceTemplate}; +use bevy::{picking::Pickable, prelude::*, text::FontSourceTemplate}; use crate::{fighter::manifest::FighterManifest, menus::{button::FGUiButton, style::FGUiButtonType}}; @@ -25,6 +25,7 @@ impl CharacterBox { } BackgroundColor(Color::srgb(1.0, 1.0, 1.0)) Children [ + Pickable::IGNORE Node { width: percent(100) } @@ -38,4 +39,4 @@ impl CharacterBox { ] } } -} \ No newline at end of file +} diff --git a/src/menus/character_select/mod.rs b/src/menus/character_select/mod.rs index 1441c06..9242cbd 100644 --- a/src/menus/character_select/mod.rs +++ b/src/menus/character_select/mod.rs @@ -2,7 +2,7 @@ use bevy::prelude::*; use crate::{ fighter::manifest::{FighterManifest, FighterManifestRegistry}, - input::{LocalInputAssignments, LocalInputSource}, + input::LocalInputAssignments, menus::{MenuMarker, build_menu_with_props, cursor::FGMenuCursor, spawn_menu, wrap_menu}, }; @@ -16,10 +16,12 @@ pub struct CharacterSelectScreen { pub fn setup_character_select( existing_menu: Option>>, - commands: Commands, + mut commands: Commands, manifest_registry: Res, assignments: Res, manifests: Res>, + mut meshes: ResMut>, + mut materials: ResMut>, ) { let character_boxes = manifest_registry .iter() @@ -32,6 +34,10 @@ pub fn setup_character_select( .map(|(slot, _)| fighter_portrait::FighterPortrait::create(*slot)) .collect::>(); + for (slot, _) in assignments.iter() { + commands.spawn(FGMenuCursor::create_cursor(*slot, &mut meshes, &mut materials)); + } + let menu = bsn! { // Characters CharacterSelectScreen { @@ -75,7 +81,6 @@ pub fn create_portrait( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, - mapping: Res, ) { let entity = commands .spawn_scene(fighter_portrait::FighterPortrait::create(player_slot)) @@ -83,7 +88,7 @@ pub fn create_portrait( commands.entity(container).add_child(entity); commands.spawn( - FGMenuCursor::create_cursor(player_slot, meshes, materials, mapping) + FGMenuCursor::create_cursor(player_slot, &mut meshes, &mut materials) ); } @@ -98,7 +103,6 @@ pub fn handle_fighter_slot_addition( commands: Commands, meshes: ResMut>, materials: ResMut>, - mapping: Res, ) { let slot = addition.slot; create_portrait( @@ -107,43 +111,20 @@ pub fn handle_fighter_slot_addition( commands, meshes, materials, - mapping, ); } pub fn css_input( - key: Res>, - pads: Query<(Entity, &Gamepad)>, + menu_inputs: Res, mut assignments: ResMut, mut commands: Commands, ) { - if key.get_pressed().len() != 0 { - if let None = assignments - .iter() - .find(|(_, source)| matches!(source, LocalInputSource::Keyboard)) - { - if let Some(free_idx) = assignments.get_free_player_index() { - assignments.push((free_idx, LocalInputSource::Keyboard)); - info!("New keyboard assignment"); - commands.trigger(FighterSlotAssigned { slot: free_idx }); - } - } - } - - for (entity, pad) in pads { - if pad.any_pressed(GamepadButton::all()) { - let existed = assignments - .iter() - .find(|(_, assignment)| { - if let LocalInputSource::Gamepad(assignment_entity) = assignment { - return entity == *assignment_entity; - } - false - }) - .is_some(); - + for (source, input) in &menu_inputs.inputs { + if input.movement != Vec2::ZERO { + let existed = assignments.iter().any(|(_, assigned)| assigned == source); if !existed && let Some(free_idx) = assignments.get_free_player_index() { - assignments.push((free_idx, LocalInputSource::Gamepad(entity))); + assignments.push((free_idx, *source)); + info!("New input assignment"); commands.trigger(FighterSlotAssigned { slot: free_idx }); } } diff --git a/src/menus/cursor.rs b/src/menus/cursor.rs index 6cfb614..cb85b48 100644 --- a/src/menus/cursor.rs +++ b/src/menus/cursor.rs @@ -1,12 +1,11 @@ use bevy::{ asset::uuid::Uuid, - math::VectorSpace, - picking::pointer::{Location, PointerId, PointerInput, PointerLocation}, + picking::{pointer::{Location, PointerAction, PointerId, PointerInput, PointerLocation}, Pickable}, prelude::*, - window::{NormalizedWindowRef, WindowRef}, + window::WindowRef, }; -use crate::{game_settings::GameSettings, input::LocalInputAssignments, menus::input::MenuInput}; +use crate::{input::LocalInputAssignments, menus::input::{MenuInput, MenuInputState}}; #[derive(Default)] pub enum MenuCursorInputSource { @@ -19,28 +18,20 @@ pub enum MenuCursorInputSource { pub struct FGMenuCursor { pub input_source: MenuCursorInputSource, pub velocity: Vec2, + pub accepting: bool, } impl FGMenuCursor { pub fn create_cursor( player_slot: usize, - mut meshes: ResMut>, - mut materials: ResMut>, - mapping: Res, + meshes: &mut Assets, + materials: &mut Assets, ) -> impl Bundle { - let (_, mapping) = mapping - .iter() - .find(|(slot, _)| *slot == player_slot) - .unwrap(); - let material = materials.add(ColorMaterial::from_color( bevy::color::palettes::tailwind::ROSE_600, )); let circle_mesh = meshes.add(Circle::new(25.0)); - let pointer_id = match mapping { - crate::input::LocalInputSource::Keyboard => PointerId::Mouse, - crate::input::LocalInputSource::Gamepad(_) => PointerId::Custom(Uuid::new_v4()), - }; + let pointer_id = PointerId::Custom(Uuid::new_v4()); ( FGMenuCursor { input_source: super::cursor::MenuCursorInputSource::Player(player_slot), @@ -51,42 +42,37 @@ impl FGMenuCursor { Mesh2d(circle_mesh), Transform::IDENTITY, GlobalZIndex(1000), + Pickable::IGNORE, ) } } pub fn cursor_input( - window: Single>, + window: Single<(Entity, &Window), With>, query: Query<( &mut FGMenuCursor, &PointerLocation, &PointerId, )>, - key: Res>, assignments: Res, - game_settings: Res, + menu_inputs: Res, time: Res