#![allow(non_camel_case_types)]
use strum_macros::{Display, EnumString, FromRepr, IntoStaticStr};
use crate::enums::bitflag_impl::BitFlags;
pub const JOYSTICK_MASK: u32 = 0xf0000;
pub const CSTICK_MASK: u32 = 0xf00000;
pub const ANYTRIGGER_MASK: u32 = 0x8000_0000;
pub const DIGITAL_TRIGGER_MASK: u32 = 0x60;
#[rustfmt::skip]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum EngineInput {
None = 0,
DPAD_LEFT = 1 << 0,
DPAD_RIGHT = 1 << 1,
DPAD_DOWN = 1 << 2,
DPAD_UP = 1 << 3,
Z = 1 << 4,
R = 1 << 5,
L = 1 << 6,
A = 1 << 8,
B = 1 << 9,
X = 1 << 10,
Y = 1 << 11,
START = 1 << 12,
JOYSTICK_UP = 1 << 16,
JOYSTICK_DOWN = 1 << 17,
JOYSTICK_LEFT = 1 << 18,
JOYSTICK_RIGHT = 1 << 19,
CSTICK_UP = 1 << 20,
CSTICK_DOWN = 1 << 21,
CSTICK_LEFT = 1 << 22,
CSTICK_RIGHT = 1 << 23,
ANY_TRIGGER = 1 << 31,
Raw(u32)
}
#[rustfmt::skip]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[repr(u16)]
pub enum ControllerInput {
None = 0,
DPAD_LEFT = 1 << 0,
DPAD_RIGHT = 1 << 1,
DPAD_DOWN = 1 << 2,
DPAD_UP = 1 << 3,
Z = 1 << 4,
R = 1 << 5,
L = 1 << 6,
A = 1 << 8,
B = 1 << 9,
X = 1 << 10,
Y = 1 << 11,
START = 1 << 12,
Raw(u16)
}
#[derive(
Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, EnumString, IntoStaticStr, Display, FromRepr,
)]
#[repr(i8)]
pub enum StickRegion {
DEAD_ZONE = -1,
UP = 0,
UP_RIGHT = 1,
RIGHT = 2,
DOWN_RIGHT = 3,
DOWN = 4,
DOWN_LEFT = 5,
LEFT = 6,
UP_LEFT = 7,
}
impl Default for StickRegion {
#[inline]
fn default() -> Self {
Self::DEAD_ZONE
}
}
impl StickRegion {
pub fn to_utf_arrow(&self) -> &'static str {
match self {
StickRegion::DEAD_ZONE => "•",
StickRegion::UP => "↑",
StickRegion::UP_RIGHT => "↗",
StickRegion::RIGHT => "→",
StickRegion::DOWN_RIGHT => "↘",
StickRegion::DOWN => "↓",
StickRegion::DOWN_LEFT => "↙",
StickRegion::LEFT => "←",
StickRegion::UP_LEFT => "↖",
}
}
pub fn from_coordinates(mut x: f32, mut y: f32) -> Self {
use StickRegion as R;
if -0.2875 < x && x < 0.2875 {
x = 0.0;
}
if -0.2875 < y && y < 0.2875 {
y = 0.0;
}
match () {
_ if x == 0.0 && y == 0.0 => R::DEAD_ZONE,
_ if x > 0.0 && y > 0.0 => R::UP_RIGHT,
_ if x > 0.0 && y < 0.0 => R::DOWN_RIGHT,
_ if x < 0.0 && y < 0.0 => R::DOWN_LEFT,
_ if x < 0.0 && y > 0.0 => R::UP_LEFT,
_ if y > 0.0 => R::UP,
_ if x > 0.0 => R::RIGHT,
_ if y < 0.0 => R::DOWN,
_ if x < 0.0 => R::LEFT,
_ => R::DEAD_ZONE,
}
}
pub fn from_engine_bits(bits: u32) -> Self {
use StickRegion as R;
let masked = bits & JOYSTICK_MASK;
if masked == 0u32 {
return R::DEAD_ZONE;
}
let js_bits = EngineInput::from(masked);
let up = js_bits.contains(EngineInput::JOYSTICK_UP.into());
let down = js_bits.contains(EngineInput::JOYSTICK_DOWN.into());
let left = js_bits.contains(EngineInput::JOYSTICK_LEFT.into());
let right = js_bits.contains(EngineInput::JOYSTICK_RIGHT.into());
match () {
_ if up && left => R::UP_LEFT,
_ if down && right => R::DOWN_RIGHT,
_ if down && left => R::DOWN_LEFT,
_ if up && left => R::UP_LEFT,
_ if up => R::UP,
_ if right => R::RIGHT,
_ if down => R::DOWN,
_ if left => R::LEFT,
_ => panic!("Somehow failed all conditions"),
}
}
#[inline]
pub fn is_cardinal(&self) -> bool {
(*self as i8 & 1) == 0
}
#[inline]
pub fn is_diagonal(&self) -> bool {
(*self as i8 & 1) != 0
}
#[inline]
pub fn is_deadzone(&self) -> bool {
(*self as i8).is_negative()
}
pub fn valid_sdi(&self, prev: StickRegion) -> bool {
if self.is_deadzone() || *self == prev {
return false;
}
if prev.is_cardinal() || prev.is_deadzone() {
return true;
}
if *self as i8 % 2 == 1 || {
let temp = (*self as i8 - prev as i8).abs();
temp == 3 || temp == 5
} {
return true;
}
false
}
}