mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-01-15 23:36:41 +00:00
remove gilrs dependency for controller support
This commit is contained in:
parent
9932b1209f
commit
84d9dbf877
|
@ -59,7 +59,6 @@ cpal = "0.13"
|
|||
directories = "3"
|
||||
downcast = "0.11"
|
||||
funty = "=1.1.0" # https://github.com/bitvecto-rs/bitvec/issues/105
|
||||
gilrs = { version = "0.9.0", features = ["serde-serialize"] }
|
||||
glutin = { git = "https://github.com/doukutsu-rs/glutin.git", rev = "8dd457b9adb7dbac7ade337246b6356c784272d9", optional = true, default_features = false, features = ["x11"] }
|
||||
imgui = "0.8.0"
|
||||
image = { version = "0.23", default-features = false, features = ["png", "bmp"] }
|
||||
|
|
|
@ -9,6 +9,7 @@ use std::time::{Duration, Instant};
|
|||
|
||||
use imgui::internal::RawWrapper;
|
||||
use imgui::{ConfigFlags, DrawCmd, DrawData, DrawIdx, DrawVert, Key, MouseCursor, TextureId, Ui};
|
||||
use sdl2::controller::GameController;
|
||||
use sdl2::event::{Event, WindowEvent};
|
||||
use sdl2::keyboard::Scancode;
|
||||
use sdl2::mouse::{Cursor, SystemCursor};
|
||||
|
@ -17,7 +18,7 @@ use sdl2::render::{Texture, TextureCreator, TextureQuery, WindowCanvas};
|
|||
use sdl2::video::GLProfile;
|
||||
use sdl2::video::Window;
|
||||
use sdl2::video::WindowContext;
|
||||
use sdl2::{keyboard, pixels, EventPump, Sdl, VideoSubsystem};
|
||||
use sdl2::{controller, keyboard, pixels, EventPump, GameControllerSubsystem, Sdl, VideoSubsystem};
|
||||
|
||||
use crate::common::{Color, Rect};
|
||||
use crate::framework::backend::{
|
||||
|
@ -25,6 +26,7 @@ use crate::framework::backend::{
|
|||
};
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::{GameError, GameResult};
|
||||
use crate::framework::gamepad::{Axis, Button};
|
||||
use crate::framework::graphics::BlendMode;
|
||||
use crate::framework::keyboard::ScanCode;
|
||||
use crate::framework::render_opengl::{GLContext, OpenGLRenderer};
|
||||
|
@ -42,6 +44,8 @@ pub struct SDL2Backend {
|
|||
|
||||
impl SDL2Backend {
|
||||
pub fn new(size_hint: (u16, u16)) -> GameResult<Box<dyn Backend>> {
|
||||
sdl2::hint::set("SDL_JOYSTICK_THREAD", "1");
|
||||
|
||||
let context = sdl2::init().map_err(GameError::WindowError)?;
|
||||
|
||||
let backend = SDL2Backend { context, size_hint };
|
||||
|
@ -141,12 +145,15 @@ struct SDL2Context {
|
|||
gl_context: Option<sdl2::video::GLContext>,
|
||||
blend_mode: sdl2::render::BlendMode,
|
||||
fullscreen_type: sdl2::video::FullscreenType,
|
||||
game_controller: GameControllerSubsystem,
|
||||
}
|
||||
|
||||
impl SDL2EventLoop {
|
||||
pub fn new(sdl: &Sdl, size_hint: (u16, u16)) -> GameResult<Box<dyn BackendEventLoop>> {
|
||||
let event_pump = sdl.event_pump().map_err(GameError::WindowError)?;
|
||||
let video = sdl.video().map_err(GameError::WindowError)?;
|
||||
let game_controller = sdl.game_controller().map_err(GameError::GamepadError)?;
|
||||
|
||||
let gl_attr = video.gl_attr();
|
||||
|
||||
gl_attr.set_context_profile(GLProfile::Compatibility);
|
||||
|
@ -160,8 +167,8 @@ impl SDL2EventLoop {
|
|||
window.opengl();
|
||||
|
||||
let window = window.build().map_err(|e| GameError::WindowError(e.to_string()))?;
|
||||
|
||||
let opengl_available = if let Ok(v) = std::env::var("CAVESTORY_NO_OPENGL") { v != "1" } else { true };
|
||||
|
||||
let event_loop = SDL2EventLoop {
|
||||
event_pump,
|
||||
refs: Rc::new(RefCell::new(SDL2Context {
|
||||
|
@ -170,6 +177,7 @@ impl SDL2EventLoop {
|
|||
gl_context: None,
|
||||
blend_mode: sdl2::render::BlendMode::Blend,
|
||||
fullscreen_type: sdl2::video::FullscreenType::Off,
|
||||
game_controller,
|
||||
})),
|
||||
opengl_available: RefCell::new(opengl_available),
|
||||
};
|
||||
|
@ -293,6 +301,39 @@ impl BackendEventLoop for SDL2EventLoop {
|
|||
ctx.keyboard_context.set_key(drs_scan, false);
|
||||
}
|
||||
}
|
||||
Event::ControllerDeviceAdded { which, .. } => {
|
||||
let game_controller = &self.refs.borrow().game_controller;
|
||||
|
||||
if game_controller.is_game_controller(which) {
|
||||
let controller = game_controller.open(which).unwrap();
|
||||
log::info!("Connected gamepad: {} (ID: {})", controller.name(), controller.instance_id());
|
||||
|
||||
let axis_sensitivity = state.settings.get_gamepad_axis_sensitivity(which);
|
||||
ctx.gamepad_context.add_gamepad(controller, axis_sensitivity);
|
||||
}
|
||||
}
|
||||
Event::ControllerDeviceRemoved { which, .. } => {
|
||||
let game_controller = &self.refs.borrow().game_controller;
|
||||
log::info!("Disconnected gamepad with ID {}", which);
|
||||
ctx.gamepad_context.remove_gamepad(which);
|
||||
}
|
||||
Event::ControllerAxisMotion { which, axis, value, .. } => {
|
||||
if let Some(drs_axis) = conv_gamepad_axis(axis) {
|
||||
let new_value = (value as f64) / i16::MAX as f64;
|
||||
ctx.gamepad_context.set_axis_value(which, drs_axis, new_value);
|
||||
ctx.gamepad_context.update_axes(which);
|
||||
}
|
||||
}
|
||||
Event::ControllerButtonDown { which, button, .. } => {
|
||||
if let Some(drs_button) = conv_gamepad_button(button) {
|
||||
ctx.gamepad_context.set_button(which, drs_button, true);
|
||||
}
|
||||
}
|
||||
Event::ControllerButtonUp { which, button, .. } => {
|
||||
if let Some(drs_button) = conv_gamepad_button(button) {
|
||||
ctx.gamepad_context.set_button(which, drs_button, false);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -1100,6 +1141,39 @@ fn conv_scancode(code: keyboard::Scancode) -> Option<ScanCode> {
|
|||
}
|
||||
}
|
||||
|
||||
fn conv_gamepad_button(code: controller::Button) -> Option<Button> {
|
||||
match code {
|
||||
controller::Button::A => Some(Button::South),
|
||||
controller::Button::B => Some(Button::East),
|
||||
controller::Button::X => Some(Button::West),
|
||||
controller::Button::Y => Some(Button::North),
|
||||
controller::Button::Back => Some(Button::Back),
|
||||
controller::Button::Guide => Some(Button::Guide),
|
||||
controller::Button::Start => Some(Button::Start),
|
||||
controller::Button::LeftStick => Some(Button::LeftStick),
|
||||
controller::Button::RightStick => Some(Button::RightStick),
|
||||
controller::Button::LeftShoulder => Some(Button::LeftShoulder),
|
||||
controller::Button::RightShoulder => Some(Button::RightShoulder),
|
||||
controller::Button::DPadUp => Some(Button::DPadUp),
|
||||
controller::Button::DPadDown => Some(Button::DPadDown),
|
||||
controller::Button::DPadLeft => Some(Button::DPadLeft),
|
||||
controller::Button::DPadRight => Some(Button::DPadRight),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn conv_gamepad_axis(code: controller::Axis) -> Option<Axis> {
|
||||
match code {
|
||||
controller::Axis::LeftX => Some(Axis::LeftX),
|
||||
controller::Axis::LeftY => Some(Axis::LeftY),
|
||||
controller::Axis::RightX => Some(Axis::RightX),
|
||||
controller::Axis::RightY => Some(Axis::RightY),
|
||||
controller::Axis::TriggerLeft => Some(Axis::TriggerLeft),
|
||||
controller::Axis::TriggerRight => Some(Axis::TriggerRight),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// based on imgui-sdl2 crate
|
||||
pub struct ImguiSdl2 {
|
||||
mouse_press: [bool; 5],
|
||||
|
|
|
@ -1,13 +1,25 @@
|
|||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use gilrs::{Axis, Button, Gamepad, GamepadId};
|
||||
use sdl2::controller::GameController;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{framework::context::Context, settings::PlayerControllerInputType};
|
||||
|
||||
#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Axis {
|
||||
LeftX,
|
||||
LeftY,
|
||||
RightX,
|
||||
RightY,
|
||||
TriggerLeft,
|
||||
TriggerRight,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum AxisDirection {
|
||||
None,
|
||||
Either,
|
||||
Up,
|
||||
Left,
|
||||
Right,
|
||||
|
@ -18,107 +30,169 @@ impl AxisDirection {
|
|||
pub fn compare(&self, value: f64, axis_sensitivity: f64) -> bool {
|
||||
match self {
|
||||
AxisDirection::None => false,
|
||||
AxisDirection::Up => value > axis_sensitivity,
|
||||
AxisDirection::Left => value < -axis_sensitivity,
|
||||
AxisDirection::Right => value > axis_sensitivity,
|
||||
AxisDirection::Down => value < -axis_sensitivity,
|
||||
AxisDirection::Either => value.abs() > 0.0,
|
||||
AxisDirection::Down | AxisDirection::Right => value > axis_sensitivity,
|
||||
AxisDirection::Up | AxisDirection::Left => value < -axis_sensitivity,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Button {
|
||||
South,
|
||||
East,
|
||||
West,
|
||||
North,
|
||||
|
||||
Back,
|
||||
Guide,
|
||||
Start,
|
||||
LeftStick,
|
||||
RightStick,
|
||||
LeftShoulder,
|
||||
RightShoulder,
|
||||
DPadUp,
|
||||
DPadDown,
|
||||
DPadLeft,
|
||||
DPadRight,
|
||||
}
|
||||
|
||||
pub struct GamepadData {
|
||||
controller: GameController,
|
||||
|
||||
left_x: f64,
|
||||
left_y: f64,
|
||||
right_x: f64,
|
||||
right_y: f64,
|
||||
trigger_left: f64,
|
||||
trigger_right: f64,
|
||||
|
||||
axis_sensitivity: f64,
|
||||
|
||||
pressed_buttons_set: HashSet<Button>,
|
||||
axis_values: HashMap<Axis, f64>,
|
||||
}
|
||||
|
||||
impl GamepadData {
|
||||
pub(crate) fn new(axis_sensitivity: f64) -> Self {
|
||||
GamepadData { left_x: 0.0, left_y: 0.0, right_x: 0.0, right_y: 0.0, axis_sensitivity }
|
||||
pub(crate) fn new(game_controller: GameController, axis_sensitivity: f64) -> Self {
|
||||
GamepadData {
|
||||
controller: game_controller,
|
||||
|
||||
left_x: 0.0,
|
||||
left_y: 0.0,
|
||||
right_x: 0.0,
|
||||
right_y: 0.0,
|
||||
trigger_left: 0.0,
|
||||
trigger_right: 0.0,
|
||||
|
||||
axis_sensitivity,
|
||||
|
||||
pressed_buttons_set: HashSet::with_capacity(16),
|
||||
axis_values: HashMap::with_capacity(8),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct GamepadContext {
|
||||
gamepads: HashMap<GamepadId, GamepadData>,
|
||||
gamepads: Vec<GamepadData>,
|
||||
}
|
||||
|
||||
impl GamepadContext {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self { gamepads: HashMap::new() }
|
||||
Self { gamepads: Vec::new() }
|
||||
}
|
||||
|
||||
fn gamepad_exists(&self, gamepad: &Gamepad) -> bool {
|
||||
self.gamepads.contains_key(&gamepad.id())
|
||||
fn get_gamepad(&self, gamepad_id: u32) -> Option<&GamepadData> {
|
||||
self.gamepads.iter().find(|gamepad| gamepad.controller.instance_id() == gamepad_id)
|
||||
}
|
||||
|
||||
pub(crate) fn add_gamepad(&mut self, gamepad: &Gamepad, axis_sensitivity: f64) {
|
||||
self.gamepads.insert(gamepad.id(), GamepadData::new(axis_sensitivity));
|
||||
fn get_gamepad_by_index(&self, gamepad_index: usize) -> Option<&GamepadData> {
|
||||
self.gamepads.get(gamepad_index)
|
||||
}
|
||||
|
||||
pub(crate) fn remove_gamepad(&mut self, gamepad: &Gamepad) {
|
||||
self.gamepads.remove(&gamepad.id());
|
||||
fn get_gamepad_mut(&mut self, gamepad_id: u32) -> Option<&mut GamepadData> {
|
||||
self.gamepads.iter_mut().find(|gamepad| gamepad.controller.instance_id() == gamepad_id)
|
||||
}
|
||||
|
||||
pub(crate) fn is_active(
|
||||
&self,
|
||||
gamepad: &Gamepad,
|
||||
input_type: &PlayerControllerInputType,
|
||||
axis_direction: AxisDirection,
|
||||
) -> bool {
|
||||
match input_type {
|
||||
PlayerControllerInputType::ButtonInput(button) => self.is_button_active(gamepad, *button),
|
||||
PlayerControllerInputType::AxisInput(axis) => self.is_axis_active(gamepad, *axis, axis_direction),
|
||||
PlayerControllerInputType::Either(button, axis) => {
|
||||
self.is_button_active(gamepad, *button) || self.is_axis_active(gamepad, *axis, axis_direction)
|
||||
pub(crate) fn add_gamepad(&mut self, game_controller: GameController, axis_sensitivity: f64) {
|
||||
self.gamepads.push(GamepadData::new(game_controller, axis_sensitivity));
|
||||
}
|
||||
|
||||
pub(crate) fn remove_gamepad(&mut self, gamepad_id: u32) {
|
||||
self.gamepads.retain(|data| data.controller.instance_id() != gamepad_id);
|
||||
}
|
||||
|
||||
pub(crate) fn set_button(&mut self, gamepad_id: u32, button: Button, pressed: bool) {
|
||||
if let Some(gamepad) = self.get_gamepad_mut(gamepad_id) {
|
||||
if pressed {
|
||||
gamepad.pressed_buttons_set.insert(button);
|
||||
} else {
|
||||
gamepad.pressed_buttons_set.remove(&button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_button_active(&self, gamepad: &Gamepad, button: Button) -> bool {
|
||||
if !self.gamepad_exists(gamepad) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gamepad.is_pressed(button)
|
||||
}
|
||||
|
||||
pub(crate) fn is_axis_active(&self, gamepad: &Gamepad, axis: Axis, direction: AxisDirection) -> bool {
|
||||
if !self.gamepad_exists(gamepad) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let data = self.gamepads.get(&gamepad.id()).unwrap();
|
||||
|
||||
match axis {
|
||||
Axis::LeftStickX => direction.compare(data.left_x, data.axis_sensitivity),
|
||||
Axis::LeftStickY => direction.compare(data.left_y, data.axis_sensitivity),
|
||||
Axis::RightStickX => direction.compare(data.right_x, data.axis_sensitivity),
|
||||
Axis::RightStickY => direction.compare(data.right_y, data.axis_sensitivity),
|
||||
_ => false,
|
||||
pub(crate) fn set_axis_value(&mut self, gamepad_id: u32, axis: Axis, value: f64) {
|
||||
if let Some(gamepad) = self.get_gamepad_mut(gamepad_id) {
|
||||
gamepad.axis_values.insert(axis, value);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn update_axes(&mut self, gamepad: &Gamepad) {
|
||||
if !self.gamepad_exists(gamepad) {
|
||||
return;
|
||||
pub(crate) fn is_active(
|
||||
&self,
|
||||
gamepad_index: u32,
|
||||
input_type: &PlayerControllerInputType,
|
||||
axis_direction: AxisDirection,
|
||||
) -> bool {
|
||||
match input_type {
|
||||
PlayerControllerInputType::ButtonInput(button) => self.is_button_active(gamepad_index, *button),
|
||||
PlayerControllerInputType::AxisInput(axis) => self.is_axis_active(gamepad_index, *axis, axis_direction),
|
||||
PlayerControllerInputType::Either(button, axis) => {
|
||||
self.is_button_active(gamepad_index, *button)
|
||||
|| self.is_axis_active(gamepad_index, *axis, axis_direction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_button_active(&self, gamepad_index: u32, button: Button) -> bool {
|
||||
if let Some(gamepad) = self.get_gamepad_by_index(gamepad_index as usize) {
|
||||
return gamepad.pressed_buttons_set.contains(&button);
|
||||
}
|
||||
|
||||
let data = self.gamepads.get_mut(&gamepad.id()).unwrap();
|
||||
false
|
||||
}
|
||||
|
||||
let mut axes = [
|
||||
(&mut data.left_x, Axis::LeftStickX),
|
||||
(&mut data.left_y, Axis::LeftStickY),
|
||||
(&mut data.right_x, Axis::RightStickX),
|
||||
(&mut data.right_y, Axis::RightStickY),
|
||||
];
|
||||
pub(crate) fn is_axis_active(&self, gamepad_index: u32, axis: Axis, direction: AxisDirection) -> bool {
|
||||
if let Some(gamepad) = self.get_gamepad_by_index(gamepad_index as usize) {
|
||||
return match axis {
|
||||
Axis::LeftX => direction.compare(gamepad.left_x, gamepad.axis_sensitivity),
|
||||
Axis::LeftY => direction.compare(gamepad.left_y, gamepad.axis_sensitivity),
|
||||
Axis::RightX => direction.compare(gamepad.right_x, gamepad.axis_sensitivity),
|
||||
Axis::RightY => direction.compare(gamepad.right_y, gamepad.axis_sensitivity),
|
||||
Axis::TriggerLeft => direction.compare(gamepad.trigger_left, 0.0),
|
||||
Axis::TriggerRight => direction.compare(gamepad.trigger_right, 0.0),
|
||||
};
|
||||
}
|
||||
|
||||
for (axis_val, id) in axes.iter_mut() {
|
||||
if let Some(axis) = gamepad.axis_data(*id) {
|
||||
**axis_val = if axis.value().abs() < 0.12 { 0.0 } else { axis.value() } as f64;
|
||||
false
|
||||
}
|
||||
|
||||
pub(crate) fn update_axes(&mut self, gamepad_id: u32) {
|
||||
if let Some(gamepad) = self.get_gamepad_mut(gamepad_id) {
|
||||
let mut axes = [
|
||||
(&mut gamepad.left_x, Axis::LeftX),
|
||||
(&mut gamepad.left_y, Axis::LeftY),
|
||||
(&mut gamepad.right_x, Axis::RightX),
|
||||
(&mut gamepad.right_y, Axis::RightY),
|
||||
(&mut gamepad.trigger_left, Axis::TriggerLeft),
|
||||
(&mut gamepad.trigger_right, Axis::TriggerRight),
|
||||
];
|
||||
|
||||
for (axis_val, id) in axes.iter_mut() {
|
||||
if let Some(axis) = gamepad.axis_values.get(id) {
|
||||
**axis_val = if axis.abs() < 0.12 { 0.0 } else { *axis };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -130,31 +204,27 @@ impl Default for GamepadContext {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add_gamepad(context: &mut Context, gamepad: &Gamepad, axis_sensitivity: f64) {
|
||||
context.gamepad_context.add_gamepad(gamepad, axis_sensitivity);
|
||||
pub fn add_gamepad(context: &mut Context, game_controller: GameController, axis_sensitivity: f64) {
|
||||
context.gamepad_context.add_gamepad(game_controller, axis_sensitivity);
|
||||
}
|
||||
|
||||
pub fn remove_gamepad(context: &mut Context, gamepad: &Gamepad) {
|
||||
context.gamepad_context.remove_gamepad(gamepad);
|
||||
pub fn remove_gamepad(context: &mut Context, gamepad_id: u32) {
|
||||
context.gamepad_context.remove_gamepad(gamepad_id);
|
||||
}
|
||||
|
||||
pub fn is_active(
|
||||
ctx: &Context,
|
||||
gamepad: &Gamepad,
|
||||
gamepad_index: u32,
|
||||
input_type: &PlayerControllerInputType,
|
||||
axis_direction: AxisDirection,
|
||||
) -> bool {
|
||||
ctx.gamepad_context.is_active(gamepad, input_type, axis_direction)
|
||||
ctx.gamepad_context.is_active(gamepad_index, input_type, axis_direction)
|
||||
}
|
||||
|
||||
pub fn is_button_active(ctx: &Context, gamepad: &Gamepad, button: Button) -> bool {
|
||||
ctx.gamepad_context.is_button_active(gamepad, button)
|
||||
pub fn is_button_active(ctx: &Context, gamepad_index: u32, button: Button) -> bool {
|
||||
ctx.gamepad_context.is_button_active(gamepad_index, button)
|
||||
}
|
||||
|
||||
pub fn is_axis_active(ctx: &Context, gamepad: &Gamepad, axis: Axis, direction: AxisDirection) -> bool {
|
||||
ctx.gamepad_context.is_axis_active(gamepad, axis, direction)
|
||||
}
|
||||
|
||||
pub fn update_axes(ctx: &mut Context, gamepad: &Gamepad) {
|
||||
ctx.gamepad_context.update_axes(gamepad);
|
||||
pub fn is_axis_active(ctx: &Context, gamepad_index: u32, axis: Axis, direction: AxisDirection) -> bool {
|
||||
ctx.gamepad_context.is_axis_active(gamepad_index, axis, direction)
|
||||
}
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::framework::gamepad::{self, AxisDirection};
|
||||
use crate::framework::gamepad::{self, AxisDirection, Button};
|
||||
use crate::input::player_controller::PlayerController;
|
||||
use crate::player::TargetPlayer;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::{bitfield, settings::PlayerControllerInputType};
|
||||
|
||||
use gilrs::{Button, GamepadId};
|
||||
|
||||
bitfield! {
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct KeyState(u16);
|
||||
|
@ -31,7 +29,7 @@ bitfield! {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct GamepadController {
|
||||
gamepad_id: GamepadId,
|
||||
gamepad_id: u32,
|
||||
target: TargetPlayer,
|
||||
state: KeyState,
|
||||
old_state: KeyState,
|
||||
|
@ -39,7 +37,7 @@ pub struct GamepadController {
|
|||
}
|
||||
|
||||
impl GamepadController {
|
||||
pub fn new(gamepad_id: GamepadId, target: TargetPlayer) -> GamepadController {
|
||||
pub fn new(gamepad_id: u32, target: TargetPlayer) -> GamepadController {
|
||||
GamepadController { gamepad_id, target, state: KeyState(0), old_state: KeyState(0), trigger: KeyState(0) }
|
||||
}
|
||||
}
|
||||
|
@ -51,41 +49,35 @@ impl PlayerController for GamepadController {
|
|||
TargetPlayer::Player2 => &state.settings.player2_controller_button_map,
|
||||
};
|
||||
|
||||
if let Some(gilrs) = &state.gilrs {
|
||||
if let Some(gamepad) = gilrs.connected_gamepad(self.gamepad_id) {
|
||||
gamepad::update_axes(ctx, &gamepad);
|
||||
|
||||
self.state.set_up(gamepad::is_active(ctx, &gamepad, &button_map.up, AxisDirection::Up));
|
||||
self.state.set_down(gamepad::is_active(ctx, &gamepad, &button_map.down, AxisDirection::Down));
|
||||
self.state.set_left(gamepad::is_active(ctx, &gamepad, &button_map.left, AxisDirection::Left));
|
||||
self.state.set_right(gamepad::is_active(ctx, &gamepad, &button_map.right, AxisDirection::Right));
|
||||
self.state.set_map(gamepad::is_active(ctx, &gamepad, &button_map.map, AxisDirection::None));
|
||||
self.state.set_inventory(gamepad::is_active(ctx, &gamepad, &button_map.inventory, AxisDirection::None));
|
||||
self.state.set_jump(gamepad::is_active(ctx, &gamepad, &button_map.jump, AxisDirection::None));
|
||||
self.state.set_shoot(gamepad::is_active(ctx, &gamepad, &button_map.shoot, AxisDirection::None));
|
||||
self.state.set_next_weapon(gamepad::is_active(
|
||||
ctx,
|
||||
&gamepad,
|
||||
&button_map.next_weapon,
|
||||
AxisDirection::None,
|
||||
));
|
||||
self.state.set_prev_weapon(gamepad::is_active(
|
||||
ctx,
|
||||
&gamepad,
|
||||
&button_map.prev_weapon,
|
||||
AxisDirection::None,
|
||||
));
|
||||
self.state.set_escape(gamepad::is_active(
|
||||
ctx,
|
||||
&gamepad,
|
||||
&PlayerControllerInputType::ButtonInput(Button::Start),
|
||||
AxisDirection::None,
|
||||
));
|
||||
self.state.set_enter(gamepad::is_active(ctx, &gamepad, &button_map.jump, AxisDirection::None));
|
||||
self.state.set_skip(gamepad::is_active(ctx, &gamepad, &button_map.skip, AxisDirection::None));
|
||||
self.state.set_strafe(gamepad::is_active(ctx, &gamepad, &button_map.strafe, AxisDirection::None));
|
||||
}
|
||||
}
|
||||
self.state.set_up(gamepad::is_active(ctx, self.gamepad_id, &button_map.up, AxisDirection::Up));
|
||||
self.state.set_down(gamepad::is_active(ctx, self.gamepad_id, &button_map.down, AxisDirection::Down));
|
||||
self.state.set_left(gamepad::is_active(ctx, self.gamepad_id, &button_map.left, AxisDirection::Left));
|
||||
self.state.set_right(gamepad::is_active(ctx, self.gamepad_id, &button_map.right, AxisDirection::Right));
|
||||
self.state.set_map(gamepad::is_active(ctx, self.gamepad_id, &button_map.map, AxisDirection::None));
|
||||
self.state.set_inventory(gamepad::is_active(ctx, self.gamepad_id, &button_map.inventory, AxisDirection::None));
|
||||
self.state.set_jump(gamepad::is_active(ctx, self.gamepad_id, &button_map.jump, AxisDirection::None));
|
||||
self.state.set_shoot(gamepad::is_active(ctx, self.gamepad_id, &button_map.shoot, AxisDirection::None));
|
||||
self.state.set_next_weapon(gamepad::is_active(
|
||||
ctx,
|
||||
self.gamepad_id,
|
||||
&button_map.next_weapon,
|
||||
AxisDirection::None,
|
||||
));
|
||||
self.state.set_prev_weapon(gamepad::is_active(
|
||||
ctx,
|
||||
self.gamepad_id,
|
||||
&button_map.prev_weapon,
|
||||
AxisDirection::None,
|
||||
));
|
||||
self.state.set_escape(gamepad::is_active(
|
||||
ctx,
|
||||
self.gamepad_id,
|
||||
&PlayerControllerInputType::ButtonInput(Button::Start),
|
||||
AxisDirection::None,
|
||||
));
|
||||
self.state.set_enter(gamepad::is_active(ctx, self.gamepad_id, &button_map.jump, AxisDirection::None));
|
||||
self.state.set_skip(gamepad::is_active(ctx, self.gamepad_id, &button_map.skip, AxisDirection::Either));
|
||||
self.state.set_strafe(gamepad::is_active(ctx, self.gamepad_id, &button_map.strafe, AxisDirection::Either));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
30
src/lib.rs
30
src/lib.rs
|
@ -11,8 +11,6 @@ use std::sync::Mutex;
|
|||
use std::time::{Duration, Instant};
|
||||
|
||||
use directories::ProjectDirs;
|
||||
use framework::gamepad;
|
||||
use gilrs::EventType;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use crate::builtin_fs::BuiltinFS;
|
||||
|
@ -112,34 +110,6 @@ impl Game {
|
|||
}
|
||||
|
||||
fn update(&mut self, ctx: &mut Context) -> GameResult {
|
||||
{
|
||||
let state_ref = unsafe { &mut *self.state.get() };
|
||||
|
||||
if let Some(gilrs) = &mut state_ref.gilrs {
|
||||
while let Some(e) = gilrs.next_event() {
|
||||
let gamepad = gilrs.gamepad(e.id);
|
||||
|
||||
match e.event {
|
||||
EventType::Connected => {
|
||||
log::info!("Gamepad connected: {} (ID: {})", gamepad.name(), gamepad.id());
|
||||
|
||||
let axis_sensitivity = state_ref.settings.get_gamepad_axis_sensitivity(gamepad.id());
|
||||
gamepad::add_gamepad(ctx, &gamepad, axis_sensitivity);
|
||||
|
||||
// TODO: replace the controller of all players that use this gamepad from keyboard to gamepad
|
||||
}
|
||||
EventType::Disconnected => {
|
||||
log::info!("Gamepad disconnected: {} (ID: {})", gamepad.name(), gamepad.id());
|
||||
gamepad::remove_gamepad(ctx, &gamepad);
|
||||
|
||||
// TODO: fall back to keyboard for all players that use this gamepad
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(scene) = &mut self.scene {
|
||||
let state_ref = unsafe { &mut *self.state.get() };
|
||||
|
||||
|
|
|
@ -1773,7 +1773,7 @@ impl Scene for GameScene {
|
|||
if !state.control_flags.control_enabled() && !state.textscript_vm.flags.cutscene_skip() =>
|
||||
{
|
||||
state.touch_controls.control_type = TouchControlType::Dialog;
|
||||
if self.player1.controller.inventory() {
|
||||
if self.player1.controller.skip() {
|
||||
self.skip_counter += 1;
|
||||
if self.skip_counter >= CUTSCENE_SKIP_WAIT {
|
||||
state.textscript_vm.flags.set_cutscene_skip(true);
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use gilrs::{Axis, Button, GamepadId};
|
||||
|
||||
use crate::framework::context::Context;
|
||||
use crate::framework::error::GameResult;
|
||||
use crate::framework::filesystem::{user_create, user_open};
|
||||
use crate::framework::gamepad::{Axis, Button};
|
||||
use crate::framework::keyboard::ScanCode;
|
||||
use crate::graphics::VSyncMode;
|
||||
use crate::input::gamepad_player_controller::GamepadController;
|
||||
|
@ -232,7 +231,7 @@ impl Settings {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_gamepad_axis_sensitivity(&self, id: GamepadId) -> f64 {
|
||||
pub fn get_gamepad_axis_sensitivity(&self, id: u32) -> f64 {
|
||||
if self.player1_controller_type == ControllerType::Gamepad(id) {
|
||||
self.player1_controller_axis_sensitivity
|
||||
} else if self.player2_controller_type == ControllerType::Gamepad(id) {
|
||||
|
@ -337,7 +336,7 @@ fn p2_default_keymap() -> PlayerKeyMap {
|
|||
#[derive(serde::Serialize, serde::Deserialize, Eq, PartialEq)]
|
||||
pub enum ControllerType {
|
||||
Keyboard,
|
||||
Gamepad(GamepadId),
|
||||
Gamepad(u32),
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
|
@ -366,16 +365,16 @@ pub struct PlayerControllerButtonMap {
|
|||
#[inline(always)]
|
||||
pub fn player_default_controller_button_map() -> PlayerControllerButtonMap {
|
||||
PlayerControllerButtonMap {
|
||||
left: PlayerControllerInputType::Either(Button::DPadLeft, Axis::LeftStickX),
|
||||
up: PlayerControllerInputType::Either(Button::DPadUp, Axis::LeftStickY),
|
||||
right: PlayerControllerInputType::Either(Button::DPadRight, Axis::LeftStickX),
|
||||
down: PlayerControllerInputType::Either(Button::DPadDown, Axis::LeftStickY),
|
||||
prev_weapon: PlayerControllerInputType::ButtonInput(Button::LeftTrigger),
|
||||
next_weapon: PlayerControllerInputType::ButtonInput(Button::RightTrigger),
|
||||
jump: PlayerControllerInputType::ButtonInput(Button::East),
|
||||
shoot: PlayerControllerInputType::ButtonInput(Button::South),
|
||||
skip: PlayerControllerInputType::ButtonInput(Button::LeftTrigger2),
|
||||
strafe: PlayerControllerInputType::ButtonInput(Button::RightTrigger2),
|
||||
left: PlayerControllerInputType::Either(Button::DPadLeft, Axis::LeftX),
|
||||
up: PlayerControllerInputType::Either(Button::DPadUp, Axis::LeftY),
|
||||
right: PlayerControllerInputType::Either(Button::DPadRight, Axis::LeftX),
|
||||
down: PlayerControllerInputType::Either(Button::DPadDown, Axis::LeftY),
|
||||
prev_weapon: PlayerControllerInputType::ButtonInput(Button::LeftShoulder),
|
||||
next_weapon: PlayerControllerInputType::ButtonInput(Button::RightShoulder),
|
||||
jump: PlayerControllerInputType::ButtonInput(Button::South),
|
||||
shoot: PlayerControllerInputType::ButtonInput(Button::East),
|
||||
skip: PlayerControllerInputType::AxisInput(Axis::TriggerLeft),
|
||||
strafe: PlayerControllerInputType::AxisInput(Axis::TriggerRight),
|
||||
inventory: PlayerControllerInputType::ButtonInput(Button::North),
|
||||
map: PlayerControllerInputType::ButtonInput(Button::West),
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ use crate::framework::error::GameResult;
|
|||
use crate::framework::graphics::{create_texture_mutable, set_render_target};
|
||||
use crate::framework::keyboard::ScanCode;
|
||||
use crate::framework::vfs::OpenOptions;
|
||||
use crate::framework::{filesystem, gamepad, graphics};
|
||||
use crate::framework::{filesystem, graphics};
|
||||
#[cfg(feature = "hooks")]
|
||||
use crate::hooks::init_hooks;
|
||||
use crate::i18n::Locale;
|
||||
|
@ -38,8 +38,6 @@ use crate::stage::StageData;
|
|||
use crate::texture_set::TextureSet;
|
||||
use crate::vanilla::VanillaExtractor;
|
||||
|
||||
use gilrs::Gilrs;
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub enum TimingMode {
|
||||
_50Hz,
|
||||
|
@ -289,7 +287,6 @@ pub struct SharedGameState {
|
|||
pub super_quake_counter: u16,
|
||||
pub teleporter_slots: Vec<(u16, u16)>,
|
||||
pub carets: Vec<Caret>,
|
||||
pub gilrs: Option<Gilrs>,
|
||||
pub touch_controls: TouchControls,
|
||||
pub mod_path: Option<String>,
|
||||
pub mod_list: ModList,
|
||||
|
@ -334,16 +331,6 @@ impl SharedGameState {
|
|||
let mut sound_manager = SoundManager::new(ctx)?;
|
||||
let settings = Settings::load(ctx)?;
|
||||
let mod_requirements = ModRequirements::load(ctx)?;
|
||||
let mut gilrs = Gilrs::new().ok();
|
||||
|
||||
if let Some(gilrs) = &mut gilrs {
|
||||
for (id, gamepad) in gilrs.gamepads() {
|
||||
log::info!("Found gamepad {} (ID {})", gamepad.name(), id);
|
||||
|
||||
let axis_sensitivity = settings.get_gamepad_axis_sensitivity(id);
|
||||
gamepad::add_gamepad(ctx, &gamepad, axis_sensitivity);
|
||||
}
|
||||
}
|
||||
|
||||
let vanilla_extractor = VanillaExtractor::from(ctx, "Doukutsu.exe".to_string());
|
||||
if vanilla_extractor.is_some() {
|
||||
|
@ -437,7 +424,6 @@ impl SharedGameState {
|
|||
super_quake_counter: 0,
|
||||
teleporter_slots: Vec::with_capacity(8),
|
||||
carets: Vec::with_capacity(32),
|
||||
gilrs,
|
||||
touch_controls: TouchControls::new(),
|
||||
mod_path: None,
|
||||
mod_list,
|
||||
|
|
Loading…
Reference in a new issue