rich_sdl2_rust/event/game_controller/
button.rs1use std::{
4 ffi::{CStr, CString},
5 str::FromStr,
6};
7
8use crate::{bind, SdlError};
9
10#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Hash)]
12pub enum FourButton {
13 Up,
15 Right,
17 Down,
19 Left,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Hash)]
26#[non_exhaustive]
27pub enum Button {
28 LeftFour(FourButton),
30 RightFour(FourButton),
32 Back,
34 Guide,
36 Start,
38 LeftStick,
40 RightStick,
42 LeftShoulder,
44 RightShoulder,
46}
47
48impl Button {
49 pub(super) fn from_raw(raw: bind::SDL_GameControllerButton) -> Option<Self> {
50 let val = match raw {
51 bind::SDL_CONTROLLER_BUTTON_A => Button::RightFour(FourButton::Down),
52 bind::SDL_CONTROLLER_BUTTON_B => Button::RightFour(FourButton::Right),
53 bind::SDL_CONTROLLER_BUTTON_X => Button::RightFour(FourButton::Left),
54 bind::SDL_CONTROLLER_BUTTON_Y => Button::RightFour(FourButton::Up),
55 bind::SDL_CONTROLLER_BUTTON_BACK => Button::Back,
56 bind::SDL_CONTROLLER_BUTTON_GUIDE => Button::Guide,
57 bind::SDL_CONTROLLER_BUTTON_START => Button::Start,
58 bind::SDL_CONTROLLER_BUTTON_LEFTSTICK => Button::LeftStick,
59 bind::SDL_CONTROLLER_BUTTON_RIGHTSTICK => Button::RightStick,
60 bind::SDL_CONTROLLER_BUTTON_LEFTSHOULDER => Button::LeftShoulder,
61 bind::SDL_CONTROLLER_BUTTON_DPAD_DOWN => Button::LeftFour(FourButton::Down),
62 bind::SDL_CONTROLLER_BUTTON_DPAD_RIGHT => Button::LeftFour(FourButton::Right),
63 bind::SDL_CONTROLLER_BUTTON_DPAD_LEFT => Button::LeftFour(FourButton::Left),
64 bind::SDL_CONTROLLER_BUTTON_DPAD_UP => Button::LeftFour(FourButton::Up),
65 _ => return None,
66 };
67 Some(val)
68 }
69
70 pub(super) fn as_raw(self) -> bind::SDL_GameControllerButton {
71 match self {
72 Button::LeftFour(FourButton::Up) => bind::SDL_CONTROLLER_BUTTON_Y,
73 Button::LeftFour(FourButton::Right) => bind::SDL_CONTROLLER_BUTTON_B,
74 Button::LeftFour(FourButton::Down) => bind::SDL_CONTROLLER_BUTTON_A,
75 Button::LeftFour(FourButton::Left) => bind::SDL_CONTROLLER_BUTTON_X,
76 Button::RightFour(FourButton::Up) => bind::SDL_CONTROLLER_BUTTON_DPAD_UP,
77 Button::RightFour(FourButton::Right) => bind::SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
78 Button::RightFour(FourButton::Down) => bind::SDL_CONTROLLER_BUTTON_DPAD_DOWN,
79 Button::RightFour(FourButton::Left) => bind::SDL_CONTROLLER_BUTTON_DPAD_LEFT,
80 Button::Back => bind::SDL_CONTROLLER_BUTTON_BACK,
81 Button::Guide => bind::SDL_CONTROLLER_BUTTON_GUIDE,
82 Button::Start => bind::SDL_CONTROLLER_BUTTON_START,
83 Button::LeftStick => bind::SDL_CONTROLLER_BUTTON_LEFTSTICK,
84 Button::RightStick => bind::SDL_CONTROLLER_BUTTON_RIGHTSTICK,
85 Button::LeftShoulder => bind::SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
86 Button::RightShoulder => bind::SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
87 }
88 }
89
90 #[must_use]
92 pub fn to_mapping_string(self) -> Option<String> {
93 let ptr = unsafe { bind::SDL_GameControllerGetStringForButton(self.as_raw()) };
94 if ptr.is_null() {
95 return None;
96 }
97 let cstr = unsafe { CStr::from_ptr(ptr) };
98 Some(cstr.to_string_lossy().to_string())
99 }
100}
101
102impl std::fmt::Display for Button {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 let c_str =
105 unsafe { CStr::from_ptr(bind::SDL_GameControllerGetStringForButton(self.as_raw())) };
106 write!(f, "{}", c_str.to_str().unwrap())
107 }
108}
109
110impl FromStr for Button {
111 type Err = SdlError;
112
113 fn from_str(s: &str) -> Result<Self, Self::Err> {
114 let cstr = CString::new(s).map_err(|_| SdlError::Others {
115 msg: "string must not be empty".into(),
116 })?;
117 let axis = unsafe { bind::SDL_GameControllerGetButtonFromString(cstr.as_ptr()) };
118 Button::from_raw(axis).ok_or_else(|| SdlError::Others {
119 msg: "the axis was not found".into(),
120 })
121 }
122}