summaryrefslogtreecommitdiff
path: root/platforms/tortuise-script-wasm/src/input.rs
diff options
context:
space:
mode:
authorMica White <botahamec@outlook.com>2026-10-26 10:52:04 -0400
committerMica White <botahamec@outlook.com>2026-10-26 10:58:46 -0400
commitec40f6e3acc7874b82709ab81b254c741529fdff (patch)
treee3dfdc315bd0c6f1d2efcf442c2cfb3317d6810f /platforms/tortuise-script-wasm/src/input.rs
parente3c5839159903658a667f789963f20a31567b25c (diff)
Finish engineHEADmain
Diffstat (limited to 'platforms/tortuise-script-wasm/src/input.rs')
-rw-r--r--platforms/tortuise-script-wasm/src/input.rs264
1 files changed, 264 insertions, 0 deletions
diff --git a/platforms/tortuise-script-wasm/src/input.rs b/platforms/tortuise-script-wasm/src/input.rs
new file mode 100644
index 0000000..07cbe62
--- /dev/null
+++ b/platforms/tortuise-script-wasm/src/input.rs
@@ -0,0 +1,264 @@
+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
+ }
+}