1206 lines
52 KiB
Rust
1206 lines
52 KiB
Rust
use crate::framework::context::Context;
|
|
use crate::framework::error::GameResult;
|
|
use crate::framework::gamepad::{self, Axis, AxisDirection, Button, PlayerControllerInputType};
|
|
use crate::framework::keyboard::ScanCode;
|
|
use crate::game::settings::{
|
|
p1_default_keymap, p2_default_keymap, player_default_controller_button_map, ControllerType,
|
|
PlayerControllerButtonMap, PlayerKeyMap,
|
|
};
|
|
use crate::game::shared_game_state::SharedGameState;
|
|
use crate::input::combined_menu_controller::CombinedMenuController;
|
|
|
|
use super::{ControlMenuData, Menu, MenuEntry, MenuSelectionResult};
|
|
|
|
const FORBIDDEN_SCANCODES: [ScanCode; 12] = [
|
|
ScanCode::F1,
|
|
ScanCode::F2,
|
|
ScanCode::F3,
|
|
ScanCode::F4,
|
|
ScanCode::F5,
|
|
ScanCode::F6,
|
|
ScanCode::F7,
|
|
ScanCode::F8,
|
|
ScanCode::F9,
|
|
ScanCode::F10,
|
|
ScanCode::F11,
|
|
ScanCode::F12,
|
|
];
|
|
|
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
|
#[repr(u8)]
|
|
enum CurrentMenu {
|
|
MainMenu,
|
|
SelectControllerMenu,
|
|
RebindMenu,
|
|
ConfirmRebindMenu,
|
|
ConfirmResetMenu,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
|
enum MainMenuEntry {
|
|
SelectedPlayer,
|
|
Controller,
|
|
Rebind,
|
|
Rumble,
|
|
DisplayTouchControls,
|
|
Back,
|
|
}
|
|
|
|
impl Default for MainMenuEntry {
|
|
fn default() -> Self {
|
|
#[cfg(target_os = "android")]
|
|
return MainMenuEntry::DisplayTouchControls;
|
|
|
|
#[cfg(not(target_os = "android"))]
|
|
return MainMenuEntry::SelectedPlayer;
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
|
enum SelectControllerMenuEntry {
|
|
Keyboard,
|
|
Gamepad(usize),
|
|
Back,
|
|
}
|
|
|
|
impl Default for SelectControllerMenuEntry {
|
|
fn default() -> Self {
|
|
SelectControllerMenuEntry::Keyboard
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
|
enum RebindMenuEntry {
|
|
Control(ControlEntry),
|
|
Reset,
|
|
Back,
|
|
}
|
|
|
|
impl Default for RebindMenuEntry {
|
|
fn default() -> Self {
|
|
RebindMenuEntry::Control(ControlEntry::MenuOk)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
|
enum ConfirmResetMenuEntry {
|
|
Title,
|
|
Yes,
|
|
No,
|
|
}
|
|
|
|
impl Default for ConfirmResetMenuEntry {
|
|
fn default() -> Self {
|
|
ConfirmResetMenuEntry::No
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
|
enum Player {
|
|
Player1,
|
|
Player2,
|
|
}
|
|
|
|
impl Player {
|
|
fn controller_type(self, state: &SharedGameState) -> ControllerType {
|
|
match self {
|
|
Player::Player1 => state.settings.player1_controller_type,
|
|
Player::Player2 => state.settings.player2_controller_type,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
|
enum ControlEntry {
|
|
Left,
|
|
Up,
|
|
Right,
|
|
Down,
|
|
PrevWeapon,
|
|
NextWeapon,
|
|
Jump,
|
|
Shoot,
|
|
Skip,
|
|
Inventory,
|
|
Map,
|
|
Strafe,
|
|
MenuOk,
|
|
MenuBack,
|
|
}
|
|
|
|
impl ControlEntry {
|
|
fn to_string(&self, state: &SharedGameState) -> String {
|
|
match self {
|
|
ControlEntry::Left => state.loc.t("menus.controls_menu.rebind_menu.left"),
|
|
ControlEntry::Up => state.loc.t("menus.controls_menu.rebind_menu.up"),
|
|
ControlEntry::Right => state.loc.t("menus.controls_menu.rebind_menu.right"),
|
|
ControlEntry::Down => state.loc.t("menus.controls_menu.rebind_menu.down"),
|
|
ControlEntry::PrevWeapon => state.loc.t("menus.controls_menu.rebind_menu.prev_weapon"),
|
|
ControlEntry::NextWeapon => state.loc.t("menus.controls_menu.rebind_menu.next_weapon"),
|
|
ControlEntry::Jump => state.loc.t("menus.controls_menu.rebind_menu.jump"),
|
|
ControlEntry::Shoot => state.loc.t("menus.controls_menu.rebind_menu.shoot"),
|
|
ControlEntry::Skip => state.loc.t("menus.controls_menu.rebind_menu.skip"),
|
|
ControlEntry::Inventory => state.loc.t("menus.controls_menu.rebind_menu.inventory"),
|
|
ControlEntry::Map => state.loc.t("menus.controls_menu.rebind_menu.map"),
|
|
ControlEntry::Strafe => state.loc.t("menus.controls_menu.rebind_menu.strafe"),
|
|
ControlEntry::MenuOk => state.loc.t("menus.controls_menu.rebind_menu.menu_ok"),
|
|
ControlEntry::MenuBack => state.loc.t("menus.controls_menu.rebind_menu.menu_back"),
|
|
}
|
|
.to_owned()
|
|
}
|
|
}
|
|
|
|
pub struct ControlsMenu {
|
|
current: CurrentMenu,
|
|
main: Menu<MainMenuEntry>,
|
|
select_controller: Menu<SelectControllerMenuEntry>,
|
|
rebind: Menu<RebindMenuEntry>,
|
|
confirm_rebind: Menu<usize>,
|
|
confirm_reset: Menu<ConfirmResetMenuEntry>,
|
|
|
|
selected_player: Player,
|
|
selected_controller: ControllerType,
|
|
selected_control: Option<ControlEntry>,
|
|
|
|
player1_key_map: Vec<(ControlEntry, ScanCode)>,
|
|
player2_key_map: Vec<(ControlEntry, ScanCode)>,
|
|
player1_controller_button_map: Vec<(ControlEntry, PlayerControllerInputType)>,
|
|
player2_controller_button_map: Vec<(ControlEntry, PlayerControllerInputType)>,
|
|
|
|
input_busy: bool,
|
|
}
|
|
|
|
impl ControlsMenu {
|
|
pub fn new() -> ControlsMenu {
|
|
let main = Menu::new(0, 0, 220, 0);
|
|
let select_controller = Menu::new(0, 0, 220, 0);
|
|
let rebind = Menu::new(0, 0, 220, 0);
|
|
let confirm_rebind = Menu::new(0, 0, 220, 0);
|
|
let confirm_reset = Menu::new(0, 0, 160, 0);
|
|
|
|
ControlsMenu {
|
|
current: CurrentMenu::MainMenu,
|
|
main,
|
|
select_controller,
|
|
rebind,
|
|
confirm_rebind,
|
|
confirm_reset,
|
|
|
|
selected_player: Player::Player1,
|
|
selected_controller: ControllerType::Keyboard,
|
|
selected_control: None,
|
|
|
|
player1_key_map: Vec::new(),
|
|
player2_key_map: Vec::new(),
|
|
player1_controller_button_map: Vec::new(),
|
|
player2_controller_button_map: Vec::new(),
|
|
|
|
input_busy: false,
|
|
}
|
|
}
|
|
|
|
pub fn init(&mut self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
|
#[cfg(not(target_os = "android"))]
|
|
{
|
|
self.main.push_entry(
|
|
MainMenuEntry::SelectedPlayer,
|
|
MenuEntry::Options(
|
|
state.loc.t("menus.controls_menu.select_player.entry").to_owned(),
|
|
self.selected_player as usize,
|
|
vec![
|
|
state.loc.t("menus.controls_menu.select_player.player_1").to_owned(),
|
|
state.loc.t("menus.controls_menu.select_player.player_2").to_owned(),
|
|
],
|
|
),
|
|
);
|
|
|
|
self.main.push_entry(
|
|
MainMenuEntry::Controller,
|
|
MenuEntry::Active(state.loc.t("menus.controls_menu.controller.entry").to_owned()),
|
|
);
|
|
self.main
|
|
.push_entry(MainMenuEntry::Rebind, MenuEntry::Active(state.loc.t("menus.controls_menu.rebind").to_owned()));
|
|
self.main.push_entry(MainMenuEntry::Rumble, MenuEntry::Hidden);
|
|
}
|
|
|
|
if state.settings.touch_controls {
|
|
self.main.push_entry(
|
|
MainMenuEntry::DisplayTouchControls,
|
|
MenuEntry::Toggle(
|
|
state.loc.t("menus.options_menu.controls_menu.display_touch_controls").to_owned(),
|
|
state.settings.display_touch_controls,
|
|
),
|
|
);
|
|
}
|
|
self.main.push_entry(MainMenuEntry::Back, MenuEntry::Active(state.loc.t("common.back").to_owned()));
|
|
|
|
self.confirm_reset.push_entry(
|
|
ConfirmResetMenuEntry::Title,
|
|
MenuEntry::Disabled(state.loc.t("menus.controls_menu.reset_confirm_menu_title").to_owned()),
|
|
);
|
|
self.confirm_reset
|
|
.push_entry(ConfirmResetMenuEntry::Yes, MenuEntry::Active(state.loc.t("common.yes").to_owned()));
|
|
self.confirm_reset
|
|
.push_entry(ConfirmResetMenuEntry::No, MenuEntry::Active(state.loc.t("common.no").to_owned()));
|
|
|
|
self.player1_key_map = self.init_key_map(&state.settings.player1_key_map);
|
|
self.player2_key_map = self.init_key_map(&state.settings.player2_key_map);
|
|
self.player1_controller_button_map =
|
|
self.init_controller_button_map(&state.settings.player1_controller_button_map);
|
|
self.player2_controller_button_map =
|
|
self.init_controller_button_map(&state.settings.player2_controller_button_map);
|
|
|
|
self.confirm_rebind.draw_cursor = false;
|
|
self.confirm_rebind.non_interactive = true;
|
|
|
|
self.update_controller_options(state, ctx);
|
|
self.update_rebind_menu(state, ctx);
|
|
self.update_sizes(state);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn update_sizes(&mut self, state: &SharedGameState) {
|
|
self.main.update_width(state);
|
|
self.main.update_height(state);
|
|
self.main.x = ((state.canvas_size.0 - self.main.width as f32) / 2.0).floor() as isize;
|
|
self.main.y = ((state.canvas_size.1 - self.main.height as f32) / 2.0).floor() as isize;
|
|
|
|
self.select_controller.update_width(state);
|
|
self.select_controller.update_height(state);
|
|
self.select_controller.x = ((state.canvas_size.0 - self.select_controller.width as f32) / 2.0).floor() as isize;
|
|
self.select_controller.y =
|
|
((state.canvas_size.1 - self.select_controller.height as f32) / 2.0).floor() as isize;
|
|
|
|
self.rebind.update_width(state);
|
|
self.rebind.update_height(state);
|
|
self.rebind.x = ((state.canvas_size.0 - self.rebind.width as f32) / 2.0).floor() as isize;
|
|
self.rebind.y = ((state.canvas_size.1 - self.rebind.height as f32) / 2.0).floor() as isize;
|
|
|
|
self.confirm_rebind.update_width(state);
|
|
self.confirm_rebind.update_height(state);
|
|
self.confirm_rebind.x = ((state.canvas_size.0 - self.confirm_rebind.width as f32) / 2.0).floor() as isize;
|
|
self.confirm_rebind.y = ((state.canvas_size.1 - self.confirm_rebind.height as f32) / 2.0).floor() as isize;
|
|
|
|
self.confirm_reset.update_width(state);
|
|
self.confirm_reset.update_height(state);
|
|
self.confirm_reset.x = ((state.canvas_size.0 - self.confirm_reset.width as f32) / 2.0).floor() as isize;
|
|
self.confirm_reset.y = ((state.canvas_size.1 - self.confirm_reset.height as f32) / 2.0).floor() as isize;
|
|
}
|
|
|
|
fn init_key_map(&self, settings_key_map: &PlayerKeyMap) -> Vec<(ControlEntry, ScanCode)> {
|
|
let mut map = Vec::new();
|
|
|
|
map.push((ControlEntry::MenuOk, settings_key_map.menu_ok));
|
|
map.push((ControlEntry::MenuBack, settings_key_map.menu_back));
|
|
map.push((ControlEntry::Up, settings_key_map.up));
|
|
map.push((ControlEntry::Down, settings_key_map.down));
|
|
map.push((ControlEntry::Left, settings_key_map.left));
|
|
map.push((ControlEntry::Right, settings_key_map.right));
|
|
map.push((ControlEntry::Jump, settings_key_map.jump));
|
|
map.push((ControlEntry::Shoot, settings_key_map.shoot));
|
|
map.push((ControlEntry::PrevWeapon, settings_key_map.prev_weapon));
|
|
map.push((ControlEntry::NextWeapon, settings_key_map.next_weapon));
|
|
map.push((ControlEntry::Inventory, settings_key_map.inventory));
|
|
map.push((ControlEntry::Map, settings_key_map.map));
|
|
map.push((ControlEntry::Skip, settings_key_map.skip));
|
|
map.push((ControlEntry::Strafe, settings_key_map.strafe));
|
|
|
|
map
|
|
}
|
|
|
|
fn init_controller_button_map(
|
|
&self,
|
|
settings_controller_button_map: &PlayerControllerButtonMap,
|
|
) -> Vec<(ControlEntry, PlayerControllerInputType)> {
|
|
let mut map = Vec::new();
|
|
|
|
map.push((ControlEntry::MenuOk, settings_controller_button_map.menu_ok));
|
|
map.push((ControlEntry::MenuBack, settings_controller_button_map.menu_back));
|
|
map.push((ControlEntry::Up, settings_controller_button_map.up));
|
|
map.push((ControlEntry::Down, settings_controller_button_map.down));
|
|
map.push((ControlEntry::Left, settings_controller_button_map.left));
|
|
map.push((ControlEntry::Right, settings_controller_button_map.right));
|
|
map.push((ControlEntry::Jump, settings_controller_button_map.jump));
|
|
map.push((ControlEntry::Shoot, settings_controller_button_map.shoot));
|
|
map.push((ControlEntry::PrevWeapon, settings_controller_button_map.prev_weapon));
|
|
map.push((ControlEntry::NextWeapon, settings_controller_button_map.next_weapon));
|
|
map.push((ControlEntry::Inventory, settings_controller_button_map.inventory));
|
|
map.push((ControlEntry::Map, settings_controller_button_map.map));
|
|
map.push((ControlEntry::Skip, settings_controller_button_map.skip));
|
|
map.push((ControlEntry::Strafe, settings_controller_button_map.strafe));
|
|
|
|
map
|
|
}
|
|
|
|
fn update_rebind_menu(&mut self, state: &SharedGameState, ctx: &Context) {
|
|
self.rebind.entries.clear();
|
|
|
|
match self.selected_player {
|
|
Player::Player1 => {
|
|
if self.selected_controller == ControllerType::Keyboard {
|
|
for (k, v) in self.player1_key_map.iter() {
|
|
self.rebind.push_entry(
|
|
RebindMenuEntry::Control(*k),
|
|
MenuEntry::Control(
|
|
k.to_string(state).to_owned(),
|
|
ControlMenuData::String(format!("{:?}", v)),
|
|
),
|
|
);
|
|
}
|
|
} else {
|
|
for (k, v) in self.player1_controller_button_map.iter() {
|
|
let gamepad_sprite_offset = match state.settings.player1_controller_type {
|
|
ControllerType::Keyboard => 1,
|
|
ControllerType::Gamepad(index) => {
|
|
ctx.gamepad_context.get_gamepad_sprite_offset(index as usize)
|
|
}
|
|
};
|
|
|
|
self.rebind.push_entry(
|
|
RebindMenuEntry::Control(*k),
|
|
MenuEntry::Control(
|
|
k.to_string(state).to_owned(),
|
|
ControlMenuData::Rect(v.get_rect(gamepad_sprite_offset, &state.constants)),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
Player::Player2 => {
|
|
if self.selected_controller == ControllerType::Keyboard {
|
|
for (k, v) in self.player2_key_map.iter() {
|
|
self.rebind.push_entry(
|
|
RebindMenuEntry::Control(*k),
|
|
MenuEntry::Control(
|
|
k.to_string(state).to_owned(),
|
|
ControlMenuData::String(format!("{:?}", v)),
|
|
),
|
|
);
|
|
}
|
|
} else {
|
|
for (k, v) in self.player2_controller_button_map.iter() {
|
|
let gamepad_sprite_offset = match state.settings.player2_controller_type {
|
|
ControllerType::Keyboard => 1,
|
|
ControllerType::Gamepad(index) => {
|
|
ctx.gamepad_context.get_gamepad_sprite_offset(index as usize)
|
|
}
|
|
};
|
|
|
|
self.rebind.push_entry(
|
|
RebindMenuEntry::Control(*k),
|
|
MenuEntry::Control(
|
|
k.to_string(state).to_owned(),
|
|
ControlMenuData::Rect(v.get_rect(gamepad_sprite_offset, &state.constants)),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
self.rebind.push_entry(
|
|
RebindMenuEntry::Reset,
|
|
MenuEntry::Active(state.loc.t("menus.controls_menu.reset_confirm").to_owned()),
|
|
);
|
|
self.rebind.push_entry(RebindMenuEntry::Back, MenuEntry::Active(state.loc.t("common.back").to_owned()));
|
|
}
|
|
|
|
fn update_controller_options(&mut self, state: &SharedGameState, ctx: &Context) {
|
|
self.select_controller.entries.clear();
|
|
|
|
self.select_controller.push_entry(
|
|
SelectControllerMenuEntry::Keyboard,
|
|
MenuEntry::Active(state.loc.t("menus.controls_menu.controller.keyboard").to_owned()),
|
|
);
|
|
|
|
let gamepads = gamepad::get_gamepads(ctx);
|
|
|
|
let other_player_controller_type = match self.selected_player {
|
|
Player::Player1 => state.settings.player2_controller_type,
|
|
Player::Player2 => state.settings.player1_controller_type,
|
|
};
|
|
|
|
let mut available_gamepads = gamepads.len();
|
|
|
|
for i in 0..gamepads.len() {
|
|
if let ControllerType::Gamepad(index) = other_player_controller_type {
|
|
if index as usize == i {
|
|
available_gamepads -= 1;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
self.select_controller.push_entry(
|
|
SelectControllerMenuEntry::Gamepad(i),
|
|
MenuEntry::Active(format!("{} {}", gamepads[i].get_gamepad_name(), i + 1)),
|
|
);
|
|
}
|
|
|
|
self.select_controller
|
|
.push_entry(SelectControllerMenuEntry::Back, MenuEntry::Active(state.loc.t("common.back").to_owned()));
|
|
|
|
let controller_type = match self.selected_player {
|
|
Player::Player1 => state.settings.player1_controller_type,
|
|
Player::Player2 => state.settings.player2_controller_type,
|
|
};
|
|
|
|
let rumble = match self.selected_player {
|
|
Player::Player1 => state.settings.player1_rumble,
|
|
Player::Player2 => state.settings.player2_rumble,
|
|
};
|
|
|
|
if let ControllerType::Gamepad(index) = controller_type {
|
|
if index as usize >= available_gamepads {
|
|
self.selected_controller = ControllerType::Keyboard;
|
|
self.main.set_entry(MainMenuEntry::Rumble, MenuEntry::Hidden);
|
|
} else {
|
|
self.selected_controller = controller_type;
|
|
self.main.set_entry(
|
|
MainMenuEntry::Rumble,
|
|
MenuEntry::Toggle(state.loc.t("menus.controls_menu.rumble").to_owned(), rumble),
|
|
);
|
|
}
|
|
} else {
|
|
self.selected_controller = controller_type;
|
|
self.main.set_entry(MainMenuEntry::Rumble, MenuEntry::Hidden);
|
|
}
|
|
|
|
match self.selected_controller {
|
|
ControllerType::Keyboard => self.select_controller.selected = SelectControllerMenuEntry::Keyboard,
|
|
ControllerType::Gamepad(index) => {
|
|
self.select_controller.selected = SelectControllerMenuEntry::Gamepad(index as usize)
|
|
}
|
|
}
|
|
}
|
|
|
|
fn update_confirm_controls_menu(&mut self, state: &SharedGameState) {
|
|
match self.selected_control {
|
|
Some(control) => {
|
|
self.confirm_rebind.entries.clear();
|
|
|
|
self.confirm_rebind.push_entry(
|
|
0,
|
|
MenuEntry::DisabledWhite(state.tt(
|
|
"menus.controls_menu.rebind_confirm_menu.title",
|
|
&[("control", control.to_string(state).as_str())],
|
|
)),
|
|
);
|
|
self.confirm_rebind.push_entry(
|
|
1,
|
|
MenuEntry::Disabled(state.loc.t("menus.controls_menu.rebind_confirm_menu.cancel").to_owned()),
|
|
);
|
|
}
|
|
None => {}
|
|
}
|
|
}
|
|
|
|
fn reset_controls(&mut self, state: &mut SharedGameState, ctx: &Context) -> GameResult {
|
|
match self.selected_player {
|
|
Player::Player1 => {
|
|
if self.selected_controller == ControllerType::Keyboard {
|
|
state.settings.player1_key_map = p1_default_keymap();
|
|
self.player1_key_map = self.init_key_map(&state.settings.player1_key_map);
|
|
} else {
|
|
state.settings.player1_controller_button_map = player_default_controller_button_map();
|
|
self.player1_controller_button_map =
|
|
self.init_controller_button_map(&state.settings.player1_controller_button_map);
|
|
}
|
|
}
|
|
Player::Player2 => {
|
|
if self.selected_controller == ControllerType::Keyboard {
|
|
state.settings.player2_key_map = p2_default_keymap();
|
|
self.player2_key_map = self.init_key_map(&state.settings.player2_key_map);
|
|
} else {
|
|
state.settings.player2_controller_button_map = player_default_controller_button_map();
|
|
self.player2_controller_button_map =
|
|
self.init_controller_button_map(&state.settings.player2_controller_button_map);
|
|
}
|
|
}
|
|
}
|
|
|
|
state.settings.save(ctx)
|
|
}
|
|
|
|
fn is_key_occupied(&self, scan_code: ScanCode) -> bool {
|
|
let other_player_keymap = match self.selected_player {
|
|
Player::Player1 => &self.player2_key_map,
|
|
Player::Player2 => &self.player1_key_map,
|
|
};
|
|
|
|
for (_, v) in other_player_keymap.iter() {
|
|
if *v == scan_code {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
false
|
|
}
|
|
|
|
fn set_key(&mut self, state: &mut SharedGameState, scan_code: ScanCode, ctx: &Context) -> GameResult {
|
|
if self.selected_control.is_none() {
|
|
return Ok(());
|
|
}
|
|
|
|
let mut did_swap_controls = false;
|
|
|
|
match self.selected_control.unwrap() {
|
|
ControlEntry::Left => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_key_map.left = scan_code,
|
|
Player::Player2 => state.settings.player2_key_map.left = scan_code,
|
|
},
|
|
ControlEntry::Up => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_key_map.up = scan_code,
|
|
Player::Player2 => state.settings.player2_key_map.up = scan_code,
|
|
},
|
|
ControlEntry::Right => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_key_map.right = scan_code,
|
|
Player::Player2 => state.settings.player2_key_map.right = scan_code,
|
|
},
|
|
ControlEntry::Down => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_key_map.down = scan_code,
|
|
Player::Player2 => state.settings.player2_key_map.down = scan_code,
|
|
},
|
|
ControlEntry::PrevWeapon => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_key_map.prev_weapon = scan_code,
|
|
Player::Player2 => state.settings.player2_key_map.prev_weapon = scan_code,
|
|
},
|
|
ControlEntry::NextWeapon => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_key_map.next_weapon = scan_code,
|
|
Player::Player2 => state.settings.player2_key_map.next_weapon = scan_code,
|
|
},
|
|
ControlEntry::Jump => match self.selected_player {
|
|
Player::Player1 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player1_key_map.jump,
|
|
&mut state.settings.player1_key_map.shoot,
|
|
scan_code,
|
|
);
|
|
}
|
|
Player::Player2 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player2_key_map.jump,
|
|
&mut state.settings.player2_key_map.shoot,
|
|
scan_code,
|
|
);
|
|
}
|
|
},
|
|
ControlEntry::Shoot => match self.selected_player {
|
|
Player::Player1 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player1_key_map.shoot,
|
|
&mut state.settings.player1_key_map.jump,
|
|
scan_code,
|
|
);
|
|
}
|
|
Player::Player2 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player2_key_map.shoot,
|
|
&mut state.settings.player2_key_map.jump,
|
|
scan_code,
|
|
);
|
|
}
|
|
},
|
|
ControlEntry::Skip => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_key_map.skip = scan_code,
|
|
Player::Player2 => state.settings.player2_key_map.skip = scan_code,
|
|
},
|
|
ControlEntry::Inventory => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_key_map.inventory = scan_code,
|
|
Player::Player2 => state.settings.player2_key_map.inventory = scan_code,
|
|
},
|
|
ControlEntry::Map => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_key_map.map = scan_code,
|
|
Player::Player2 => state.settings.player2_key_map.map = scan_code,
|
|
},
|
|
ControlEntry::Strafe => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_key_map.strafe = scan_code,
|
|
Player::Player2 => state.settings.player2_key_map.strafe = scan_code,
|
|
},
|
|
ControlEntry::MenuOk => match self.selected_player {
|
|
Player::Player1 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player1_key_map.menu_ok,
|
|
&mut state.settings.player1_key_map.menu_back,
|
|
scan_code,
|
|
);
|
|
}
|
|
Player::Player2 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player2_key_map.menu_ok,
|
|
&mut state.settings.player2_key_map.menu_back,
|
|
scan_code,
|
|
);
|
|
}
|
|
},
|
|
ControlEntry::MenuBack => match self.selected_player {
|
|
Player::Player1 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player1_key_map.menu_back,
|
|
&mut state.settings.player1_key_map.menu_ok,
|
|
scan_code,
|
|
);
|
|
}
|
|
Player::Player2 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player2_key_map.menu_back,
|
|
&mut state.settings.player2_key_map.menu_ok,
|
|
scan_code,
|
|
);
|
|
}
|
|
},
|
|
}
|
|
|
|
state.settings.save(ctx)?;
|
|
|
|
let keymap = match self.selected_player {
|
|
Player::Player1 => &mut self.player1_key_map,
|
|
Player::Player2 => &mut self.player2_key_map,
|
|
};
|
|
|
|
for (entry, value) in keymap.iter_mut() {
|
|
if *entry == self.selected_control.unwrap() {
|
|
*value = scan_code;
|
|
}
|
|
|
|
if did_swap_controls {
|
|
let map = match self.selected_player {
|
|
Player::Player1 => &state.settings.player1_key_map,
|
|
Player::Player2 => &state.settings.player2_key_map,
|
|
};
|
|
|
|
match *entry {
|
|
ControlEntry::Jump => *value = map.jump,
|
|
ControlEntry::Shoot => *value = map.shoot,
|
|
ControlEntry::MenuOk => *value = map.menu_ok,
|
|
ControlEntry::MenuBack => *value = map.menu_back,
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn set_controller_input(
|
|
&mut self,
|
|
state: &mut SharedGameState,
|
|
input_type: PlayerControllerInputType,
|
|
ctx: &Context,
|
|
) -> GameResult {
|
|
if self.selected_control.is_none() {
|
|
return Ok(());
|
|
}
|
|
|
|
let mut did_swap_controls = false;
|
|
|
|
match self.selected_control.unwrap() {
|
|
ControlEntry::Left => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_controller_button_map.left = input_type,
|
|
Player::Player2 => state.settings.player2_controller_button_map.left = input_type,
|
|
},
|
|
ControlEntry::Up => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_controller_button_map.up = input_type,
|
|
Player::Player2 => state.settings.player2_controller_button_map.up = input_type,
|
|
},
|
|
ControlEntry::Right => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_controller_button_map.right = input_type,
|
|
Player::Player2 => state.settings.player2_controller_button_map.right = input_type,
|
|
},
|
|
ControlEntry::Down => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_controller_button_map.down = input_type,
|
|
Player::Player2 => state.settings.player2_controller_button_map.down = input_type,
|
|
},
|
|
ControlEntry::PrevWeapon => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_controller_button_map.prev_weapon = input_type,
|
|
Player::Player2 => state.settings.player2_controller_button_map.prev_weapon = input_type,
|
|
},
|
|
ControlEntry::NextWeapon => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_controller_button_map.next_weapon = input_type,
|
|
Player::Player2 => state.settings.player2_controller_button_map.next_weapon = input_type,
|
|
},
|
|
ControlEntry::Jump => match self.selected_player {
|
|
Player::Player1 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player1_controller_button_map.jump,
|
|
&mut state.settings.player1_controller_button_map.shoot,
|
|
input_type,
|
|
);
|
|
}
|
|
Player::Player2 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player2_controller_button_map.jump,
|
|
&mut state.settings.player2_controller_button_map.shoot,
|
|
input_type,
|
|
);
|
|
}
|
|
},
|
|
ControlEntry::Shoot => match self.selected_player {
|
|
Player::Player1 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player1_controller_button_map.shoot,
|
|
&mut state.settings.player1_controller_button_map.jump,
|
|
input_type,
|
|
);
|
|
}
|
|
Player::Player2 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player2_controller_button_map.shoot,
|
|
&mut state.settings.player2_controller_button_map.jump,
|
|
input_type,
|
|
);
|
|
}
|
|
},
|
|
ControlEntry::Skip => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_controller_button_map.skip = input_type,
|
|
Player::Player2 => state.settings.player2_controller_button_map.skip = input_type,
|
|
},
|
|
ControlEntry::Inventory => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_controller_button_map.inventory = input_type,
|
|
Player::Player2 => state.settings.player2_controller_button_map.inventory = input_type,
|
|
},
|
|
ControlEntry::Map => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_controller_button_map.map = input_type,
|
|
Player::Player2 => state.settings.player2_controller_button_map.map = input_type,
|
|
},
|
|
ControlEntry::Strafe => match self.selected_player {
|
|
Player::Player1 => state.settings.player1_controller_button_map.strafe = input_type,
|
|
Player::Player2 => state.settings.player2_controller_button_map.strafe = input_type,
|
|
},
|
|
ControlEntry::MenuOk => match self.selected_player {
|
|
Player::Player1 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player1_controller_button_map.menu_ok,
|
|
&mut state.settings.player1_controller_button_map.menu_back,
|
|
input_type,
|
|
);
|
|
}
|
|
Player::Player2 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player2_controller_button_map.menu_ok,
|
|
&mut state.settings.player2_controller_button_map.menu_back,
|
|
input_type,
|
|
);
|
|
}
|
|
},
|
|
ControlEntry::MenuBack => match self.selected_player {
|
|
Player::Player1 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player1_controller_button_map.menu_back,
|
|
&mut state.settings.player1_controller_button_map.menu_ok,
|
|
input_type,
|
|
);
|
|
}
|
|
Player::Player2 => {
|
|
did_swap_controls = self.swap_if_same(
|
|
&mut state.settings.player2_controller_button_map.menu_back,
|
|
&mut state.settings.player2_controller_button_map.menu_ok,
|
|
input_type,
|
|
);
|
|
}
|
|
},
|
|
}
|
|
|
|
state.settings.save(ctx)?;
|
|
|
|
let button_map = match self.selected_player {
|
|
Player::Player1 => &mut self.player1_controller_button_map,
|
|
Player::Player2 => &mut self.player2_controller_button_map,
|
|
};
|
|
|
|
for (entry, value) in button_map.iter_mut() {
|
|
if *entry == self.selected_control.unwrap() {
|
|
*value = input_type;
|
|
}
|
|
|
|
if did_swap_controls {
|
|
let map = match self.selected_player {
|
|
Player::Player1 => &state.settings.player1_controller_button_map,
|
|
Player::Player2 => &state.settings.player2_controller_button_map,
|
|
};
|
|
|
|
match *entry {
|
|
ControlEntry::Jump => *value = map.jump,
|
|
ControlEntry::Shoot => *value = map.shoot,
|
|
ControlEntry::MenuOk => *value = map.menu_ok,
|
|
ControlEntry::MenuBack => *value = map.menu_back,
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn swap_if_same<T: Eq + Copy>(&mut self, fst: &mut T, snd: &mut T, value: T) -> bool {
|
|
let mut swapped = false;
|
|
|
|
if *snd == value {
|
|
*snd = *fst;
|
|
swapped = true;
|
|
}
|
|
|
|
*fst = value;
|
|
|
|
swapped
|
|
}
|
|
|
|
fn normalize_gamepad_input(&self, input: PlayerControllerInputType) -> PlayerControllerInputType {
|
|
match input {
|
|
PlayerControllerInputType::ButtonInput(Button::DPadUp) => {
|
|
PlayerControllerInputType::Either(Button::DPadUp, Axis::LeftY, AxisDirection::Up)
|
|
}
|
|
PlayerControllerInputType::ButtonInput(Button::DPadDown) => {
|
|
PlayerControllerInputType::Either(Button::DPadDown, Axis::LeftY, AxisDirection::Down)
|
|
}
|
|
PlayerControllerInputType::ButtonInput(Button::DPadLeft) => {
|
|
PlayerControllerInputType::Either(Button::DPadLeft, Axis::LeftX, AxisDirection::Left)
|
|
}
|
|
PlayerControllerInputType::ButtonInput(Button::DPadRight) => {
|
|
PlayerControllerInputType::Either(Button::DPadRight, Axis::LeftX, AxisDirection::Right)
|
|
}
|
|
PlayerControllerInputType::AxisInput(Axis::LeftY, AxisDirection::Up) => {
|
|
PlayerControllerInputType::Either(Button::DPadUp, Axis::LeftY, AxisDirection::Up)
|
|
}
|
|
PlayerControllerInputType::AxisInput(Axis::LeftY, AxisDirection::Down) => {
|
|
PlayerControllerInputType::Either(Button::DPadDown, Axis::LeftY, AxisDirection::Down)
|
|
}
|
|
PlayerControllerInputType::AxisInput(Axis::LeftX, AxisDirection::Left) => {
|
|
PlayerControllerInputType::Either(Button::DPadLeft, Axis::LeftX, AxisDirection::Left)
|
|
}
|
|
PlayerControllerInputType::AxisInput(Axis::LeftX, AxisDirection::Right) => {
|
|
PlayerControllerInputType::Either(Button::DPadRight, Axis::LeftX, AxisDirection::Right)
|
|
}
|
|
PlayerControllerInputType::AxisInput(Axis::RightY, AxisDirection::Up) => {
|
|
PlayerControllerInputType::Either(Button::DPadUp, Axis::RightY, AxisDirection::Up)
|
|
}
|
|
PlayerControllerInputType::AxisInput(Axis::RightY, AxisDirection::Down) => {
|
|
PlayerControllerInputType::Either(Button::DPadDown, Axis::RightY, AxisDirection::Down)
|
|
}
|
|
PlayerControllerInputType::AxisInput(Axis::RightX, AxisDirection::Left) => {
|
|
PlayerControllerInputType::Either(Button::DPadLeft, Axis::RightX, AxisDirection::Left)
|
|
}
|
|
PlayerControllerInputType::AxisInput(Axis::RightX, AxisDirection::Right) => {
|
|
PlayerControllerInputType::Either(Button::DPadRight, Axis::RightX, AxisDirection::Right)
|
|
}
|
|
_ => input,
|
|
}
|
|
}
|
|
|
|
pub fn tick(
|
|
&mut self,
|
|
exit_action: &mut dyn FnMut(),
|
|
controller: &mut CombinedMenuController,
|
|
state: &mut SharedGameState,
|
|
ctx: &mut Context,
|
|
) -> GameResult {
|
|
self.update_sizes(state);
|
|
|
|
match self.current {
|
|
CurrentMenu::MainMenu => match self.main.tick(controller, state) {
|
|
MenuSelectionResult::Selected(MainMenuEntry::SelectedPlayer, toggle)
|
|
| MenuSelectionResult::Left(MainMenuEntry::SelectedPlayer, toggle, _)
|
|
| MenuSelectionResult::Right(MainMenuEntry::SelectedPlayer, toggle, _) => {
|
|
if let MenuEntry::Options(_, value, _) = toggle {
|
|
let (new_player, new_value) = match *value {
|
|
0 => (Player::Player2, 1),
|
|
1 => (Player::Player1, 0),
|
|
_ => unreachable!(),
|
|
};
|
|
|
|
*value = new_value;
|
|
|
|
self.selected_player = new_player;
|
|
self.selected_controller = new_player.controller_type(state);
|
|
|
|
self.update_controller_options(state, ctx);
|
|
self.update_rebind_menu(state, ctx);
|
|
}
|
|
}
|
|
MenuSelectionResult::Selected(MainMenuEntry::Controller, _) => {
|
|
if self.input_busy {
|
|
return Ok(());
|
|
}
|
|
|
|
self.update_controller_options(state, ctx);
|
|
self.current = CurrentMenu::SelectControllerMenu;
|
|
}
|
|
MenuSelectionResult::Selected(MainMenuEntry::Rebind, _) => {
|
|
self.current = CurrentMenu::RebindMenu;
|
|
}
|
|
MenuSelectionResult::Selected(MainMenuEntry::Rumble, toggle) => {
|
|
if let MenuEntry::Toggle(_, value) = toggle {
|
|
match self.selected_player {
|
|
Player::Player1 => {
|
|
state.settings.player1_rumble = !state.settings.player1_rumble;
|
|
|
|
if state.settings.player1_rumble {
|
|
if let ControllerType::Gamepad(idx) = self.selected_controller {
|
|
gamepad::set_rumble(
|
|
ctx,
|
|
state,
|
|
idx,
|
|
0,
|
|
0x5000,
|
|
(state.settings.timing_mode.get_tps() / 2) as u32,
|
|
)?;
|
|
}
|
|
}
|
|
|
|
*value = state.settings.player1_rumble;
|
|
}
|
|
Player::Player2 => {
|
|
state.settings.player2_rumble = !state.settings.player2_rumble;
|
|
|
|
if state.settings.player2_rumble {
|
|
if let ControllerType::Gamepad(idx) = self.selected_controller {
|
|
gamepad::set_rumble(
|
|
ctx,
|
|
state,
|
|
idx,
|
|
0,
|
|
0x5000,
|
|
(state.settings.timing_mode.get_tps() / 2) as u32,
|
|
)?;
|
|
}
|
|
}
|
|
|
|
*value = state.settings.player2_rumble;
|
|
}
|
|
}
|
|
|
|
state.settings.save(ctx)?;
|
|
}
|
|
}
|
|
MenuSelectionResult::Selected(MainMenuEntry::DisplayTouchControls, toggle) => {
|
|
if let MenuEntry::Toggle(_, value) = toggle {
|
|
state.settings.display_touch_controls = !state.settings.display_touch_controls;
|
|
let _ = state.settings.save(ctx);
|
|
|
|
*value = state.settings.display_touch_controls;
|
|
}
|
|
}
|
|
MenuSelectionResult::Selected(MainMenuEntry::Back, _) | MenuSelectionResult::Canceled => exit_action(),
|
|
_ => {}
|
|
},
|
|
CurrentMenu::SelectControllerMenu => match self.select_controller.tick(controller, state) {
|
|
MenuSelectionResult::Selected(SelectControllerMenuEntry::Keyboard, _) => {
|
|
if self.selected_player == Player::Player1 {
|
|
state.settings.player1_controller_type = ControllerType::Keyboard;
|
|
} else {
|
|
state.settings.player2_controller_type = ControllerType::Keyboard;
|
|
}
|
|
|
|
let _ = state.settings.save(ctx);
|
|
|
|
let mut new_menu_controller = CombinedMenuController::new();
|
|
new_menu_controller.add(state.settings.create_player1_controller());
|
|
new_menu_controller.add(state.settings.create_player2_controller());
|
|
self.input_busy = true;
|
|
self.main.non_interactive = true;
|
|
*controller = new_menu_controller;
|
|
|
|
self.selected_controller = ControllerType::Keyboard;
|
|
self.update_rebind_menu(state, ctx);
|
|
|
|
self.current = CurrentMenu::MainMenu;
|
|
}
|
|
MenuSelectionResult::Selected(SelectControllerMenuEntry::Gamepad(idx), _) => {
|
|
if self.selected_player == Player::Player1 {
|
|
state.settings.player1_controller_type = ControllerType::Gamepad(idx as u32);
|
|
} else {
|
|
state.settings.player2_controller_type = ControllerType::Gamepad(idx as u32);
|
|
}
|
|
|
|
let _ = state.settings.save(ctx);
|
|
|
|
let mut new_menu_controller = CombinedMenuController::new();
|
|
new_menu_controller.add(state.settings.create_player1_controller());
|
|
new_menu_controller.add(state.settings.create_player2_controller());
|
|
self.input_busy = true;
|
|
self.main.non_interactive = true;
|
|
*controller = new_menu_controller;
|
|
|
|
self.selected_controller = ControllerType::Gamepad(idx as u32);
|
|
self.update_rebind_menu(state, ctx);
|
|
|
|
self.current = CurrentMenu::MainMenu;
|
|
}
|
|
MenuSelectionResult::Selected(SelectControllerMenuEntry::Back, _) | MenuSelectionResult::Canceled => {
|
|
self.current = CurrentMenu::MainMenu;
|
|
}
|
|
_ => {}
|
|
},
|
|
CurrentMenu::RebindMenu => match self.rebind.tick(controller, state) {
|
|
MenuSelectionResult::Selected(RebindMenuEntry::Back, _) | MenuSelectionResult::Canceled => {
|
|
if !self.input_busy {
|
|
self.current = CurrentMenu::MainMenu;
|
|
}
|
|
}
|
|
MenuSelectionResult::Selected(RebindMenuEntry::Control(control), _) => {
|
|
if !self.input_busy {
|
|
self.selected_control = Some(control);
|
|
self.update_confirm_controls_menu(state);
|
|
self.input_busy = true;
|
|
self.current = CurrentMenu::ConfirmRebindMenu;
|
|
}
|
|
}
|
|
MenuSelectionResult::Selected(RebindMenuEntry::Reset, _) => {
|
|
self.confirm_reset.selected = ConfirmResetMenuEntry::default();
|
|
self.current = CurrentMenu::ConfirmResetMenu;
|
|
}
|
|
_ => {}
|
|
},
|
|
CurrentMenu::ConfirmRebindMenu => match self.confirm_rebind.tick(controller, state) {
|
|
_ => {
|
|
let pressed_keys: Vec<_> = ctx.keyboard_context.pressed_keys().into_iter().collect();
|
|
|
|
for key in pressed_keys.clone() {
|
|
if *key == ScanCode::Escape {
|
|
state.sound_manager.play_sfx(5);
|
|
self.current = CurrentMenu::RebindMenu;
|
|
return Ok(());
|
|
}
|
|
}
|
|
|
|
match self.selected_controller {
|
|
ControllerType::Keyboard => {
|
|
if pressed_keys.len() == 1 {
|
|
if !self.input_busy {
|
|
self.input_busy = true;
|
|
self.rebind.non_interactive = true;
|
|
|
|
let key = **pressed_keys.first().unwrap();
|
|
|
|
if self.is_key_occupied(key)
|
|
|| FORBIDDEN_SCANCODES.contains(&key)
|
|
|| self.selected_controller != ControllerType::Keyboard
|
|
{
|
|
state.sound_manager.play_sfx(12);
|
|
} else {
|
|
self.set_key(state, key, ctx)?;
|
|
self.update_rebind_menu(state, ctx);
|
|
self.selected_control = None;
|
|
state.sound_manager.play_sfx(18);
|
|
self.current = CurrentMenu::RebindMenu;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ControllerType::Gamepad(idx) => {
|
|
let pressed_gamepad_buttons: Vec<_> =
|
|
ctx.gamepad_context.pressed_buttons(idx).into_iter().collect();
|
|
|
|
for button in pressed_gamepad_buttons.clone() {
|
|
if button == Button::Start {
|
|
state.sound_manager.play_sfx(5);
|
|
self.current = CurrentMenu::RebindMenu;
|
|
return Ok(());
|
|
}
|
|
}
|
|
|
|
if pressed_gamepad_buttons.len() == 1 {
|
|
if !self.input_busy {
|
|
self.input_busy = true;
|
|
self.rebind.non_interactive = true;
|
|
|
|
let button = *pressed_gamepad_buttons.first().unwrap();
|
|
|
|
if self.selected_player.controller_type(state) != self.selected_controller {
|
|
state.sound_manager.play_sfx(12);
|
|
} else {
|
|
let normalized_input = self
|
|
.normalize_gamepad_input(PlayerControllerInputType::ButtonInput(button));
|
|
|
|
self.set_controller_input(state, normalized_input, ctx)?;
|
|
self.update_rebind_menu(state, ctx);
|
|
self.selected_control = None;
|
|
state.sound_manager.play_sfx(18);
|
|
self.current = CurrentMenu::RebindMenu;
|
|
}
|
|
}
|
|
}
|
|
|
|
let active_axes: Vec<_> = ctx.gamepad_context.active_axes(idx).into_iter().collect();
|
|
|
|
if active_axes.len() == 1 {
|
|
if !self.input_busy {
|
|
self.input_busy = true;
|
|
self.rebind.non_interactive = true;
|
|
|
|
if self.selected_player.controller_type(state) != self.selected_controller {
|
|
state.sound_manager.play_sfx(12);
|
|
} else {
|
|
let (axis, value) = *active_axes.first().unwrap();
|
|
let direction = AxisDirection::from_axis_data(axis, value);
|
|
let normalized_input = self.normalize_gamepad_input(
|
|
PlayerControllerInputType::AxisInput(axis, direction),
|
|
);
|
|
|
|
self.set_controller_input(state, normalized_input, ctx)?;
|
|
self.update_rebind_menu(state, ctx);
|
|
self.selected_control = None;
|
|
state.sound_manager.play_sfx(18);
|
|
self.current = CurrentMenu::RebindMenu;
|
|
}
|
|
}
|
|
}
|
|
|
|
if pressed_keys.is_empty() && pressed_gamepad_buttons.is_empty() && active_axes.is_empty() {
|
|
self.input_busy = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
CurrentMenu::ConfirmResetMenu => match self.confirm_reset.tick(controller, state) {
|
|
MenuSelectionResult::Selected(ConfirmResetMenuEntry::Yes, _) => {
|
|
self.reset_controls(state, ctx)?;
|
|
self.update_rebind_menu(state, ctx);
|
|
self.input_busy = true;
|
|
self.rebind.non_interactive = true;
|
|
self.current = CurrentMenu::RebindMenu;
|
|
}
|
|
MenuSelectionResult::Selected(ConfirmResetMenuEntry::No, _) | MenuSelectionResult::Canceled => {
|
|
self.current = CurrentMenu::RebindMenu;
|
|
}
|
|
_ => {}
|
|
},
|
|
}
|
|
|
|
if self.input_busy {
|
|
let pressed_keys = ctx.keyboard_context.pressed_keys();
|
|
let mut input_busy = pressed_keys.len() > 0;
|
|
|
|
let gamepads = ctx.gamepad_context.get_gamepads();
|
|
for idx in 0..gamepads.len() {
|
|
let pressed_gamepad_buttons = ctx.gamepad_context.pressed_buttons(idx as u32);
|
|
let active_axes = ctx.gamepad_context.active_axes(idx as u32);
|
|
|
|
input_busy = input_busy || !pressed_gamepad_buttons.is_empty() || !active_axes.is_empty();
|
|
}
|
|
|
|
self.input_busy = input_busy;
|
|
|
|
if !self.input_busy {
|
|
self.main.non_interactive = false;
|
|
self.rebind.non_interactive = false;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn draw(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
|
match self.current {
|
|
CurrentMenu::MainMenu => self.main.draw(state, ctx)?,
|
|
CurrentMenu::SelectControllerMenu => self.select_controller.draw(state, ctx)?,
|
|
CurrentMenu::RebindMenu => self.rebind.draw(state, ctx)?,
|
|
CurrentMenu::ConfirmRebindMenu => self.confirm_rebind.draw(state, ctx)?,
|
|
CurrentMenu::ConfirmResetMenu => self.confirm_reset.draw(state, ctx)?,
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|