From 88f81df3ae6b4c5e9bfed77e367e1886770425b9 Mon Sep 17 00:00:00 2001 From: Fenrir Date: Thu, 27 Jul 2017 20:19:11 -0600 Subject: [PATCH] Refactor HID module --- ctru-rs/src/services/hid.rs | 186 +++++++++++++++++++----------------- 1 file changed, 99 insertions(+), 87 deletions(-) diff --git a/ctru-rs/src/services/hid.rs b/ctru-rs/src/services/hid.rs index bcf6d1f..de1be99 100644 --- a/ctru-rs/src/services/hid.rs +++ b/ctru-rs/src/services/hid.rs @@ -1,76 +1,65 @@ -use std::convert::Into; +//! HID service +//! +//! The HID service provides access to user input such as button presses, touch screen presses, +//! and circle pad information. It also provides information from the sound volume slider, +//! the accelerometer, and the gyroscope. -pub enum PadKey { - A, - B, - Select, - Start, - DPadRight, - DPadLeft, - DPadUp, - DPadDown, - R, - L, - X, - Y, - ZL, - ZR, - Touch, - CSRight, - CSLeft, - CSUp, - CSDown, - CRight, - CLeft, - CUp, - CDown, - // convenience catch-all for dpad and cpad - Up, - Down, - Left, - Right, -} - -impl From for u32 { - fn from(p: PadKey) -> u32 { - use self::PadKey::*; - use ::libctru::_bindgen_ty_18::*; - match p { - Up => KEY_DUP as u32 | KEY_CPAD_UP as u32, - Down => KEY_DDOWN as u32 | KEY_CPAD_DOWN as u32, - Left => KEY_DLEFT as u32 | KEY_CPAD_LEFT as u32, - Right => KEY_DRIGHT as u32 | KEY_CPAD_RIGHT as u32, - - A => KEY_A as u32, - B => KEY_B as u32, - X => KEY_X as u32, - Y => KEY_Y as u32, - L => KEY_L as u32, - R => KEY_R as u32, - ZL => KEY_ZL as u32, - ZR => KEY_ZR as u32, - Start => KEY_START as u32, - Select => KEY_SELECT as u32, - Touch => KEY_TOUCH as u32, - CSRight => KEY_CSTICK_RIGHT as u32, - CSLeft => KEY_CSTICK_LEFT as u32, - CSUp => KEY_CSTICK_UP as u32, - CSDown => KEY_CSTICK_DOWN as u32, - CRight => KEY_CPAD_RIGHT as u32, - CLeft => KEY_CPAD_LEFT as u32, - CDown => KEY_CPAD_DOWN as u32, - CUp => KEY_CPAD_UP as u32, - DPadLeft => KEY_DLEFT as u32, - DPadRight => KEY_DRIGHT as u32, - DPadUp => KEY_DUP as u32, - DPadDown => KEY_DDOWN as u32, - } +/// A set of flags corresponding to the button and directional pad +/// inputs on the 3DS +bitflags! { + #[derive(Default)] + pub struct KeyPad: u32 { + const KEY_A = 1u32 << 0; + const KEY_B = 1u32 << 1; + const KEY_SELECT = 1u32 << 2; + const KEY_START = 1u32 << 3; + const KEY_DRIGHT = 1u32 << 4; + const KEY_DLEFT = 1u32 << 5; + const KEY_DUP = 1u32 << 6; + const KEY_DDOWN = 1u32 << 7; + const KEY_R = 1u32 << 8; + const KEY_L = 1u32 << 9; + const KEY_X = 1u32 << 10; + const KEY_Y = 1u32 << 11; + const KEY_ZL = 1u32 << 14; + const KEY_ZR = 1u32 << 15; + const KEY_TOUCH = 1u32 << 20; + const KEY_CSTICK_RIGHT = 1u32 << 24; + const KEY_CSTICK_LEFT = 1u32 << 25; + const KEY_CSTICK_UP = 1u32 << 26; + const KEY_CSTICK_DOWN = 1u32 << 27; + const KEY_CPAD_RIGHT = 1u32 << 28; + const KEY_CPAD_LEFT = 1u32 << 29; + const KEY_CPAD_UP = 1u32 << 30; + const KEY_CPAD_DOWN = 1u32 << 31; + // convenience catch-all for the dpad and cpad + const KEY_UP = KEY_DUP.bits | KEY_CPAD_UP.bits; + const KEY_DOWN = KEY_DDOWN.bits | KEY_CPAD_DOWN.bits; + const KEY_LEFT = KEY_DLEFT.bits | KEY_CPAD_LEFT.bits; + const KEY_RIGHT = KEY_DRIGHT.bits | KEY_CPAD_RIGHT.bits; } } +/// A reference-counted handle to the HID service. The service is closed +/// when all instances of this struct fall out of scope. +/// +/// This service requires no special permissions to use. pub struct Hid(()); +/// Represents user input to the touchscreen. +pub struct TouchPosition(::libctru::touchPosition); + +/// Represents the current position of the 3DS circle pad. +pub struct CirclePosition(::libctru::circlePosition); + +/// Initializes the HID service. +/// +/// # Errors +/// +/// This function will return an error if the service was unable to be initialized. +/// Since this service requires no special or elevated permissions, errors are +/// rare in practice. impl Hid { pub fn init() -> ::Result { unsafe { @@ -83,44 +72,67 @@ impl Hid { } } + /// Scans the HID service for all user input occurring on the current + /// frame. This function should be called on every frame when polling + /// for user input. pub fn scan_input(&self) { unsafe { ::libctru::hidScanInput() }; } - pub fn key_down(&self, key: PadKey) -> bool { - let k: u32 = key.into(); + /// Returns a bitflag struct representing which buttons have just been pressed + /// on the current frame (and were not pressed on the previous frame). + pub fn keys_held(&self) -> KeyPad { unsafe { - if ::libctru::hidKeysDown() & k != 0 { - true - } else { - false - } + let keys = ::libctru::hidKeysHeld(); + KeyPad::from_bits_truncate(keys) } } - pub fn key_held(&self, key: PadKey) -> bool { - let k: u32 = key.into(); + /// Returns a bitflag struct representing which buttons have been held down + /// during the current frame. + pub fn keys_down(&self) -> KeyPad { unsafe { - if ::libctru::hidKeysHeld() & k != 0 { - true - } else { - false - } + let keys = ::libctru::hidKeysDown(); + KeyPad::from_bits_truncate(keys) } } - pub fn key_up(&self, key: PadKey) -> bool { - let k: u32 = key.into(); + /// Returns a bitflag struct representing which buttons have just been released on + /// the current frame. + pub fn keys_up(&self) -> KeyPad { unsafe { - if ::libctru::hidKeysUp() & k != 0 { - return true; - } else { - return false; - } + let keys = ::libctru::hidKeysUp(); + KeyPad::from_bits_truncate(keys) } } } +impl TouchPosition { + /// Create a new TouchPosition instance. + pub fn new() -> Self { + TouchPosition(::libctru::touchPosition { px: 0, py: 0 }) + } + + /// Returns the current touch position in pixels. + pub fn get(&mut self) -> (u16, u16) { + unsafe { ::libctru::hidTouchRead(&mut self.0); } + (self.0.px, self.0.py) + } +} + +impl CirclePosition { + /// Create a new CirclePosition instance. + pub fn new() -> Self { + CirclePosition(::libctru::circlePosition { dx: 0, dy: 0 }) + } + + /// Returns the current circle pad position in (x, y) form. + pub fn get(&mut self) -> (i16, i16) { + unsafe { ::libctru::hidCircleRead(&mut self.0); } + (self.0.dx, self.0.dy) + } +} + impl Drop for Hid { fn drop(&mut self) { unsafe { ::libctru::hidExit() };