use serde::{Deserialize, Serialize};
use crate::ScriptContext;
mod tortuise {
#[link(wasm_import_module = "tortuise")]
unsafe extern "C" {
pub safe fn is_key_pressed_this_frame(context: u64, keycode: u32) -> u32;
pub safe fn is_mouse_clicked_this_frame(context: u64) -> u32;
pub safe fn mouse_location(context: u64) -> u32;
pub safe fn scroll_direction_this_frame(context: u64) -> u32;
pub safe fn is_button_pressed_this_frame(context: u64, gamepad_id: u32, button: u32)
-> u32;
pub safe fn is_button_released_this_frame(
context: u64,
gamepad_id: u32,
button: u32,
) -> u32;
pub safe fn is_button_down(context: u64, gamepad_id: u32, button: u32) -> u32;
pub safe fn axis_value(context: u64, gamepad_id: u32, axis: u32) -> f32;
pub safe fn is_gamepad_connected_this_frame(context: u64) -> u32;
pub safe fn is_gamepad_connected(context: u64, gamepad_id: u32) -> u32;
pub safe fn gamepad_power_info(context: u64, gamepad_id: u32) -> u32;
pub safe fn is_focused(context: u64) -> u32;
pub safe fn was_focused_this_frame(context: u64) -> u32;
pub safe fn was_unfocused_this_frame(context: u64) -> u32;
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Position {
pub x: u16,
pub y: u16,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Direction {
Up = 1,
Down,
Left,
Right,
}
/// Represents a key.
#[derive(Debug, PartialOrd, PartialEq, Eq, Clone, Copy, Hash, Serialize, Deserialize)]
pub enum KeyCode {
/// Backspace key (Delete on macOS, Backspace on other platforms).
Backspace,
/// Enter key.
Enter,
/// Left arrow key.
Left,
/// Right arrow key.
Right,
/// Up arrow key.
Up,
/// Down arrow key.
Down,
/// Home key.
Home,
/// End key.
End,
/// Page up key.
PageUp,
/// Page down key.
PageDown,
/// Tab key.
Tab,
/// Shift + Tab key.
BackTab,
/// Delete key. (Fn+Delete on macOS, Delete on other platforms)
Delete,
/// Insert key.
Insert,
/// F key.
///
/// `KeyCode::F(1)` represents F1 key, etc.
F(u8),
/// A character.
///
/// `KeyCode::Char('c')` represents `c` character, etc.
Char(char),
/// Null.
Null,
/// Escape key.
Esc,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Button {
// Action Pad
South = 1,
East = 2,
North = 4,
West = 5,
C = 3,
Z = 6,
// Triggers
LeftTrigger = 7,
LeftTrigger2 = 9,
RightTrigger = 8,
RightTrigger2 = 10,
// Menu Pad
Select = 11,
Start = 12,
Mode = 13,
// Sticks
LeftThumb = 14,
RightThumb = 15,
// D-Pad
DPadUp = 16,
DPadDown = 17,
DPadLeft = 18,
DPadRight = 19,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Axis {
LeftStickX = 1,
LeftStickY = 2,
LeftZ = 3,
RightStickX = 4,
RightStickY = 5,
RightZ = 6,
DPadX = 7,
DPadY = 8,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum PowerInfo {
Wired,
Discharging(u8),
Charging(u8),
Charged,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Gamepad(u32);
impl From<u32> for Position {
fn from(value: u32) -> Self {
Self {
x: (value & 0xffff) as u16,
y: ((value >> 16) & 0xffff) as u16,
}
}
}
impl TryFrom<u32> for Direction {
type Error = ();
fn try_from(value: u32) -> Result<Self, Self::Error> {
match value {
1 => Ok(Direction::Up),
2 => Ok(Direction::Down),
3 => Ok(Direction::Left),
4 => Ok(Direction::Right),
_ => Err(()),
}
}
}
fn key_code_to_number(key_code: KeyCode) -> u32 {
match key_code {
KeyCode::Null => 0,
KeyCode::Backspace => 1 << 24,
KeyCode::Enter => 2 << 24,
KeyCode::Left => 3 << 24,
KeyCode::Right => 4 << 24,
KeyCode::Up => 5 << 24,
KeyCode::Down => 6 << 24,
KeyCode::Home => 7 << 24,
KeyCode::End => 8 << 24,
KeyCode::PageUp => 9 << 24,
KeyCode::PageDown => 10 << 24,
KeyCode::Tab => 11 << 24,
KeyCode::BackTab => 12 << 24,
KeyCode::Delete => 13 << 24,
KeyCode::Insert => 14 << 24,
KeyCode::F(f) => 15 << 24 | f as u32,
KeyCode::Char(c) => 16 << 24 | c as u32,
KeyCode::Esc => 17 << 24,
}
}
impl Gamepad {
pub fn is_button_pressed_this_frame(&self, context: &ScriptContext, button: Button) -> bool {
tortuise::is_button_pressed_this_frame(context.0, self.0, button as u32) > 0
}
pub fn is_button_released_this_frame(&self, context: &ScriptContext, button: Button) -> bool {
tortuise::is_button_released_this_frame(context.0, self.0, button as u32) > 0
}
pub fn is_button_down(&self, context: &ScriptContext, button: Button) -> bool {
tortuise::is_button_down(context.0, self.0, button as u32) > 0
}
pub fn axis_value(&self, context: &ScriptContext, axis: Axis) -> f32 {
tortuise::axis_value(context.0, self.0, axis as u32)
}
pub fn is_connected(&self, context: &ScriptContext) -> bool {
tortuise::is_gamepad_connected(context.0, self.0) > 0
}
pub fn power_info(&self, context: &ScriptContext) -> PowerInfo {
const WIRED: u32 = 1 << 16;
const DISCHARGING: u32 = 2 << 16;
const CHARGING: u32 = 3 << 16;
const CHARGED: u32 = 4 << 16;
match tortuise::gamepad_power_info(context.0, self.0) {
WIRED => PowerInfo::Wired,
power @ DISCHARGING..CHARGING => PowerInfo::Discharging((power & 0xff) as u8),
power @ CHARGING..CHARGED => PowerInfo::Charging((power & 0xff) as u8),
CHARGED => PowerInfo::Charged,
_ => PowerInfo::Unknown,
}
}
}
impl ScriptContext<'_> {
pub fn is_key_pressed_this_frame(&self, key_code: KeyCode) -> bool {
tortuise::is_key_pressed_this_frame(self.0, key_code_to_number(key_code)) > 0
}
pub fn is_mouse_clicked_this_frame(&self) -> bool {
tortuise::is_mouse_clicked_this_frame(self.0) > 0
}
pub fn mouse_location(&self) -> Option<Position> {
let location = tortuise::mouse_location(self.0);
(location != u32::MAX).then(|| location.into())
}
pub fn scroll_direction_this_frame(&self) -> Option<Direction> {
tortuise::scroll_direction_this_frame(self.0)
.try_into()
.ok()
}
pub fn is_gamepad_connected_this_frame(&self) -> Option<Gamepad> {
let gamepad_id = tortuise::is_gamepad_connected_this_frame(self.0);
if gamepad_id == 0 {
return None;
}
Some(Gamepad(gamepad_id))
}
pub fn is_focused(&self) -> bool {
tortuise::is_focused(self.0) > 0
}
pub fn was_focused_this_frame(&self) -> bool {
tortuise::was_focused_this_frame(self.0) > 0
}
pub fn was_unfocused_this_frame(&self) -> bool {
tortuise::was_unfocused_this_frame(self.0) > 0
}
}
|