From 14801b6ee09c15d047a66dff64161bd92d422590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?charlotte=20=F0=9F=8C=B8?= Date: Thu, 12 Nov 2026 14:25:21 -0800 Subject: [PATCH] Python input events and sketch folder asset root. --- crates/processing_core/src/constants.rs | 45 +++- crates/processing_ffi/src/lib.rs | 240 ++---------------- crates/processing_input/src/keys.rs | 145 +++++++++++ crates/processing_input/src/lib.rs | 2 + .../processing_pyo3/processing_py/__init__.py | 20 +- crates/processing_pyo3/src/constants.rs | 35 ++- crates/processing_pyo3/src/graphics.rs | 16 +- crates/processing_pyo3/src/input.rs | 169 ++++-------- crates/processing_pyo3/src/lib.rs | 153 ++++++++--- crates/processing_pyo3/src/surface.rs | 1 - crates/processing_wasm/src/lib.rs | 239 +---------------- 11 files changed, 438 insertions(+), 627 deletions(-) create mode 100644 crates/processing_input/src/keys.rs diff --git a/crates/processing_core/src/constants.rs b/crates/processing_core/src/constants.rs index 3fb7ba0c..f6771497 100644 --- a/crates/processing_core/src/constants.rs +++ b/crates/processing_core/src/constants.rs @@ -138,7 +138,7 @@ pub const TAU: f32 = std::f32::consts::TAU; pub const DEG_TO_RAD: f32 = std::f32::consts::PI / 180.0; pub const RAD_TO_DEG: f32 = 180.0 / std::f32::consts::PI; -// Key codes stay numeric (compared against `key_code`); values must match `key_code_to_u32`. +// Key codes are GLFW values, mapped to Bevy `KeyCode`s by `processing_input::keys`. pub const KEY_A: u32 = 65; pub const KEY_B: u32 = 66; @@ -223,3 +223,46 @@ pub const F9: u32 = 298; pub const F10: u32 = 299; pub const F11: u32 = 300; pub const F12: u32 = 301; +pub const F13: u32 = 302; +pub const F14: u32 = 303; +pub const F15: u32 = 304; +pub const F16: u32 = 305; +pub const F17: u32 = 306; +pub const F18: u32 = 307; +pub const F19: u32 = 308; +pub const F20: u32 = 309; +pub const F21: u32 = 310; +pub const F22: u32 = 311; +pub const F23: u32 = 312; +pub const F24: u32 = 313; +pub const F25: u32 = 314; + +pub const CAPS_LOCK: u32 = 280; +pub const SCROLL_LOCK: u32 = 281; +pub const NUM_LOCK: u32 = 282; +pub const PRINT_SCREEN: u32 = 283; +pub const PAUSE: u32 = 284; + +pub const NUMPAD_0: u32 = 320; +pub const NUMPAD_1: u32 = 321; +pub const NUMPAD_2: u32 = 322; +pub const NUMPAD_3: u32 = 323; +pub const NUMPAD_4: u32 = 324; +pub const NUMPAD_5: u32 = 325; +pub const NUMPAD_6: u32 = 326; +pub const NUMPAD_7: u32 = 327; +pub const NUMPAD_8: u32 = 328; +pub const NUMPAD_9: u32 = 329; +pub const NUMPAD_DECIMAL: u32 = 330; +pub const NUMPAD_DIVIDE: u32 = 331; +pub const NUMPAD_MULTIPLY: u32 = 332; +pub const NUMPAD_SUBTRACT: u32 = 333; +pub const NUMPAD_ADD: u32 = 334; +pub const NUMPAD_ENTER: u32 = 335; +pub const NUMPAD_EQUAL: u32 = 336; + +pub const SHIFT_RIGHT: u32 = 344; +pub const CONTROL_RIGHT: u32 = 345; +pub const ALT_RIGHT: u32 = 346; +pub const SUPER_RIGHT: u32 = 347; +pub const CONTEXT_MENU: u32 = 348; diff --git a/crates/processing_ffi/src/lib.rs b/crates/processing_ffi/src/lib.rs index 2b1e8c79..f6db5d22 100644 --- a/crates/processing_ffi/src/lib.rs +++ b/crates/processing_ffi/src/lib.rs @@ -4109,6 +4109,19 @@ pub const PROCESSING_KEY_F9: u32 = 298; pub const PROCESSING_KEY_F10: u32 = 299; pub const PROCESSING_KEY_F11: u32 = 300; pub const PROCESSING_KEY_F12: u32 = 301; +pub const PROCESSING_KEY_F13: u32 = 302; +pub const PROCESSING_KEY_F14: u32 = 303; +pub const PROCESSING_KEY_F15: u32 = 304; +pub const PROCESSING_KEY_F16: u32 = 305; +pub const PROCESSING_KEY_F17: u32 = 306; +pub const PROCESSING_KEY_F18: u32 = 307; +pub const PROCESSING_KEY_F19: u32 = 308; +pub const PROCESSING_KEY_F20: u32 = 309; +pub const PROCESSING_KEY_F21: u32 = 310; +pub const PROCESSING_KEY_F22: u32 = 311; +pub const PROCESSING_KEY_F23: u32 = 312; +pub const PROCESSING_KEY_F24: u32 = 313; +pub const PROCESSING_KEY_F25: u32 = 314; pub const PROCESSING_KEY_NUMPAD_0: u32 = 320; pub const PROCESSING_KEY_NUMPAD_1: u32 = 321; pub const PROCESSING_KEY_NUMPAD_2: u32 = 322; @@ -4327,7 +4340,8 @@ pub extern "C" fn processing_key() -> u32 { #[unsafe(no_mangle)] pub extern "C" fn processing_key_code() -> u32 { error::clear_error(); - error::check(|| input_key_code().map(|opt| opt.map(key_code_to_u32).unwrap_or(0))).unwrap_or(0) + error::check(|| input_key_code().map(|opt| opt.and_then(key_code_to_u32).unwrap_or(0))) + .unwrap_or(0) } #[unsafe(no_mangle)] @@ -4347,227 +4361,3 @@ pub extern "C" fn processing_mouse_wheel() -> f32 { error::clear_error(); error::check(input_mouse_wheel).unwrap_or(0.0) } - -fn key_code_from_u32(val: u32) -> processing::prelude::error::Result { - match val { - PROCESSING_KEY_SPACE => Ok(KeyCode::Space), - PROCESSING_KEY_QUOTE => Ok(KeyCode::Quote), - PROCESSING_KEY_COMMA => Ok(KeyCode::Comma), - PROCESSING_KEY_MINUS => Ok(KeyCode::Minus), - PROCESSING_KEY_PERIOD => Ok(KeyCode::Period), - PROCESSING_KEY_SLASH => Ok(KeyCode::Slash), - PROCESSING_KEY_0 => Ok(KeyCode::Digit0), - PROCESSING_KEY_1 => Ok(KeyCode::Digit1), - PROCESSING_KEY_2 => Ok(KeyCode::Digit2), - PROCESSING_KEY_3 => Ok(KeyCode::Digit3), - PROCESSING_KEY_4 => Ok(KeyCode::Digit4), - PROCESSING_KEY_5 => Ok(KeyCode::Digit5), - PROCESSING_KEY_6 => Ok(KeyCode::Digit6), - PROCESSING_KEY_7 => Ok(KeyCode::Digit7), - PROCESSING_KEY_8 => Ok(KeyCode::Digit8), - PROCESSING_KEY_9 => Ok(KeyCode::Digit9), - PROCESSING_KEY_SEMICOLON => Ok(KeyCode::Semicolon), - PROCESSING_KEY_EQUAL => Ok(KeyCode::Equal), - PROCESSING_KEY_A => Ok(KeyCode::KeyA), - PROCESSING_KEY_B => Ok(KeyCode::KeyB), - PROCESSING_KEY_C => Ok(KeyCode::KeyC), - PROCESSING_KEY_D => Ok(KeyCode::KeyD), - PROCESSING_KEY_E => Ok(KeyCode::KeyE), - PROCESSING_KEY_F => Ok(KeyCode::KeyF), - PROCESSING_KEY_G => Ok(KeyCode::KeyG), - PROCESSING_KEY_H => Ok(KeyCode::KeyH), - PROCESSING_KEY_I => Ok(KeyCode::KeyI), - PROCESSING_KEY_J => Ok(KeyCode::KeyJ), - PROCESSING_KEY_K => Ok(KeyCode::KeyK), - PROCESSING_KEY_L => Ok(KeyCode::KeyL), - PROCESSING_KEY_M => Ok(KeyCode::KeyM), - PROCESSING_KEY_N => Ok(KeyCode::KeyN), - PROCESSING_KEY_O => Ok(KeyCode::KeyO), - PROCESSING_KEY_P => Ok(KeyCode::KeyP), - PROCESSING_KEY_Q => Ok(KeyCode::KeyQ), - PROCESSING_KEY_R => Ok(KeyCode::KeyR), - PROCESSING_KEY_S => Ok(KeyCode::KeyS), - PROCESSING_KEY_T => Ok(KeyCode::KeyT), - PROCESSING_KEY_U => Ok(KeyCode::KeyU), - PROCESSING_KEY_V => Ok(KeyCode::KeyV), - PROCESSING_KEY_W => Ok(KeyCode::KeyW), - PROCESSING_KEY_X => Ok(KeyCode::KeyX), - PROCESSING_KEY_Y => Ok(KeyCode::KeyY), - PROCESSING_KEY_Z => Ok(KeyCode::KeyZ), - PROCESSING_KEY_BRACKET_LEFT => Ok(KeyCode::BracketLeft), - PROCESSING_KEY_BACKSLASH => Ok(KeyCode::Backslash), - PROCESSING_KEY_BRACKET_RIGHT => Ok(KeyCode::BracketRight), - PROCESSING_KEY_BACKQUOTE => Ok(KeyCode::Backquote), - PROCESSING_KEY_ESCAPE => Ok(KeyCode::Escape), - PROCESSING_KEY_ENTER => Ok(KeyCode::Enter), - PROCESSING_KEY_TAB => Ok(KeyCode::Tab), - PROCESSING_KEY_BACKSPACE => Ok(KeyCode::Backspace), - PROCESSING_KEY_INSERT => Ok(KeyCode::Insert), - PROCESSING_KEY_DELETE => Ok(KeyCode::Delete), - PROCESSING_KEY_RIGHT => Ok(KeyCode::ArrowRight), - PROCESSING_KEY_LEFT => Ok(KeyCode::ArrowLeft), - PROCESSING_KEY_DOWN => Ok(KeyCode::ArrowDown), - PROCESSING_KEY_UP => Ok(KeyCode::ArrowUp), - PROCESSING_KEY_PAGE_UP => Ok(KeyCode::PageUp), - PROCESSING_KEY_PAGE_DOWN => Ok(KeyCode::PageDown), - PROCESSING_KEY_HOME => Ok(KeyCode::Home), - PROCESSING_KEY_END => Ok(KeyCode::End), - PROCESSING_KEY_CAPS_LOCK => Ok(KeyCode::CapsLock), - PROCESSING_KEY_SCROLL_LOCK => Ok(KeyCode::ScrollLock), - PROCESSING_KEY_NUM_LOCK => Ok(KeyCode::NumLock), - PROCESSING_KEY_PRINT_SCREEN => Ok(KeyCode::PrintScreen), - PROCESSING_KEY_PAUSE => Ok(KeyCode::Pause), - PROCESSING_KEY_F1 => Ok(KeyCode::F1), - PROCESSING_KEY_F2 => Ok(KeyCode::F2), - PROCESSING_KEY_F3 => Ok(KeyCode::F3), - PROCESSING_KEY_F4 => Ok(KeyCode::F4), - PROCESSING_KEY_F5 => Ok(KeyCode::F5), - PROCESSING_KEY_F6 => Ok(KeyCode::F6), - PROCESSING_KEY_F7 => Ok(KeyCode::F7), - PROCESSING_KEY_F8 => Ok(KeyCode::F8), - PROCESSING_KEY_F9 => Ok(KeyCode::F9), - PROCESSING_KEY_F10 => Ok(KeyCode::F10), - PROCESSING_KEY_F11 => Ok(KeyCode::F11), - PROCESSING_KEY_F12 => Ok(KeyCode::F12), - PROCESSING_KEY_NUMPAD_0 => Ok(KeyCode::Numpad0), - PROCESSING_KEY_NUMPAD_1 => Ok(KeyCode::Numpad1), - PROCESSING_KEY_NUMPAD_2 => Ok(KeyCode::Numpad2), - PROCESSING_KEY_NUMPAD_3 => Ok(KeyCode::Numpad3), - PROCESSING_KEY_NUMPAD_4 => Ok(KeyCode::Numpad4), - PROCESSING_KEY_NUMPAD_5 => Ok(KeyCode::Numpad5), - PROCESSING_KEY_NUMPAD_6 => Ok(KeyCode::Numpad6), - PROCESSING_KEY_NUMPAD_7 => Ok(KeyCode::Numpad7), - PROCESSING_KEY_NUMPAD_8 => Ok(KeyCode::Numpad8), - PROCESSING_KEY_NUMPAD_9 => Ok(KeyCode::Numpad9), - PROCESSING_KEY_NUMPAD_DECIMAL => Ok(KeyCode::NumpadDecimal), - PROCESSING_KEY_NUMPAD_DIVIDE => Ok(KeyCode::NumpadDivide), - PROCESSING_KEY_NUMPAD_MULTIPLY => Ok(KeyCode::NumpadMultiply), - PROCESSING_KEY_NUMPAD_SUBTRACT => Ok(KeyCode::NumpadSubtract), - PROCESSING_KEY_NUMPAD_ADD => Ok(KeyCode::NumpadAdd), - PROCESSING_KEY_NUMPAD_ENTER => Ok(KeyCode::NumpadEnter), - PROCESSING_KEY_NUMPAD_EQUAL => Ok(KeyCode::NumpadEqual), - PROCESSING_KEY_SHIFT_LEFT => Ok(KeyCode::ShiftLeft), - PROCESSING_KEY_CONTROL_LEFT => Ok(KeyCode::ControlLeft), - PROCESSING_KEY_ALT_LEFT => Ok(KeyCode::AltLeft), - PROCESSING_KEY_SUPER_LEFT => Ok(KeyCode::SuperLeft), - PROCESSING_KEY_SHIFT_RIGHT => Ok(KeyCode::ShiftRight), - PROCESSING_KEY_CONTROL_RIGHT => Ok(KeyCode::ControlRight), - PROCESSING_KEY_ALT_RIGHT => Ok(KeyCode::AltRight), - PROCESSING_KEY_SUPER_RIGHT => Ok(KeyCode::SuperRight), - PROCESSING_KEY_CONTEXT_MENU => Ok(KeyCode::ContextMenu), - _ => Err(ProcessingError::InvalidArgument(format!( - "unknown key code: {val}" - ))), - } -} - -fn key_code_to_u32(kc: KeyCode) -> u32 { - match kc { - KeyCode::Space => PROCESSING_KEY_SPACE, - KeyCode::Quote => PROCESSING_KEY_QUOTE, - KeyCode::Comma => PROCESSING_KEY_COMMA, - KeyCode::Minus => PROCESSING_KEY_MINUS, - KeyCode::Period => PROCESSING_KEY_PERIOD, - KeyCode::Slash => PROCESSING_KEY_SLASH, - KeyCode::Digit0 => PROCESSING_KEY_0, - KeyCode::Digit1 => PROCESSING_KEY_1, - KeyCode::Digit2 => PROCESSING_KEY_2, - KeyCode::Digit3 => PROCESSING_KEY_3, - KeyCode::Digit4 => PROCESSING_KEY_4, - KeyCode::Digit5 => PROCESSING_KEY_5, - KeyCode::Digit6 => PROCESSING_KEY_6, - KeyCode::Digit7 => PROCESSING_KEY_7, - KeyCode::Digit8 => PROCESSING_KEY_8, - KeyCode::Digit9 => PROCESSING_KEY_9, - KeyCode::Semicolon => PROCESSING_KEY_SEMICOLON, - KeyCode::Equal => PROCESSING_KEY_EQUAL, - KeyCode::KeyA => PROCESSING_KEY_A, - KeyCode::KeyB => PROCESSING_KEY_B, - KeyCode::KeyC => PROCESSING_KEY_C, - KeyCode::KeyD => PROCESSING_KEY_D, - KeyCode::KeyE => PROCESSING_KEY_E, - KeyCode::KeyF => PROCESSING_KEY_F, - KeyCode::KeyG => PROCESSING_KEY_G, - KeyCode::KeyH => PROCESSING_KEY_H, - KeyCode::KeyI => PROCESSING_KEY_I, - KeyCode::KeyJ => PROCESSING_KEY_J, - KeyCode::KeyK => PROCESSING_KEY_K, - KeyCode::KeyL => PROCESSING_KEY_L, - KeyCode::KeyM => PROCESSING_KEY_M, - KeyCode::KeyN => PROCESSING_KEY_N, - KeyCode::KeyO => PROCESSING_KEY_O, - KeyCode::KeyP => PROCESSING_KEY_P, - KeyCode::KeyQ => PROCESSING_KEY_Q, - KeyCode::KeyR => PROCESSING_KEY_R, - KeyCode::KeyS => PROCESSING_KEY_S, - KeyCode::KeyT => PROCESSING_KEY_T, - KeyCode::KeyU => PROCESSING_KEY_U, - KeyCode::KeyV => PROCESSING_KEY_V, - KeyCode::KeyW => PROCESSING_KEY_W, - KeyCode::KeyX => PROCESSING_KEY_X, - KeyCode::KeyY => PROCESSING_KEY_Y, - KeyCode::KeyZ => PROCESSING_KEY_Z, - KeyCode::BracketLeft => PROCESSING_KEY_BRACKET_LEFT, - KeyCode::Backslash => PROCESSING_KEY_BACKSLASH, - KeyCode::BracketRight => PROCESSING_KEY_BRACKET_RIGHT, - KeyCode::Backquote => PROCESSING_KEY_BACKQUOTE, - KeyCode::Escape => PROCESSING_KEY_ESCAPE, - KeyCode::Enter => PROCESSING_KEY_ENTER, - KeyCode::Tab => PROCESSING_KEY_TAB, - KeyCode::Backspace => PROCESSING_KEY_BACKSPACE, - KeyCode::Insert => PROCESSING_KEY_INSERT, - KeyCode::Delete => PROCESSING_KEY_DELETE, - KeyCode::ArrowRight => PROCESSING_KEY_RIGHT, - KeyCode::ArrowLeft => PROCESSING_KEY_LEFT, - KeyCode::ArrowDown => PROCESSING_KEY_DOWN, - KeyCode::ArrowUp => PROCESSING_KEY_UP, - KeyCode::PageUp => PROCESSING_KEY_PAGE_UP, - KeyCode::PageDown => PROCESSING_KEY_PAGE_DOWN, - KeyCode::Home => PROCESSING_KEY_HOME, - KeyCode::End => PROCESSING_KEY_END, - KeyCode::CapsLock => PROCESSING_KEY_CAPS_LOCK, - KeyCode::ScrollLock => PROCESSING_KEY_SCROLL_LOCK, - KeyCode::NumLock => PROCESSING_KEY_NUM_LOCK, - KeyCode::PrintScreen => PROCESSING_KEY_PRINT_SCREEN, - KeyCode::Pause => PROCESSING_KEY_PAUSE, - KeyCode::F1 => PROCESSING_KEY_F1, - KeyCode::F2 => PROCESSING_KEY_F2, - KeyCode::F3 => PROCESSING_KEY_F3, - KeyCode::F4 => PROCESSING_KEY_F4, - KeyCode::F5 => PROCESSING_KEY_F5, - KeyCode::F6 => PROCESSING_KEY_F6, - KeyCode::F7 => PROCESSING_KEY_F7, - KeyCode::F8 => PROCESSING_KEY_F8, - KeyCode::F9 => PROCESSING_KEY_F9, - KeyCode::F10 => PROCESSING_KEY_F10, - KeyCode::F11 => PROCESSING_KEY_F11, - KeyCode::F12 => PROCESSING_KEY_F12, - KeyCode::Numpad0 => PROCESSING_KEY_NUMPAD_0, - KeyCode::Numpad1 => PROCESSING_KEY_NUMPAD_1, - KeyCode::Numpad2 => PROCESSING_KEY_NUMPAD_2, - KeyCode::Numpad3 => PROCESSING_KEY_NUMPAD_3, - KeyCode::Numpad4 => PROCESSING_KEY_NUMPAD_4, - KeyCode::Numpad5 => PROCESSING_KEY_NUMPAD_5, - KeyCode::Numpad6 => PROCESSING_KEY_NUMPAD_6, - KeyCode::Numpad7 => PROCESSING_KEY_NUMPAD_7, - KeyCode::Numpad8 => PROCESSING_KEY_NUMPAD_8, - KeyCode::Numpad9 => PROCESSING_KEY_NUMPAD_9, - KeyCode::NumpadDecimal => PROCESSING_KEY_NUMPAD_DECIMAL, - KeyCode::NumpadDivide => PROCESSING_KEY_NUMPAD_DIVIDE, - KeyCode::NumpadMultiply => PROCESSING_KEY_NUMPAD_MULTIPLY, - KeyCode::NumpadSubtract => PROCESSING_KEY_NUMPAD_SUBTRACT, - KeyCode::NumpadAdd => PROCESSING_KEY_NUMPAD_ADD, - KeyCode::NumpadEnter => PROCESSING_KEY_NUMPAD_ENTER, - KeyCode::NumpadEqual => PROCESSING_KEY_NUMPAD_EQUAL, - KeyCode::ShiftLeft => PROCESSING_KEY_SHIFT_LEFT, - KeyCode::ControlLeft => PROCESSING_KEY_CONTROL_LEFT, - KeyCode::AltLeft => PROCESSING_KEY_ALT_LEFT, - KeyCode::SuperLeft => PROCESSING_KEY_SUPER_LEFT, - KeyCode::ShiftRight => PROCESSING_KEY_SHIFT_RIGHT, - KeyCode::ControlRight => PROCESSING_KEY_CONTROL_RIGHT, - KeyCode::AltRight => PROCESSING_KEY_ALT_RIGHT, - KeyCode::SuperRight => PROCESSING_KEY_SUPER_RIGHT, - KeyCode::ContextMenu => PROCESSING_KEY_CONTEXT_MENU, - _ => 0, - } -} diff --git a/crates/processing_input/src/keys.rs b/crates/processing_input/src/keys.rs new file mode 100644 index 00000000..4f6c661d --- /dev/null +++ b/crates/processing_input/src/keys.rs @@ -0,0 +1,145 @@ +//! The numeric key codes front ends expose (GLFW values, see +//! `processing_core::constants`) and their Bevy `KeyCode`s. + +use bevy::input::keyboard::KeyCode; +use processing_core::constants as c; +use processing_core::error::{ProcessingError, Result}; + +macro_rules! key_table { + ($($code:ident => $key:ident),* $(,)?) => { + pub fn key_code_from_u32(code: u32) -> Result { + match code { + $(c::$code => Ok(KeyCode::$key),)* + _ => Err(ProcessingError::InvalidArgument(format!("unknown key code: {code}"))), + } + } + + pub fn key_code_to_u32(key: KeyCode) -> Option { + match key { + $(KeyCode::$key => Some(c::$code),)* + _ => None, + } + } + }; +} + +key_table! { + KEY_A => KeyA, + KEY_B => KeyB, + KEY_C => KeyC, + KEY_D => KeyD, + KEY_E => KeyE, + KEY_F => KeyF, + KEY_G => KeyG, + KEY_H => KeyH, + KEY_I => KeyI, + KEY_J => KeyJ, + KEY_K => KeyK, + KEY_L => KeyL, + KEY_M => KeyM, + KEY_N => KeyN, + KEY_O => KeyO, + KEY_P => KeyP, + KEY_Q => KeyQ, + KEY_R => KeyR, + KEY_S => KeyS, + KEY_T => KeyT, + KEY_U => KeyU, + KEY_V => KeyV, + KEY_W => KeyW, + KEY_X => KeyX, + KEY_Y => KeyY, + KEY_Z => KeyZ, + KEY_0 => Digit0, + KEY_1 => Digit1, + KEY_2 => Digit2, + KEY_3 => Digit3, + KEY_4 => Digit4, + KEY_5 => Digit5, + KEY_6 => Digit6, + KEY_7 => Digit7, + KEY_8 => Digit8, + KEY_9 => Digit9, + SPACE => Space, + QUOTE => Quote, + COMMA => Comma, + MINUS => Minus, + PERIOD => Period, + SLASH => Slash, + SEMICOLON => Semicolon, + EQUAL => Equal, + BRACKET_LEFT => BracketLeft, + BACKSLASH => Backslash, + BRACKET_RIGHT => BracketRight, + BACKQUOTE => Backquote, + ESCAPE => Escape, + ENTER => Enter, + TAB => Tab, + BACKSPACE => Backspace, + INSERT => Insert, + DELETE => Delete, + RIGHT_ARROW => ArrowRight, + LEFT_ARROW => ArrowLeft, + DOWN => ArrowDown, + UP => ArrowUp, + PAGE_UP => PageUp, + PAGE_DOWN => PageDown, + HOME => Home, + END => End, + CAPS_LOCK => CapsLock, + SCROLL_LOCK => ScrollLock, + NUM_LOCK => NumLock, + PRINT_SCREEN => PrintScreen, + PAUSE => Pause, + F1 => F1, + F2 => F2, + F3 => F3, + F4 => F4, + F5 => F5, + F6 => F6, + F7 => F7, + F8 => F8, + F9 => F9, + F10 => F10, + F11 => F11, + F12 => F12, + F13 => F13, + F14 => F14, + F15 => F15, + F16 => F16, + F17 => F17, + F18 => F18, + F19 => F19, + F20 => F20, + F21 => F21, + F22 => F22, + F23 => F23, + F24 => F24, + F25 => F25, + NUMPAD_0 => Numpad0, + NUMPAD_1 => Numpad1, + NUMPAD_2 => Numpad2, + NUMPAD_3 => Numpad3, + NUMPAD_4 => Numpad4, + NUMPAD_5 => Numpad5, + NUMPAD_6 => Numpad6, + NUMPAD_7 => Numpad7, + NUMPAD_8 => Numpad8, + NUMPAD_9 => Numpad9, + NUMPAD_DECIMAL => NumpadDecimal, + NUMPAD_DIVIDE => NumpadDivide, + NUMPAD_MULTIPLY => NumpadMultiply, + NUMPAD_SUBTRACT => NumpadSubtract, + NUMPAD_ADD => NumpadAdd, + NUMPAD_ENTER => NumpadEnter, + NUMPAD_EQUAL => NumpadEqual, + SHIFT => ShiftLeft, + CONTROL => ControlLeft, + ALT => AltLeft, + SUPER => SuperLeft, + SHIFT_RIGHT => ShiftRight, + CONTROL_RIGHT => ControlRight, + ALT_RIGHT => AltRight, + SUPER_RIGHT => SuperRight, + CONTEXT_MENU => ContextMenu, +} diff --git a/crates/processing_input/src/lib.rs b/crates/processing_input/src/lib.rs index 118a295f..5c758f33 100644 --- a/crates/processing_input/src/lib.rs +++ b/crates/processing_input/src/lib.rs @@ -1,3 +1,4 @@ +pub mod keys; pub mod state; use bevy::input::ButtonState; @@ -14,6 +15,7 @@ use bevy::window::{CursorMoved, WindowResized}; use processing_core::app_mut; use processing_core::error; +pub use keys::{key_code_from_u32, key_code_to_u32}; pub use state::{CursorPosition, LastKey, LastMouseButton}; pub struct InputPlugin; diff --git a/crates/processing_pyo3/processing_py/__init__.py b/crates/processing_pyo3/processing_py/__init__.py index e7735aec..aac23965 100644 --- a/crates/processing_pyo3/processing_py/__init__.py +++ b/crates/processing_pyo3/processing_py/__init__.py @@ -27,7 +27,6 @@ "width", "height", "focused", - "pixel_density", "pixel_width", "pixel_height", "mouse_x", @@ -36,12 +35,13 @@ "pmouse_y", "mouse_is_pressed", "mouse_button", - "mouse_wheel", "moved_x", "moved_y", "key", "key_code", "key_is_pressed", + "window_x", + "window_y", ) _DYNAMIC_TIME_ATTRS = ( @@ -54,7 +54,6 @@ "width": 100, "height": 100, "focused": False, - "pixel_density": 1.0, "pixel_width": 100, "pixel_height": 100, "mouse_x": 0.0, @@ -63,18 +62,19 @@ "pmouse_y": 0.0, "mouse_is_pressed": False, "mouse_button": None, - "mouse_wheel": 0.0, "moved_x": 0.0, "moved_y": 0.0, "key": None, "key_code": None, "key_is_pressed": False, + "window_x": 0, + "window_y": 0, } _DYNAMIC = ( _DYNAMIC_GRAPHICS_ATTRS + _DYNAMIC_TIME_ATTRS - + ("display_width", "display_height", "window_x", "window_y") + + ("display_width", "display_height") ) @@ -104,16 +104,6 @@ def __getattr__(name): if mon is None: return 0 return mon.width if name == "display_width" else mon.height - if name in ("window_x", "window_y"): - g = _get_graphics() - if g is None: - return 0 - # offscreen canvases (notebooks, embedding hosts) have no window position - try: - x, y = g.surface.position - except (AttributeError, RuntimeError): - return 0 - return x if name == "window_x" else y raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/crates/processing_pyo3/src/constants.rs b/crates/processing_pyo3/src/constants.rs index 99486f82..5a5673ce 100644 --- a/crates/processing_pyo3/src/constants.rs +++ b/crates/processing_pyo3/src/constants.rs @@ -135,8 +135,41 @@ pub fn register(m: &Bound<'_, PyModule>) -> PyResult<()> { HOME, END ); + add!( + m, + CAPS_LOCK, + SCROLL_LOCK, + NUM_LOCK, + PRINT_SCREEN, + PAUSE, + CONTEXT_MENU + ); add!(m, SHIFT, CONTROL, ALT, SUPER); - add!(m, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12); + add!(m, SHIFT_RIGHT, CONTROL_RIGHT, ALT_RIGHT, SUPER_RIGHT); + add!( + m, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, + F20, F21, F22, F23, F24, F25 + ); + add!( + m, + NUMPAD_0, + NUMPAD_1, + NUMPAD_2, + NUMPAD_3, + NUMPAD_4, + NUMPAD_5, + NUMPAD_6, + NUMPAD_7, + NUMPAD_8, + NUMPAD_9, + NUMPAD_DECIMAL, + NUMPAD_DIVIDE, + NUMPAD_MULTIPLY, + NUMPAD_SUBTRACT, + NUMPAD_ADD, + NUMPAD_ENTER, + NUMPAD_EQUAL + ); // Objects rather than strings, passed straight to blend_mode(). m.add("BLEND", PyBlendMode::from_preset(BlendMode::Blend))?; diff --git a/crates/processing_pyo3/src/graphics.rs b/crates/processing_pyo3/src/graphics.rs index d3b16919..ca1265c8 100644 --- a/crates/processing_pyo3/src/graphics.rs +++ b/crates/processing_pyo3/src/graphics.rs @@ -1005,6 +1005,17 @@ impl Graphics { self.surface.pixel_width() } + /// 0 for offscreen canvases, which have no window. + #[getter] + pub fn window_x(&self) -> i32 { + self.surface.position().map_or(0, |(x, _)| x) + } + + #[getter] + pub fn window_y(&self) -> i32 { + self.surface.position().map_or(0, |(_, y)| y) + } + #[getter] pub fn pixel_height(&self) -> PyResult { self.surface.pixel_height() @@ -2738,11 +2749,6 @@ impl Graphics { input::moved_y() } - #[getter] - fn mouse_wheel(&self) -> PyResult { - input::mouse_wheel() - } - #[getter] fn key(&self) -> PyResult> { input::key() diff --git a/crates/processing_pyo3/src/input.rs b/crates/processing_pyo3/src/input.rs index 1126d3fb..8c811a99 100644 --- a/crates/processing_pyo3/src/input.rs +++ b/crates/processing_pyo3/src/input.rs @@ -64,12 +64,12 @@ pub fn key_is_pressed() -> PyResult { } pub fn key_is_down(key_code: u32) -> PyResult { - let kc = u32_to_key_code(key_code)?; + let kc = key_code_from_u32(key_code).map_err(|e| PyValueError::new_err(format!("{e}")))?; processing::prelude::input_key_is_down(kc).map_err(|e| PyRuntimeError::new_err(format!("{e}"))) } pub fn key_just_pressed(key_code: u32) -> PyResult { - let kc = u32_to_key_code(key_code)?; + let kc = key_code_from_u32(key_code).map_err(|e| PyValueError::new_err(format!("{e}")))?; processing::prelude::input_key_just_pressed(kc) .map_err(|e| PyRuntimeError::new_err(format!("{e}"))) } @@ -82,7 +82,7 @@ pub fn key() -> PyResult> { pub fn key_code() -> PyResult> { processing::prelude::input_key_code() - .map(|opt| opt.map(key_code_to_u32)) + .map(|opt| opt.and_then(key_code_to_u32)) .map_err(|e| PyRuntimeError::new_err(format!("{e}"))) } @@ -101,129 +101,62 @@ pub fn sync_globals( set_tracked(globals, "mouse_button", mouse_button()?)?; set_tracked(globals, "moved_x", moved_x()?)?; set_tracked(globals, "moved_y", moved_y()?)?; - set_tracked(globals, "mouse_wheel", mouse_wheel()?)?; set_tracked(globals, "key", key()?)?; set_tracked(globals, "key_code", key_code()?)?; set_tracked(globals, "key_is_pressed", key_is_pressed()?)?; Ok(()) } -fn u32_to_key_code(val: u32) -> PyResult { - use bevy::input::keyboard::KeyCode; - match val { - 32 => Ok(KeyCode::Space), - 256 => Ok(KeyCode::Escape), - 257 => Ok(KeyCode::Enter), - 258 => Ok(KeyCode::Tab), - 259 => Ok(KeyCode::Backspace), - 261 => Ok(KeyCode::Delete), - 262 => Ok(KeyCode::ArrowRight), - 263 => Ok(KeyCode::ArrowLeft), - 264 => Ok(KeyCode::ArrowDown), - 265 => Ok(KeyCode::ArrowUp), - 340 => Ok(KeyCode::ShiftLeft), - 341 => Ok(KeyCode::ControlLeft), - 342 => Ok(KeyCode::AltLeft), - 343 => Ok(KeyCode::SuperLeft), - 65..=90 => Ok(match val { - 65 => KeyCode::KeyA, - 66 => KeyCode::KeyB, - 67 => KeyCode::KeyC, - 68 => KeyCode::KeyD, - 69 => KeyCode::KeyE, - 70 => KeyCode::KeyF, - 71 => KeyCode::KeyG, - 72 => KeyCode::KeyH, - 73 => KeyCode::KeyI, - 74 => KeyCode::KeyJ, - 75 => KeyCode::KeyK, - 76 => KeyCode::KeyL, - 77 => KeyCode::KeyM, - 78 => KeyCode::KeyN, - 79 => KeyCode::KeyO, - 80 => KeyCode::KeyP, - 81 => KeyCode::KeyQ, - 82 => KeyCode::KeyR, - 83 => KeyCode::KeyS, - 84 => KeyCode::KeyT, - 85 => KeyCode::KeyU, - 86 => KeyCode::KeyV, - 87 => KeyCode::KeyW, - 88 => KeyCode::KeyX, - 89 => KeyCode::KeyY, - 90 => KeyCode::KeyZ, - _ => unreachable!(), - }), - 48..=57 => Ok(match val { - 48 => KeyCode::Digit0, - 49 => KeyCode::Digit1, - 50 => KeyCode::Digit2, - 51 => KeyCode::Digit3, - 52 => KeyCode::Digit4, - 53 => KeyCode::Digit5, - 54 => KeyCode::Digit6, - 55 => KeyCode::Digit7, - 56 => KeyCode::Digit8, - 57 => KeyCode::Digit9, - _ => unreachable!(), - }), - _ => Err(PyValueError::new_err(format!("unknown key code: {val}"))), +/// Passed to mouse callbacks that take a parameter, e.g. `def mouse_wheel(e)`. +#[pyclass(frozen, get_all)] +pub struct MouseEvent { + pub x: f32, + pub y: f32, + pub button: Option, + /// Vertical scroll since the last frame. + pub wheel: f32, +} + +impl MouseEvent { + pub fn current(surface: Entity, width: u32, height: u32) -> PyResult { + Ok(Self { + x: mouse_x(surface, width)?, + y: mouse_y(surface, height)?, + button: mouse_button()?, + wheel: mouse_wheel()?, + }) + } +} + +#[pymethods] +impl MouseEvent { + fn __repr__(&self) -> String { + format!( + "MouseEvent(x={}, y={}, button={:?}, wheel={})", + self.x, self.y, self.button, self.wheel + ) + } +} + +/// Passed to key callbacks that take a parameter, e.g. `def key_pressed(e)`. +#[pyclass(frozen, get_all)] +pub struct KeyEvent { + pub key: Option, + pub key_code: Option, +} + +impl KeyEvent { + pub fn current() -> PyResult { + Ok(Self { + key: key()?, + key_code: key_code()?, + }) } } -fn key_code_to_u32(kc: bevy::input::keyboard::KeyCode) -> u32 { - use bevy::input::keyboard::KeyCode; - match kc { - KeyCode::Space => 32, - KeyCode::Escape => 256, - KeyCode::Enter => 257, - KeyCode::Tab => 258, - KeyCode::Backspace => 259, - KeyCode::Delete => 261, - KeyCode::ArrowRight => 262, - KeyCode::ArrowLeft => 263, - KeyCode::ArrowDown => 264, - KeyCode::ArrowUp => 265, - KeyCode::ShiftLeft => 340, - KeyCode::ControlLeft => 341, - KeyCode::AltLeft => 342, - KeyCode::SuperLeft => 343, - KeyCode::KeyA => 65, - KeyCode::KeyB => 66, - KeyCode::KeyC => 67, - KeyCode::KeyD => 68, - KeyCode::KeyE => 69, - KeyCode::KeyF => 70, - KeyCode::KeyG => 71, - KeyCode::KeyH => 72, - KeyCode::KeyI => 73, - KeyCode::KeyJ => 74, - KeyCode::KeyK => 75, - KeyCode::KeyL => 76, - KeyCode::KeyM => 77, - KeyCode::KeyN => 78, - KeyCode::KeyO => 79, - KeyCode::KeyP => 80, - KeyCode::KeyQ => 81, - KeyCode::KeyR => 82, - KeyCode::KeyS => 83, - KeyCode::KeyT => 84, - KeyCode::KeyU => 85, - KeyCode::KeyV => 86, - KeyCode::KeyW => 87, - KeyCode::KeyX => 88, - KeyCode::KeyY => 89, - KeyCode::KeyZ => 90, - KeyCode::Digit0 => 48, - KeyCode::Digit1 => 49, - KeyCode::Digit2 => 50, - KeyCode::Digit3 => 51, - KeyCode::Digit4 => 52, - KeyCode::Digit5 => 53, - KeyCode::Digit6 => 54, - KeyCode::Digit7 => 55, - KeyCode::Digit8 => 56, - KeyCode::Digit9 => 57, - _ => 0, +#[pymethods] +impl KeyEvent { + fn __repr__(&self) -> String { + format!("KeyEvent(key={:?}, key_code={:?})", self.key, self.key_code) } } diff --git a/crates/processing_pyo3/src/lib.rs b/crates/processing_pyo3/src/lib.rs index f0235caa..15e0820b 100644 --- a/crates/processing_pyo3/src/lib.rs +++ b/crates/processing_pyo3/src/lib.rs @@ -128,9 +128,18 @@ impl Default for LoopState { } } +/// Input history the derived callbacks need across frames. +#[derive(Clone, Copy, Default)] +pub(crate) struct EventState { + /// Pressed and not dragged since, so the release is a click. + click_pending: bool, + canvas_size: Option<(u32, u32)>, +} + thread_local! { pub(crate) static LAST_GLOBALS: RefCell>> = RefCell::new(HashMap::new()); pub(crate) static LOOP_STATE: Cell = Cell::new(LoopState::default()); + pub(crate) static EVENT_STATE: Cell = Cell::new(EventState::default()); } fn update_loop_state(f: impl FnOnce(&mut LoopState)) { @@ -177,61 +186,132 @@ where Ok(()) } -pub(crate) fn reset_tracked_globals() { - LAST_GLOBALS.with(|cache| cache.borrow_mut().clear()); +fn canvas_size(graphics: &Graphics) -> PyResult<(u32, u32)> { + let err = + |e: processing::prelude::error::ProcessingError| PyRuntimeError::new_err(format!("{e}")); + let width = ::processing::prelude::surface_width(graphics.surface.entity).map_err(err)?; + let height = ::processing::prelude::surface_height(graphics.surface.entity).map_err(err)?; + Ok(( + if width == 0 { graphics.width } else { width }, + if height == 0 { graphics.height } else { height }, + )) } fn sync_globals(module: &Bound<'_, PyModule>, globals: &Bound<'_, PyAny>) -> PyResult<()> { let graphics = get_graphics(module)?.ok_or_else(|| PyRuntimeError::new_err("call size() first"))?; - let width = ::processing::prelude::surface_width(graphics.surface.entity) - .map_err(|e| PyRuntimeError::new_err(format!("{e}")))?; - let width = if width == 0 { graphics.width } else { width }; - let height = ::processing::prelude::surface_height(graphics.surface.entity) - .map_err(|e| PyRuntimeError::new_err(format!("{e}")))?; - let height = if height == 0 { graphics.height } else { height }; + let (width, height) = canvas_size(&graphics)?; input::sync_globals(globals, graphics.surface.entity, width, height)?; surface::sync_globals(globals, &graphics.surface, width, height)?; time::sync_globals(globals)?; Ok(()) } -fn try_call(locals: &Bound<'_, PyAny>, name: &str) -> PyResult<()> { - if let Ok(cb) = locals.get_item(name) - && cb.is_callable() - { - cb.call0() - .map_err(|e| PyRuntimeError::new_err(format!("{e}")))?; +fn mouse_event(module: &Bound<'_, PyModule>) -> PyResult> { + // the graphics borrow has to end before the callback runs, which may draw + let event = { + let graphics = + get_graphics(module)?.ok_or_else(|| PyRuntimeError::new_err("call size() first"))?; + let (width, height) = canvas_size(&graphics)?; + input::MouseEvent::current(graphics.surface.entity, width, height)? + }; + Ok(Py::new(module.py(), event)?.into_any()) +} + +fn key_event(module: &Bound<'_, PyModule>) -> PyResult> { + Ok(Py::new(module.py(), input::KeyEvent::current()?)?.into_any()) +} + +fn no_event(module: &Bound<'_, PyModule>) -> PyResult> { + Ok(module.py().None()) +} + +/// Calls the sketch's `name` callback, with an event if it takes a parameter +/// (`def mouse_pressed(e)`), as py5 and Processing's `mousePressed(MouseEvent)` do. +fn call_event_callback( + module: &Bound<'_, PyModule>, + locals: &Bound<'_, PyAny>, + name: &str, + event: fn(&Bound<'_, PyModule>) -> PyResult>, +) -> PyResult<()> { + let Ok(cb) = locals.get_item(name) else { + return Ok(()); + }; + if !cb.is_callable() { + return Ok(()); + } + let inspect = PyModule::import(module.py(), "inspect")?; + // builtins without a signature can't take our event either + let takes_event = inspect + .call_method1("signature", (&cb,)) + .and_then(|sig| sig.getattr("parameters")?.len()) + .is_ok_and(|n| n > 0); + if takes_event { + cb.call1((event(module)?,))?; + } else { + cb.call0()?; } Ok(()) } -fn dispatch_event_callbacks(locals: &Bound<'_, PyAny>) -> PyResult<()> { +fn dispatch_event_callbacks( + module: &Bound<'_, PyModule>, + locals: &Bound<'_, PyAny>, +) -> PyResult<()> { use processing::prelude::*; let err = |e: processing::prelude::error::ProcessingError| PyRuntimeError::new_err(format!("{e}")); - if input_mouse_any_just_pressed().map_err(err)? { - try_call(locals, "mouse_pressed")?; + let update_events = |f: &dyn Fn(&mut EventState)| { + EVENT_STATE.with(|s| { + let mut state = s.get(); + f(&mut state); + s.set(state); + }) + }; + + let size = { + let graphics = + get_graphics(module)?.ok_or_else(|| PyRuntimeError::new_err("call size() first"))?; + canvas_size(&graphics)? + }; + let previous = EVENT_STATE.with(|s| s.get().canvas_size); + update_events(&|s| s.canvas_size = Some(size)); + if previous.is_some_and(|p| p != size) { + call_event_callback(module, locals, "window_resized", no_event)?; } - if input_mouse_any_just_released().map_err(err)? { - try_call(locals, "mouse_released")?; + + if input_mouse_any_just_pressed().map_err(err)? { + update_events(&|s| s.click_pending = true); + call_event_callback(module, locals, "mouse_pressed", mouse_event)?; } if input_mouse_moved().map_err(err)? { if input_mouse_is_pressed().map_err(err)? { - try_call(locals, "mouse_dragged")?; + update_events(&|s| s.click_pending = false); + call_event_callback(module, locals, "mouse_dragged", mouse_event)?; } else { - try_call(locals, "mouse_moved")?; + call_event_callback(module, locals, "mouse_moved", mouse_event)?; + } + } + if input_mouse_any_just_released().map_err(err)? { + call_event_callback(module, locals, "mouse_released", mouse_event)?; + if EVENT_STATE.with(|s| s.get().click_pending) { + update_events(&|s| s.click_pending = false); + call_event_callback(module, locals, "mouse_clicked", mouse_event)?; } } if input_mouse_scrolled().map_err(err)? { - try_call(locals, "mouse_wheel")?; + call_event_callback(module, locals, "mouse_wheel", mouse_event)?; } if input_key_any_just_pressed().map_err(err)? { - try_call(locals, "key_pressed")?; + call_event_callback(module, locals, "key_pressed", key_event)?; + // Processing's keyTyped: only keys that produce a character + if input_key().map_err(err)?.is_some_and(|c| !c.is_control()) { + call_event_callback(module, locals, "key_typed", key_event)?; + } } if input_key_any_just_released().map_err(err)? { - try_call(locals, "key_released")?; + call_event_callback(module, locals, "key_released", key_event)?; } Ok(()) } @@ -360,21 +440,18 @@ fn get_asset_root() -> PyResult { // in ipython/jupyter argv[0] is weird so we use cwd // todo: what is the correct way to get notebook path if filename.is_empty() || !path.getattr("isfile")?.call1((filename,))?.is_truthy()? { - let cwd = os.getattr("getcwd")?.call0()?.to_string(); - let asset_root = path.getattr("join")?.call1((cwd, "assets"))?.to_string(); - return Ok(asset_root); + return Ok(os.getattr("getcwd")?.call0()?.to_string()); } let dirname = path.getattr("dirname")?.call1((filename,))?; - let abspath = path.getattr("abspath")?.call1((dirname,))?; - let asset_root = path - .getattr("join")? - .call1((abspath, "assets"))? - .to_string(); - Ok(asset_root) + Ok(path.getattr("abspath")?.call1((dirname,))?.to_string()) }) } +pub(crate) fn reset_tracked_globals() { + LAST_GLOBALS.with(|cache| cache.borrow_mut().clear()); +} + fn get_sketch_info() -> PyResult<(String, String)> { Python::attach(|py| { let sys = PyModule::import(py, "sys")?; @@ -471,6 +548,10 @@ pub mod processing_py { #[pymodule_export] use super::cuda::CudaImage; #[pymodule_export] + use super::input::KeyEvent; + #[pymodule_export] + use super::input::MouseEvent; + #[pymodule_export] use super::math::PyQuat; #[pymodule_export] use super::math::PyVec2; @@ -693,7 +774,7 @@ pub mod processing_py { return Ok(()); } sync_globals(module, ns)?; - dispatch_event_callbacks(ns)?; + dispatch_event_callbacks(module, ns)?; Ok(()) } @@ -1106,7 +1187,7 @@ pub mod processing_py { break; } } - dispatch_event_callbacks(&locals)?; + dispatch_event_callbacks(module, &locals)?; std::thread::sleep(std::time::Duration::from_millis(16)); } @@ -1148,7 +1229,7 @@ pub mod processing_py { } } - dispatch_event_callbacks(&locals)?; + dispatch_event_callbacks(module, &locals)?; let should_draw = first_frame || LOOP_STATE.with(|s| { diff --git a/crates/processing_pyo3/src/surface.rs b/crates/processing_pyo3/src/surface.rs index 6aa70901..72828f58 100644 --- a/crates/processing_pyo3/src/surface.rs +++ b/crates/processing_pyo3/src/surface.rs @@ -187,7 +187,6 @@ pub fn sync_globals( set_tracked(globals, "width", canvas_width)?; set_tracked(globals, "height", canvas_height)?; set_tracked(globals, "focused", surface.focused()?)?; - set_tracked(globals, "pixel_density", surface.pixel_density()?)?; set_tracked(globals, "pixel_width", surface.pixel_width()?)?; set_tracked(globals, "pixel_height", surface.pixel_height()?)?; diff --git a/crates/processing_wasm/src/lib.rs b/crates/processing_wasm/src/lib.rs index 3153b783..260f005a 100644 --- a/crates/processing_wasm/src/lib.rs +++ b/crates/processing_wasm/src/lib.rs @@ -1885,6 +1885,19 @@ pub const PROCESSING_KEY_F9: u32 = 298; pub const PROCESSING_KEY_F10: u32 = 299; pub const PROCESSING_KEY_F11: u32 = 300; pub const PROCESSING_KEY_F12: u32 = 301; +pub const PROCESSING_KEY_F13: u32 = 302; +pub const PROCESSING_KEY_F14: u32 = 303; +pub const PROCESSING_KEY_F15: u32 = 304; +pub const PROCESSING_KEY_F16: u32 = 305; +pub const PROCESSING_KEY_F17: u32 = 306; +pub const PROCESSING_KEY_F18: u32 = 307; +pub const PROCESSING_KEY_F19: u32 = 308; +pub const PROCESSING_KEY_F20: u32 = 309; +pub const PROCESSING_KEY_F21: u32 = 310; +pub const PROCESSING_KEY_F22: u32 = 311; +pub const PROCESSING_KEY_F23: u32 = 312; +pub const PROCESSING_KEY_F24: u32 = 313; +pub const PROCESSING_KEY_F25: u32 = 314; pub const PROCESSING_KEY_NUMPAD_0: u32 = 320; pub const PROCESSING_KEY_NUMPAD_1: u32 = 321; pub const PROCESSING_KEY_NUMPAD_2: u32 = 322; @@ -2041,7 +2054,7 @@ pub fn js_key() -> Result { #[wasm_bindgen(js_name = "keyCode")] pub fn js_key_code() -> Result { - check(input_key_code().map(|opt| opt.map(key_code_to_u32).unwrap_or(0))) + check(input_key_code().map(|opt| opt.and_then(key_code_to_u32).unwrap_or(0))) } #[wasm_bindgen(js_name = "movedX")] @@ -2059,230 +2072,6 @@ pub fn js_mouse_wheel() -> Result { check(input_mouse_wheel()) } -fn key_code_from_u32(val: u32) -> processing::prelude::error::Result { - match val { - PROCESSING_KEY_SPACE => Ok(KeyCode::Space), - PROCESSING_KEY_QUOTE => Ok(KeyCode::Quote), - PROCESSING_KEY_COMMA => Ok(KeyCode::Comma), - PROCESSING_KEY_MINUS => Ok(KeyCode::Minus), - PROCESSING_KEY_PERIOD => Ok(KeyCode::Period), - PROCESSING_KEY_SLASH => Ok(KeyCode::Slash), - PROCESSING_KEY_0 => Ok(KeyCode::Digit0), - PROCESSING_KEY_1 => Ok(KeyCode::Digit1), - PROCESSING_KEY_2 => Ok(KeyCode::Digit2), - PROCESSING_KEY_3 => Ok(KeyCode::Digit3), - PROCESSING_KEY_4 => Ok(KeyCode::Digit4), - PROCESSING_KEY_5 => Ok(KeyCode::Digit5), - PROCESSING_KEY_6 => Ok(KeyCode::Digit6), - PROCESSING_KEY_7 => Ok(KeyCode::Digit7), - PROCESSING_KEY_8 => Ok(KeyCode::Digit8), - PROCESSING_KEY_9 => Ok(KeyCode::Digit9), - PROCESSING_KEY_SEMICOLON => Ok(KeyCode::Semicolon), - PROCESSING_KEY_EQUAL => Ok(KeyCode::Equal), - PROCESSING_KEY_A => Ok(KeyCode::KeyA), - PROCESSING_KEY_B => Ok(KeyCode::KeyB), - PROCESSING_KEY_C => Ok(KeyCode::KeyC), - PROCESSING_KEY_D => Ok(KeyCode::KeyD), - PROCESSING_KEY_E => Ok(KeyCode::KeyE), - PROCESSING_KEY_F => Ok(KeyCode::KeyF), - PROCESSING_KEY_G => Ok(KeyCode::KeyG), - PROCESSING_KEY_H => Ok(KeyCode::KeyH), - PROCESSING_KEY_I => Ok(KeyCode::KeyI), - PROCESSING_KEY_J => Ok(KeyCode::KeyJ), - PROCESSING_KEY_K => Ok(KeyCode::KeyK), - PROCESSING_KEY_L => Ok(KeyCode::KeyL), - PROCESSING_KEY_M => Ok(KeyCode::KeyM), - PROCESSING_KEY_N => Ok(KeyCode::KeyN), - PROCESSING_KEY_O => Ok(KeyCode::KeyO), - PROCESSING_KEY_P => Ok(KeyCode::KeyP), - PROCESSING_KEY_Q => Ok(KeyCode::KeyQ), - PROCESSING_KEY_R => Ok(KeyCode::KeyR), - PROCESSING_KEY_S => Ok(KeyCode::KeyS), - PROCESSING_KEY_T => Ok(KeyCode::KeyT), - PROCESSING_KEY_U => Ok(KeyCode::KeyU), - PROCESSING_KEY_V => Ok(KeyCode::KeyV), - PROCESSING_KEY_W => Ok(KeyCode::KeyW), - PROCESSING_KEY_X => Ok(KeyCode::KeyX), - PROCESSING_KEY_Y => Ok(KeyCode::KeyY), - PROCESSING_KEY_Z => Ok(KeyCode::KeyZ), - PROCESSING_KEY_BRACKET_LEFT => Ok(KeyCode::BracketLeft), - PROCESSING_KEY_BACKSLASH => Ok(KeyCode::Backslash), - PROCESSING_KEY_BRACKET_RIGHT => Ok(KeyCode::BracketRight), - PROCESSING_KEY_BACKQUOTE => Ok(KeyCode::Backquote), - PROCESSING_KEY_ESCAPE => Ok(KeyCode::Escape), - PROCESSING_KEY_ENTER => Ok(KeyCode::Enter), - PROCESSING_KEY_TAB => Ok(KeyCode::Tab), - PROCESSING_KEY_BACKSPACE => Ok(KeyCode::Backspace), - PROCESSING_KEY_INSERT => Ok(KeyCode::Insert), - PROCESSING_KEY_DELETE => Ok(KeyCode::Delete), - PROCESSING_KEY_RIGHT => Ok(KeyCode::ArrowRight), - PROCESSING_KEY_LEFT => Ok(KeyCode::ArrowLeft), - PROCESSING_KEY_DOWN => Ok(KeyCode::ArrowDown), - PROCESSING_KEY_UP => Ok(KeyCode::ArrowUp), - PROCESSING_KEY_PAGE_UP => Ok(KeyCode::PageUp), - PROCESSING_KEY_PAGE_DOWN => Ok(KeyCode::PageDown), - PROCESSING_KEY_HOME => Ok(KeyCode::Home), - PROCESSING_KEY_END => Ok(KeyCode::End), - PROCESSING_KEY_CAPS_LOCK => Ok(KeyCode::CapsLock), - PROCESSING_KEY_SCROLL_LOCK => Ok(KeyCode::ScrollLock), - PROCESSING_KEY_NUM_LOCK => Ok(KeyCode::NumLock), - PROCESSING_KEY_PRINT_SCREEN => Ok(KeyCode::PrintScreen), - PROCESSING_KEY_PAUSE => Ok(KeyCode::Pause), - PROCESSING_KEY_F1 => Ok(KeyCode::F1), - PROCESSING_KEY_F2 => Ok(KeyCode::F2), - PROCESSING_KEY_F3 => Ok(KeyCode::F3), - PROCESSING_KEY_F4 => Ok(KeyCode::F4), - PROCESSING_KEY_F5 => Ok(KeyCode::F5), - PROCESSING_KEY_F6 => Ok(KeyCode::F6), - PROCESSING_KEY_F7 => Ok(KeyCode::F7), - PROCESSING_KEY_F8 => Ok(KeyCode::F8), - PROCESSING_KEY_F9 => Ok(KeyCode::F9), - PROCESSING_KEY_F10 => Ok(KeyCode::F10), - PROCESSING_KEY_F11 => Ok(KeyCode::F11), - PROCESSING_KEY_F12 => Ok(KeyCode::F12), - PROCESSING_KEY_NUMPAD_0 => Ok(KeyCode::Numpad0), - PROCESSING_KEY_NUMPAD_1 => Ok(KeyCode::Numpad1), - PROCESSING_KEY_NUMPAD_2 => Ok(KeyCode::Numpad2), - PROCESSING_KEY_NUMPAD_3 => Ok(KeyCode::Numpad3), - PROCESSING_KEY_NUMPAD_4 => Ok(KeyCode::Numpad4), - PROCESSING_KEY_NUMPAD_5 => Ok(KeyCode::Numpad5), - PROCESSING_KEY_NUMPAD_6 => Ok(KeyCode::Numpad6), - PROCESSING_KEY_NUMPAD_7 => Ok(KeyCode::Numpad7), - PROCESSING_KEY_NUMPAD_8 => Ok(KeyCode::Numpad8), - PROCESSING_KEY_NUMPAD_9 => Ok(KeyCode::Numpad9), - PROCESSING_KEY_NUMPAD_DECIMAL => Ok(KeyCode::NumpadDecimal), - PROCESSING_KEY_NUMPAD_DIVIDE => Ok(KeyCode::NumpadDivide), - PROCESSING_KEY_NUMPAD_MULTIPLY => Ok(KeyCode::NumpadMultiply), - PROCESSING_KEY_NUMPAD_SUBTRACT => Ok(KeyCode::NumpadSubtract), - PROCESSING_KEY_NUMPAD_ADD => Ok(KeyCode::NumpadAdd), - PROCESSING_KEY_NUMPAD_ENTER => Ok(KeyCode::NumpadEnter), - PROCESSING_KEY_NUMPAD_EQUAL => Ok(KeyCode::NumpadEqual), - PROCESSING_KEY_SHIFT_LEFT => Ok(KeyCode::ShiftLeft), - PROCESSING_KEY_CONTROL_LEFT => Ok(KeyCode::ControlLeft), - PROCESSING_KEY_ALT_LEFT => Ok(KeyCode::AltLeft), - PROCESSING_KEY_SUPER_LEFT => Ok(KeyCode::SuperLeft), - PROCESSING_KEY_SHIFT_RIGHT => Ok(KeyCode::ShiftRight), - PROCESSING_KEY_CONTROL_RIGHT => Ok(KeyCode::ControlRight), - PROCESSING_KEY_ALT_RIGHT => Ok(KeyCode::AltRight), - PROCESSING_KEY_SUPER_RIGHT => Ok(KeyCode::SuperRight), - PROCESSING_KEY_CONTEXT_MENU => Ok(KeyCode::ContextMenu), - _ => Err(ProcessingError::InvalidArgument(format!( - "unknown key code: {val}" - ))), - } -} - -fn key_code_to_u32(kc: KeyCode) -> u32 { - match kc { - KeyCode::Space => PROCESSING_KEY_SPACE, - KeyCode::Quote => PROCESSING_KEY_QUOTE, - KeyCode::Comma => PROCESSING_KEY_COMMA, - KeyCode::Minus => PROCESSING_KEY_MINUS, - KeyCode::Period => PROCESSING_KEY_PERIOD, - KeyCode::Slash => PROCESSING_KEY_SLASH, - KeyCode::Digit0 => PROCESSING_KEY_0, - KeyCode::Digit1 => PROCESSING_KEY_1, - KeyCode::Digit2 => PROCESSING_KEY_2, - KeyCode::Digit3 => PROCESSING_KEY_3, - KeyCode::Digit4 => PROCESSING_KEY_4, - KeyCode::Digit5 => PROCESSING_KEY_5, - KeyCode::Digit6 => PROCESSING_KEY_6, - KeyCode::Digit7 => PROCESSING_KEY_7, - KeyCode::Digit8 => PROCESSING_KEY_8, - KeyCode::Digit9 => PROCESSING_KEY_9, - KeyCode::Semicolon => PROCESSING_KEY_SEMICOLON, - KeyCode::Equal => PROCESSING_KEY_EQUAL, - KeyCode::KeyA => PROCESSING_KEY_A, - KeyCode::KeyB => PROCESSING_KEY_B, - KeyCode::KeyC => PROCESSING_KEY_C, - KeyCode::KeyD => PROCESSING_KEY_D, - KeyCode::KeyE => PROCESSING_KEY_E, - KeyCode::KeyF => PROCESSING_KEY_F, - KeyCode::KeyG => PROCESSING_KEY_G, - KeyCode::KeyH => PROCESSING_KEY_H, - KeyCode::KeyI => PROCESSING_KEY_I, - KeyCode::KeyJ => PROCESSING_KEY_J, - KeyCode::KeyK => PROCESSING_KEY_K, - KeyCode::KeyL => PROCESSING_KEY_L, - KeyCode::KeyM => PROCESSING_KEY_M, - KeyCode::KeyN => PROCESSING_KEY_N, - KeyCode::KeyO => PROCESSING_KEY_O, - KeyCode::KeyP => PROCESSING_KEY_P, - KeyCode::KeyQ => PROCESSING_KEY_Q, - KeyCode::KeyR => PROCESSING_KEY_R, - KeyCode::KeyS => PROCESSING_KEY_S, - KeyCode::KeyT => PROCESSING_KEY_T, - KeyCode::KeyU => PROCESSING_KEY_U, - KeyCode::KeyV => PROCESSING_KEY_V, - KeyCode::KeyW => PROCESSING_KEY_W, - KeyCode::KeyX => PROCESSING_KEY_X, - KeyCode::KeyY => PROCESSING_KEY_Y, - KeyCode::KeyZ => PROCESSING_KEY_Z, - KeyCode::BracketLeft => PROCESSING_KEY_BRACKET_LEFT, - KeyCode::Backslash => PROCESSING_KEY_BACKSLASH, - KeyCode::BracketRight => PROCESSING_KEY_BRACKET_RIGHT, - KeyCode::Backquote => PROCESSING_KEY_BACKQUOTE, - KeyCode::Escape => PROCESSING_KEY_ESCAPE, - KeyCode::Enter => PROCESSING_KEY_ENTER, - KeyCode::Tab => PROCESSING_KEY_TAB, - KeyCode::Backspace => PROCESSING_KEY_BACKSPACE, - KeyCode::Insert => PROCESSING_KEY_INSERT, - KeyCode::Delete => PROCESSING_KEY_DELETE, - KeyCode::ArrowRight => PROCESSING_KEY_RIGHT, - KeyCode::ArrowLeft => PROCESSING_KEY_LEFT, - KeyCode::ArrowDown => PROCESSING_KEY_DOWN, - KeyCode::ArrowUp => PROCESSING_KEY_UP, - KeyCode::PageUp => PROCESSING_KEY_PAGE_UP, - KeyCode::PageDown => PROCESSING_KEY_PAGE_DOWN, - KeyCode::Home => PROCESSING_KEY_HOME, - KeyCode::End => PROCESSING_KEY_END, - KeyCode::CapsLock => PROCESSING_KEY_CAPS_LOCK, - KeyCode::ScrollLock => PROCESSING_KEY_SCROLL_LOCK, - KeyCode::NumLock => PROCESSING_KEY_NUM_LOCK, - KeyCode::PrintScreen => PROCESSING_KEY_PRINT_SCREEN, - KeyCode::Pause => PROCESSING_KEY_PAUSE, - KeyCode::F1 => PROCESSING_KEY_F1, - KeyCode::F2 => PROCESSING_KEY_F2, - KeyCode::F3 => PROCESSING_KEY_F3, - KeyCode::F4 => PROCESSING_KEY_F4, - KeyCode::F5 => PROCESSING_KEY_F5, - KeyCode::F6 => PROCESSING_KEY_F6, - KeyCode::F7 => PROCESSING_KEY_F7, - KeyCode::F8 => PROCESSING_KEY_F8, - KeyCode::F9 => PROCESSING_KEY_F9, - KeyCode::F10 => PROCESSING_KEY_F10, - KeyCode::F11 => PROCESSING_KEY_F11, - KeyCode::F12 => PROCESSING_KEY_F12, - KeyCode::Numpad0 => PROCESSING_KEY_NUMPAD_0, - KeyCode::Numpad1 => PROCESSING_KEY_NUMPAD_1, - KeyCode::Numpad2 => PROCESSING_KEY_NUMPAD_2, - KeyCode::Numpad3 => PROCESSING_KEY_NUMPAD_3, - KeyCode::Numpad4 => PROCESSING_KEY_NUMPAD_4, - KeyCode::Numpad5 => PROCESSING_KEY_NUMPAD_5, - KeyCode::Numpad6 => PROCESSING_KEY_NUMPAD_6, - KeyCode::Numpad7 => PROCESSING_KEY_NUMPAD_7, - KeyCode::Numpad8 => PROCESSING_KEY_NUMPAD_8, - KeyCode::Numpad9 => PROCESSING_KEY_NUMPAD_9, - KeyCode::NumpadDecimal => PROCESSING_KEY_NUMPAD_DECIMAL, - KeyCode::NumpadDivide => PROCESSING_KEY_NUMPAD_DIVIDE, - KeyCode::NumpadMultiply => PROCESSING_KEY_NUMPAD_MULTIPLY, - KeyCode::NumpadSubtract => PROCESSING_KEY_NUMPAD_SUBTRACT, - KeyCode::NumpadAdd => PROCESSING_KEY_NUMPAD_ADD, - KeyCode::NumpadEnter => PROCESSING_KEY_NUMPAD_ENTER, - KeyCode::NumpadEqual => PROCESSING_KEY_NUMPAD_EQUAL, - KeyCode::ShiftLeft => PROCESSING_KEY_SHIFT_LEFT, - KeyCode::ControlLeft => PROCESSING_KEY_CONTROL_LEFT, - KeyCode::AltLeft => PROCESSING_KEY_ALT_LEFT, - KeyCode::SuperLeft => PROCESSING_KEY_SUPER_LEFT, - KeyCode::ShiftRight => PROCESSING_KEY_SHIFT_RIGHT, - KeyCode::ControlRight => PROCESSING_KEY_CONTROL_RIGHT, - KeyCode::AltRight => PROCESSING_KEY_ALT_RIGHT, - KeyCode::SuperRight => PROCESSING_KEY_SUPER_RIGHT, - KeyCode::ContextMenu => PROCESSING_KEY_CONTEXT_MENU, - _ => 0, - } -} - #[wasm_bindgen(js_name = "geometryAttributeRotation")] pub fn js_geometry_attribute_rotation() -> u64 { geometry_attribute_rotation().to_bits()