[oden] Input

This commit is contained in:
John Doty 2023-07-07 07:28:46 -07:00
parent c934914ac5
commit e0878b4ea6
6 changed files with 363 additions and 14 deletions

View file

@ -3,6 +3,8 @@ use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::mpsc::Sender;
use std::sync::Arc;
// TODO: Fix the dumb command structures.
#[derive(Debug)]
pub struct PrintCommand {
pub text: String,

132
src/script/input.rs Normal file
View file

@ -0,0 +1,132 @@
use oden_js::{module::native::NativeModuleBuilder, ContextRef};
use std::cell::RefCell;
use std::sync::Arc;
use winit::event::{ElementState, KeyboardInput, VirtualKeyCode};
/// An abstraction over hardware keys.
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
enum Button {
Up,
Down,
Left,
Right,
}
impl From<Button> for u32 {
fn from(v: Button) -> Self {
match v {
Button::Up => 0,
Button::Down => 1,
Button::Left => 2,
Button::Right => 3,
}
}
}
impl TryFrom<u32> for Button {
type Error = &'static str;
fn try_from(v: u32) -> Result<Self, Self::Error> {
match v {
0 => Ok(Button::Up),
1 => Ok(Button::Down),
2 => Ok(Button::Left),
3 => Ok(Button::Right),
_ => Err("unknown button value"),
}
}
}
struct InputState {
up_pressed: bool,
down_pressed: bool,
left_pressed: bool,
right_pressed: bool,
}
impl InputState {
fn new() -> Self {
InputState {
up_pressed: false,
down_pressed: false,
left_pressed: false,
right_pressed: false,
}
}
fn handle_keyboard_input(&mut self, input: &KeyboardInput) -> bool {
let pressed = input.state == ElementState::Pressed;
match input.virtual_keycode {
Some(VirtualKeyCode::Left) => {
self.left_pressed = pressed;
true
}
Some(VirtualKeyCode::Right) => {
self.right_pressed = pressed;
true
}
Some(VirtualKeyCode::Up) => {
self.up_pressed = pressed;
true
}
Some(VirtualKeyCode::Down) => {
self.down_pressed = pressed;
true
}
_ => false,
}
}
}
struct InputImpl {
state: RefCell<InputState>,
}
impl InputImpl {
fn new() -> Self {
InputImpl {
state: RefCell::new(InputState::new()),
}
}
fn handle_keyboard_input(&self, input: &KeyboardInput) -> bool {
self.state.borrow_mut().handle_keyboard_input(input)
}
fn btn(&self, button: u32) -> bool {
if let Ok(b) = Button::try_from(button) {
let state = self.state.borrow();
match b {
Button::Up => state.up_pressed,
Button::Down => state.down_pressed,
Button::Left => state.left_pressed,
Button::Right => state.right_pressed,
}
} else {
false
}
}
}
pub struct InputAPI {
input: Arc<InputImpl>,
}
impl InputAPI {
pub fn define(ctx: &ContextRef) -> oden_js::Result<Self> {
let input = Arc::new(InputImpl::new());
let mut builder = NativeModuleBuilder::new(ctx);
{
let input = input.clone();
builder.export(
"btn",
ctx.new_fn(move |_ctx: &ContextRef, b: u32| input.btn(b))?,
)?;
}
builder.build("input-core")?;
Ok(InputAPI { input })
}
pub fn handle_keyboard_input(&mut self, input: &KeyboardInput) -> bool {
self.input.handle_keyboard_input(input)
}
}