Compare commits
No commits in common. "8d81f94b70705fd91eecfc343d0d858c59e2a739" and "1bb29b5f750cdfe9f5485a3cd45cc2a98e031f65" have entirely different histories.
8d81f94b70
...
1bb29b5f75
2 changed files with 217 additions and 387 deletions
|
@ -3,7 +3,7 @@ Game store page: https://crispypin.itch.io/marble-machinations
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### added
|
### added
|
||||||
- configurable key bindings for the basic editor actions
|
- configurable hotkeys (via file only, only some actions)
|
||||||
- OS clipboard copy/paste, with fallback to old behavior when copying
|
- OS clipboard copy/paste, with fallback to old behavior when copying
|
||||||
- in-grid text comments (not yet editable in-game)
|
- in-grid text comments (not yet editable in-game)
|
||||||
- changelog file
|
- changelog file
|
||||||
|
|
602
src/input.rs
602
src/input.rs
|
@ -1,4 +1,4 @@
|
||||||
use std::{collections::BTreeMap, mem::transmute, vec};
|
use std::{collections::BTreeMap, mem::transmute};
|
||||||
|
|
||||||
use raylib::{
|
use raylib::{
|
||||||
color::Color,
|
color::Color,
|
||||||
|
@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use crate::{
|
use crate::{
|
||||||
theme::{BG_DARK, BG_LIGHT},
|
theme::{BG_DARK, BG_LIGHT},
|
||||||
ui::text_button,
|
ui::text_button,
|
||||||
util::{rect, screen_centered_rect},
|
util::screen_centered_rect,
|
||||||
Globals,
|
Globals,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,28 +27,32 @@ pub enum ActionId {
|
||||||
StopSim,
|
StopSim,
|
||||||
StepSim,
|
StepSim,
|
||||||
// just like in C, because this way doesn't need more dependencies
|
// just like in C, because this way doesn't need more dependencies
|
||||||
_EnumSize,
|
_ActionIdSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Input {
|
impl Default for Input {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
use Button::*;
|
use KeyboardKey::*;
|
||||||
let mut bindings = [(); ActionId::SIZE].map(|_| Vec::new());
|
let mut bindings = [(); ActionId::SIZE].map(|_| Vec::new());
|
||||||
let mut bind_key = |action, mods, trigger| {
|
let mut bind_key = |action, mods, key| {
|
||||||
bindings[action as usize].push(Binding {
|
bindings[action as usize].push(Binding {
|
||||||
modifiers: mods,
|
modifiers: mods,
|
||||||
trigger,
|
trigger: InputTrigger::Key(key),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
bind_key(ActionId::Undo, vec![LCtrl], Z);
|
bind_key(ActionId::Undo, vec![KEY_LEFT_CONTROL], KEY_Z);
|
||||||
bind_key(ActionId::Redo, vec![LCtrl], Y);
|
bind_key(ActionId::Redo, vec![KEY_LEFT_CONTROL], KEY_Y);
|
||||||
bind_key(ActionId::Redo, vec![LCtrl, LShift], Z);
|
bind_key(
|
||||||
bind_key(ActionId::Copy, vec![LCtrl], C);
|
ActionId::Redo,
|
||||||
bind_key(ActionId::Paste, vec![LCtrl], V);
|
vec![KEY_LEFT_CONTROL, KEY_LEFT_SHIFT],
|
||||||
bind_key(ActionId::ToggleMenu, vec![], Escape);
|
KEY_Z,
|
||||||
bind_key(ActionId::StartSim, vec![], Enter);
|
);
|
||||||
bind_key(ActionId::StopSim, vec![], Enter);
|
bind_key(ActionId::Copy, vec![KEY_LEFT_CONTROL], KEY_C);
|
||||||
bind_key(ActionId::StepSim, vec![], Space);
|
bind_key(ActionId::Paste, vec![KEY_LEFT_CONTROL], KEY_V);
|
||||||
|
bind_key(ActionId::ToggleMenu, vec![], KEY_ESCAPE);
|
||||||
|
bind_key(ActionId::StartSim, vec![], KEY_ENTER);
|
||||||
|
bind_key(ActionId::StopSim, vec![], KEY_ENTER);
|
||||||
|
bind_key(ActionId::StepSim, vec![], KEY_SPACE);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
bindings,
|
bindings,
|
||||||
|
@ -75,14 +79,7 @@ pub struct Input {
|
||||||
bindings: [Vec<Binding>; ActionId::SIZE],
|
bindings: [Vec<Binding>; ActionId::SIZE],
|
||||||
states: [BindingState; ActionId::SIZE],
|
states: [BindingState; ActionId::SIZE],
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
editing_input: Option<(ActionId, usize, BindingEdit)>,
|
editing_input: Option<(ActionId, usize)>,
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
enum BindingEdit {
|
|
||||||
Init,
|
|
||||||
Adding(Binding),
|
|
||||||
Releasing(Binding),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Input {
|
impl Input {
|
||||||
|
@ -105,7 +102,7 @@ impl Input {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if text_button(d, &globals.mouse, 245, y, 45, "edit") {
|
if text_button(d, &globals.mouse, 245, y, 45, "edit") {
|
||||||
self.editing_input = Some((action, binding_index, BindingEdit::Init));
|
self.editing_input = Some((action, binding_index));
|
||||||
}
|
}
|
||||||
let trigger = format!("{:?}", binding.trigger);
|
let trigger = format!("{:?}", binding.trigger);
|
||||||
d.draw_text(&trigger, 300, y, 20, Color::LIMEGREEN);
|
d.draw_text(&trigger, 300, y, 20, Color::LIMEGREEN);
|
||||||
|
@ -114,93 +111,21 @@ impl Input {
|
||||||
d.draw_text(&modifiers, x, y, 20, Color::LIGHTBLUE);
|
d.draw_text(&modifiers, x, y, 20, Color::LIGHTBLUE);
|
||||||
y += 32;
|
y += 32;
|
||||||
}
|
}
|
||||||
if text_button(d, &globals.mouse, 160, y, 130, "add binding") {
|
y += 8;
|
||||||
self.editing_input =
|
|
||||||
Some((action, self.bindings[action_index].len(), BindingEdit::Init));
|
|
||||||
}
|
|
||||||
y += 45;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((action, binding_index, edit_state)) = &mut self.editing_input {
|
if let Some((action, binding_index)) = &self.editing_input {
|
||||||
globals.mouse.update(d);
|
globals.mouse.update(d); // todo less scuffed
|
||||||
let border = screen_centered_rect(d, 368, 128);
|
let border = screen_centered_rect(d, 208, 88);
|
||||||
d.draw_rectangle_rec(border, BG_LIGHT);
|
d.draw_rectangle_rec(border, BG_LIGHT);
|
||||||
let bounds = screen_centered_rect(d, 360, 120);
|
let bounds = screen_centered_rect(d, 200, 80);
|
||||||
d.draw_rectangle_rec(bounds, BG_DARK);
|
d.draw_rectangle_rec(bounds, BG_DARK);
|
||||||
|
|
||||||
|
// TODO capture and display current input
|
||||||
|
|
||||||
let x = bounds.x as i32;
|
let x = bounds.x as i32;
|
||||||
let y = bounds.y as i32;
|
let y = bounds.y as i32;
|
||||||
d.draw_text(
|
if text_button(d, &globals.mouse, x + 10, y + 40, 80, "ok") {}
|
||||||
&format!("editing binding for {action:?}"),
|
|
||||||
x + 5,
|
|
||||||
y + 5,
|
|
||||||
20,
|
|
||||||
Color::WHITE,
|
|
||||||
);
|
|
||||||
let y = y + 30;
|
|
||||||
let ok_btn_x = x + 10;
|
|
||||||
let ok_btn_y = y + 40;
|
|
||||||
let ok_btn_width = 80;
|
|
||||||
let ok_btn_rect = rect(ok_btn_x, ok_btn_y, ok_btn_width, 30);
|
|
||||||
|
|
||||||
for key_index in 0..Button::SIZE {
|
|
||||||
let key = Button::from_usize(key_index).unwrap();
|
|
||||||
match edit_state {
|
|
||||||
BindingEdit::Init => {
|
|
||||||
if key.just_pressed(d) {
|
|
||||||
*edit_state = BindingEdit::Adding(Binding {
|
|
||||||
modifiers: Vec::new(),
|
|
||||||
trigger: key,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BindingEdit::Adding(binding) => {
|
|
||||||
if key.just_pressed(d) {
|
|
||||||
if key != binding.trigger && !binding.modifiers.contains(&key) {
|
|
||||||
binding.modifiers.push(binding.trigger);
|
|
||||||
binding.trigger = key;
|
|
||||||
}
|
|
||||||
} else if key.released(d) {
|
|
||||||
if let Some(i) = binding.modifiers.iter().position(|&k| k == key) {
|
|
||||||
binding.modifiers.remove(i);
|
|
||||||
binding.modifiers.push(binding.trigger);
|
|
||||||
binding.trigger = key;
|
|
||||||
}
|
|
||||||
*edit_state = BindingEdit::Releasing(binding.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BindingEdit::Releasing(_binding) => {
|
|
||||||
let clicking_ok =
|
|
||||||
globals.mouse.is_over(ok_btn_rect) && key == Button::MouseLeft;
|
|
||||||
if key.just_pressed(d) && !clicking_ok {
|
|
||||||
*edit_state = BindingEdit::Adding(Binding {
|
|
||||||
modifiers: Vec::new(),
|
|
||||||
trigger: key,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let BindingEdit::Adding(b) | BindingEdit::Releasing(b) = &edit_state {
|
|
||||||
let colour = if matches!(edit_state, BindingEdit::Releasing(_)) {
|
|
||||||
Color::GREEN
|
|
||||||
} else {
|
|
||||||
Color::ORANGE
|
|
||||||
};
|
|
||||||
let text = format!("{:?} + {:?}", b.modifiers, b.trigger);
|
|
||||||
d.draw_text(&text, x + 5, y + 5, 20, colour);
|
|
||||||
}
|
|
||||||
if text_button(d, &globals.mouse, ok_btn_x, ok_btn_y, ok_btn_width, "ok") {
|
|
||||||
if let BindingEdit::Releasing(binding) = edit_state {
|
|
||||||
let binding_list = &mut self.bindings[*action as usize];
|
|
||||||
if *binding_index < binding_list.len() {
|
|
||||||
binding_list[*binding_index] = binding.clone();
|
|
||||||
} else {
|
|
||||||
binding_list.push(binding.clone());
|
|
||||||
}
|
|
||||||
self.editing_input = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if text_button(d, &globals.mouse, x + 100, y + 40, 80, "cancel") {
|
if text_button(d, &globals.mouse, x + 100, y + 40, 80, "cancel") {
|
||||||
self.editing_input = None;
|
self.editing_input = None;
|
||||||
}
|
}
|
||||||
|
@ -212,8 +137,11 @@ impl Input {
|
||||||
let bindings = &self.bindings[i];
|
let bindings = &self.bindings[i];
|
||||||
let mut is_active = false;
|
let mut is_active = false;
|
||||||
for binding in bindings {
|
for binding in bindings {
|
||||||
if binding.modifiers.iter().all(|&m| m.is_down(rl)) {
|
if binding.modifiers.iter().all(|&m| rl.is_key_down(m)) {
|
||||||
is_active |= binding.trigger.is_down(rl);
|
is_active |= match binding.trigger {
|
||||||
|
InputTrigger::Mouse(btn) => rl.is_mouse_button_down(btn),
|
||||||
|
InputTrigger::Key(key) => rl.is_key_down(key),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let state = &mut self.states[i];
|
let state = &mut self.states[i];
|
||||||
|
@ -246,11 +174,11 @@ impl Input {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActionId {
|
impl ActionId {
|
||||||
pub const SIZE: usize = Self::_EnumSize as usize;
|
pub const SIZE: usize = Self::_ActionIdSize as usize;
|
||||||
|
|
||||||
fn from_usize(val: usize) -> Option<Self> {
|
fn from_usize(val: usize) -> Option<Self> {
|
||||||
if val < Self::SIZE {
|
if val < Self::SIZE {
|
||||||
Some(unsafe { transmute::<u8, Self>(val as u8) })
|
Some(unsafe { transmute::<u8, ActionId>(val as u8) })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -258,11 +186,20 @@ impl ActionId {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(from = "BindingSerde", into = "BindingSerde")]
|
||||||
pub struct Binding {
|
pub struct Binding {
|
||||||
modifiers: Vec<Button>,
|
modifiers: Vec<KeyboardKey>,
|
||||||
trigger: Button,
|
trigger: InputTrigger,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum InputTrigger {
|
||||||
|
Mouse(MouseButton),
|
||||||
|
Key(KeyboardKey),
|
||||||
|
}
|
||||||
|
|
||||||
|
// ###### everything below is for serialization of key bindings ######
|
||||||
|
|
||||||
impl From<InputMap> for Input {
|
impl From<InputMap> for Input {
|
||||||
fn from(value: InputMap) -> Self {
|
fn from(value: InputMap) -> Self {
|
||||||
let mut new = Self::default();
|
let mut new = Self::default();
|
||||||
|
@ -285,285 +222,178 @@ impl From<Input> for InputMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
#[repr(u8)]
|
struct BindingSerde {
|
||||||
enum Button {
|
modifiers: Vec<String>,
|
||||||
MouseLeft,
|
trigger: InputTriggerSerde,
|
||||||
MouseRight,
|
|
||||||
MouseMiddle,
|
|
||||||
Mouse3,
|
|
||||||
Mouse4,
|
|
||||||
Mouse5,
|
|
||||||
Mouse6,
|
|
||||||
Apostrophe,
|
|
||||||
Comma,
|
|
||||||
Minus,
|
|
||||||
Period,
|
|
||||||
Slash,
|
|
||||||
Zero,
|
|
||||||
One,
|
|
||||||
Two,
|
|
||||||
Three,
|
|
||||||
Four,
|
|
||||||
Five,
|
|
||||||
Six,
|
|
||||||
Seven,
|
|
||||||
Eight,
|
|
||||||
Nine,
|
|
||||||
Semicolon,
|
|
||||||
Equal,
|
|
||||||
A,
|
|
||||||
B,
|
|
||||||
C,
|
|
||||||
D,
|
|
||||||
E,
|
|
||||||
F,
|
|
||||||
G,
|
|
||||||
H,
|
|
||||||
I,
|
|
||||||
J,
|
|
||||||
K,
|
|
||||||
L,
|
|
||||||
M,
|
|
||||||
N,
|
|
||||||
O,
|
|
||||||
P,
|
|
||||||
Q,
|
|
||||||
R,
|
|
||||||
S,
|
|
||||||
T,
|
|
||||||
U,
|
|
||||||
V,
|
|
||||||
W,
|
|
||||||
X,
|
|
||||||
Y,
|
|
||||||
Z,
|
|
||||||
LeftBracket,
|
|
||||||
Backslash,
|
|
||||||
RightBracket,
|
|
||||||
Grave,
|
|
||||||
Space,
|
|
||||||
Escape,
|
|
||||||
Enter,
|
|
||||||
Tab,
|
|
||||||
Backspace,
|
|
||||||
Insert,
|
|
||||||
Delete,
|
|
||||||
Right,
|
|
||||||
Left,
|
|
||||||
Down,
|
|
||||||
Up,
|
|
||||||
PageUp,
|
|
||||||
PageDown,
|
|
||||||
Home,
|
|
||||||
End,
|
|
||||||
CapsLock,
|
|
||||||
ScrollLock,
|
|
||||||
NumLock,
|
|
||||||
PrintScreen,
|
|
||||||
Pause,
|
|
||||||
F1,
|
|
||||||
F2,
|
|
||||||
F3,
|
|
||||||
F4,
|
|
||||||
F5,
|
|
||||||
F6,
|
|
||||||
F7,
|
|
||||||
F8,
|
|
||||||
F9,
|
|
||||||
F10,
|
|
||||||
F11,
|
|
||||||
F12,
|
|
||||||
LShift,
|
|
||||||
LCtrl,
|
|
||||||
LAlt,
|
|
||||||
LeftSuper,
|
|
||||||
RShift,
|
|
||||||
RCtrl,
|
|
||||||
RAlt,
|
|
||||||
RightSuper,
|
|
||||||
Menu,
|
|
||||||
Kp0,
|
|
||||||
Kp1,
|
|
||||||
Kp2,
|
|
||||||
Kp3,
|
|
||||||
Kp4,
|
|
||||||
Kp5,
|
|
||||||
Kp6,
|
|
||||||
Kp7,
|
|
||||||
Kp8,
|
|
||||||
Kp9,
|
|
||||||
KpDecimal,
|
|
||||||
KpDivide,
|
|
||||||
KpMultiply,
|
|
||||||
KpSubtract,
|
|
||||||
KpAdd,
|
|
||||||
KpEnter,
|
|
||||||
KpEqual,
|
|
||||||
Back,
|
|
||||||
VolumeUp,
|
|
||||||
VolumeDown,
|
|
||||||
//
|
|
||||||
_EnumSize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RlInput {
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
Key(KeyboardKey),
|
enum InputTriggerSerde {
|
||||||
Mouse(MouseButton),
|
Mouse(String),
|
||||||
|
Key(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Button {
|
impl From<BindingSerde> for Binding {
|
||||||
const SIZE: usize = Self::_EnumSize as usize;
|
fn from(value: BindingSerde) -> Self {
|
||||||
|
Self {
|
||||||
fn from_usize(val: usize) -> Option<Self> {
|
modifiers: value
|
||||||
if val < Self::SIZE {
|
.modifiers
|
||||||
Some(unsafe { transmute::<u8, Self>(val as u8) })
|
.iter()
|
||||||
} else {
|
.map(|s| key_string_to_enum(s))
|
||||||
None
|
.collect(),
|
||||||
}
|
trigger: value.trigger.into(),
|
||||||
}
|
|
||||||
|
|
||||||
fn is_down(self, rl: &RaylibHandle) -> bool {
|
|
||||||
match self.to_raylib() {
|
|
||||||
RlInput::Key(key) => rl.is_key_down(key),
|
|
||||||
RlInput::Mouse(btn) => rl.is_mouse_button_down(btn),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn just_pressed(self, rl: &RaylibHandle) -> bool {
|
|
||||||
match self.to_raylib() {
|
|
||||||
RlInput::Key(key) => rl.is_key_pressed(key),
|
|
||||||
RlInput::Mouse(btn) => rl.is_mouse_button_pressed(btn),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn released(self, rl: &RaylibHandle) -> bool {
|
|
||||||
match self.to_raylib() {
|
|
||||||
RlInput::Key(key) => rl.is_key_released(key),
|
|
||||||
RlInput::Mouse(btn) => rl.is_mouse_button_released(btn),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_raylib(self) -> RlInput {
|
|
||||||
use KeyboardKey::*;
|
|
||||||
use RlInput::*;
|
|
||||||
match self {
|
|
||||||
Button::MouseLeft => Mouse(MouseButton::MOUSE_BUTTON_LEFT),
|
|
||||||
Button::MouseRight => Mouse(MouseButton::MOUSE_BUTTON_RIGHT),
|
|
||||||
Button::MouseMiddle => Mouse(MouseButton::MOUSE_BUTTON_MIDDLE),
|
|
||||||
Button::Mouse3 => Mouse(MouseButton::MOUSE_BUTTON_SIDE),
|
|
||||||
Button::Mouse4 => Mouse(MouseButton::MOUSE_BUTTON_EXTRA),
|
|
||||||
Button::Mouse5 => Mouse(MouseButton::MOUSE_BUTTON_FORWARD),
|
|
||||||
Button::Mouse6 => Mouse(MouseButton::MOUSE_BUTTON_BACK),
|
|
||||||
Button::Apostrophe => Key(KEY_APOSTROPHE),
|
|
||||||
Button::Comma => Key(KEY_COMMA),
|
|
||||||
Button::Minus => Key(KEY_MINUS),
|
|
||||||
Button::Period => Key(KEY_PERIOD),
|
|
||||||
Button::Slash => Key(KEY_SLASH),
|
|
||||||
Button::Zero => Key(KEY_ZERO),
|
|
||||||
Button::One => Key(KEY_ONE),
|
|
||||||
Button::Two => Key(KEY_TWO),
|
|
||||||
Button::Three => Key(KEY_THREE),
|
|
||||||
Button::Four => Key(KEY_FOUR),
|
|
||||||
Button::Five => Key(KEY_FIVE),
|
|
||||||
Button::Six => Key(KEY_SIX),
|
|
||||||
Button::Seven => Key(KEY_SEVEN),
|
|
||||||
Button::Eight => Key(KEY_EIGHT),
|
|
||||||
Button::Nine => Key(KEY_NINE),
|
|
||||||
Button::Semicolon => Key(KEY_SEMICOLON),
|
|
||||||
Button::Equal => Key(KEY_EQUAL),
|
|
||||||
Button::A => Key(KEY_A),
|
|
||||||
Button::B => Key(KEY_B),
|
|
||||||
Button::C => Key(KEY_C),
|
|
||||||
Button::D => Key(KEY_D),
|
|
||||||
Button::E => Key(KEY_E),
|
|
||||||
Button::F => Key(KEY_F),
|
|
||||||
Button::G => Key(KEY_G),
|
|
||||||
Button::H => Key(KEY_H),
|
|
||||||
Button::I => Key(KEY_I),
|
|
||||||
Button::J => Key(KEY_J),
|
|
||||||
Button::K => Key(KEY_K),
|
|
||||||
Button::L => Key(KEY_L),
|
|
||||||
Button::M => Key(KEY_M),
|
|
||||||
Button::N => Key(KEY_N),
|
|
||||||
Button::O => Key(KEY_O),
|
|
||||||
Button::P => Key(KEY_P),
|
|
||||||
Button::Q => Key(KEY_Q),
|
|
||||||
Button::R => Key(KEY_R),
|
|
||||||
Button::S => Key(KEY_S),
|
|
||||||
Button::T => Key(KEY_T),
|
|
||||||
Button::U => Key(KEY_U),
|
|
||||||
Button::V => Key(KEY_V),
|
|
||||||
Button::W => Key(KEY_W),
|
|
||||||
Button::X => Key(KEY_X),
|
|
||||||
Button::Y => Key(KEY_Y),
|
|
||||||
Button::Z => Key(KEY_Z),
|
|
||||||
Button::LeftBracket => Key(KEY_LEFT_BRACKET),
|
|
||||||
Button::Backslash => Key(KEY_BACKSLASH),
|
|
||||||
Button::RightBracket => Key(KEY_RIGHT_BRACKET),
|
|
||||||
Button::Grave => Key(KEY_GRAVE),
|
|
||||||
Button::Space => Key(KEY_SPACE),
|
|
||||||
Button::Escape => Key(KEY_ESCAPE),
|
|
||||||
Button::Enter => Key(KEY_ENTER),
|
|
||||||
Button::Tab => Key(KEY_TAB),
|
|
||||||
Button::Backspace => Key(KEY_BACKSPACE),
|
|
||||||
Button::Insert => Key(KEY_INSERT),
|
|
||||||
Button::Delete => Key(KEY_DELETE),
|
|
||||||
Button::Right => Key(KEY_RIGHT),
|
|
||||||
Button::Left => Key(KEY_LEFT),
|
|
||||||
Button::Down => Key(KEY_DOWN),
|
|
||||||
Button::Up => Key(KEY_UP),
|
|
||||||
Button::PageUp => Key(KEY_PAGE_UP),
|
|
||||||
Button::PageDown => Key(KEY_PAGE_DOWN),
|
|
||||||
Button::Home => Key(KEY_HOME),
|
|
||||||
Button::End => Key(KEY_END),
|
|
||||||
Button::CapsLock => Key(KEY_CAPS_LOCK),
|
|
||||||
Button::ScrollLock => Key(KEY_SCROLL_LOCK),
|
|
||||||
Button::NumLock => Key(KEY_NUM_LOCK),
|
|
||||||
Button::PrintScreen => Key(KEY_PRINT_SCREEN),
|
|
||||||
Button::Pause => Key(KEY_PAUSE),
|
|
||||||
Button::F1 => Key(KEY_F1),
|
|
||||||
Button::F2 => Key(KEY_F2),
|
|
||||||
Button::F3 => Key(KEY_F3),
|
|
||||||
Button::F4 => Key(KEY_F4),
|
|
||||||
Button::F5 => Key(KEY_F5),
|
|
||||||
Button::F6 => Key(KEY_F6),
|
|
||||||
Button::F7 => Key(KEY_F7),
|
|
||||||
Button::F8 => Key(KEY_F8),
|
|
||||||
Button::F9 => Key(KEY_F9),
|
|
||||||
Button::F10 => Key(KEY_F10),
|
|
||||||
Button::F11 => Key(KEY_F11),
|
|
||||||
Button::F12 => Key(KEY_F12),
|
|
||||||
Button::LShift => Key(KEY_LEFT_SHIFT),
|
|
||||||
Button::LCtrl => Key(KEY_LEFT_CONTROL),
|
|
||||||
Button::LAlt => Key(KEY_LEFT_ALT),
|
|
||||||
Button::LeftSuper => Key(KEY_LEFT_SUPER),
|
|
||||||
Button::RShift => Key(KEY_RIGHT_SHIFT),
|
|
||||||
Button::RCtrl => Key(KEY_RIGHT_CONTROL),
|
|
||||||
Button::RAlt => Key(KEY_RIGHT_ALT),
|
|
||||||
Button::RightSuper => Key(KEY_RIGHT_SUPER),
|
|
||||||
Button::Menu => Key(KEY_KB_MENU),
|
|
||||||
Button::Kp0 => Key(KEY_KP_0),
|
|
||||||
Button::Kp1 => Key(KEY_KP_1),
|
|
||||||
Button::Kp2 => Key(KEY_KP_2),
|
|
||||||
Button::Kp3 => Key(KEY_KP_3),
|
|
||||||
Button::Kp4 => Key(KEY_KP_4),
|
|
||||||
Button::Kp5 => Key(KEY_KP_5),
|
|
||||||
Button::Kp6 => Key(KEY_KP_6),
|
|
||||||
Button::Kp7 => Key(KEY_KP_7),
|
|
||||||
Button::Kp8 => Key(KEY_KP_8),
|
|
||||||
Button::Kp9 => Key(KEY_KP_9),
|
|
||||||
Button::KpDecimal => Key(KEY_KP_DECIMAL),
|
|
||||||
Button::KpDivide => Key(KEY_KP_DIVIDE),
|
|
||||||
Button::KpMultiply => Key(KEY_KP_MULTIPLY),
|
|
||||||
Button::KpSubtract => Key(KEY_KP_SUBTRACT),
|
|
||||||
Button::KpAdd => Key(KEY_KP_ADD),
|
|
||||||
Button::KpEnter => Key(KEY_KP_ENTER),
|
|
||||||
Button::KpEqual => Key(KEY_KP_EQUAL),
|
|
||||||
Button::Back => Key(KEY_BACK),
|
|
||||||
Button::VolumeUp => Key(KEY_VOLUME_UP),
|
|
||||||
Button::VolumeDown => Key(KEY_VOLUME_DOWN),
|
|
||||||
Button::_EnumSize => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Binding> for BindingSerde {
|
||||||
|
fn from(value: Binding) -> Self {
|
||||||
|
Self {
|
||||||
|
modifiers: value.modifiers.iter().map(|c| format!("{c:?}")).collect(),
|
||||||
|
trigger: value.trigger.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<InputTrigger> for InputTriggerSerde {
|
||||||
|
fn from(value: InputTrigger) -> Self {
|
||||||
|
match value {
|
||||||
|
InputTrigger::Mouse(btn) => InputTriggerSerde::Mouse(format!("{btn:?}")),
|
||||||
|
InputTrigger::Key(key) => InputTriggerSerde::Key(format!("{key:?}")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<InputTriggerSerde> for InputTrigger {
|
||||||
|
fn from(value: InputTriggerSerde) -> Self {
|
||||||
|
match value {
|
||||||
|
InputTriggerSerde::Mouse(btn) => InputTrigger::Mouse(match btn.as_str() {
|
||||||
|
"MOUSE_BUTTON_LEFT" => MouseButton::MOUSE_BUTTON_LEFT,
|
||||||
|
"MOUSE_BUTTON_RIGHT" => MouseButton::MOUSE_BUTTON_RIGHT,
|
||||||
|
"MOUSE_BUTTON_MIDDLE" => MouseButton::MOUSE_BUTTON_MIDDLE,
|
||||||
|
"MOUSE_BUTTON_SIDE" => MouseButton::MOUSE_BUTTON_SIDE,
|
||||||
|
"MOUSE_BUTTON_EXTRA" => MouseButton::MOUSE_BUTTON_EXTRA,
|
||||||
|
"MOUSE_BUTTON_FORWARD" => MouseButton::MOUSE_BUTTON_FORWARD,
|
||||||
|
"MOUSE_BUTTON_BACK" => MouseButton::MOUSE_BUTTON_BACK,
|
||||||
|
_ => panic!("{btn} not a valid mouse button"),
|
||||||
|
}),
|
||||||
|
InputTriggerSerde::Key(key) => InputTrigger::Key(key_string_to_enum(key.as_str())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn key_string_to_enum(key: &str) -> KeyboardKey {
|
||||||
|
match key {
|
||||||
|
"KEY_NULL" => KeyboardKey::KEY_NULL,
|
||||||
|
"KEY_APOSTROPHE" => KeyboardKey::KEY_APOSTROPHE,
|
||||||
|
"KEY_COMMA" => KeyboardKey::KEY_COMMA,
|
||||||
|
"KEY_MINUS" => KeyboardKey::KEY_MINUS,
|
||||||
|
"KEY_PERIOD" => KeyboardKey::KEY_PERIOD,
|
||||||
|
"KEY_SLASH" => KeyboardKey::KEY_SLASH,
|
||||||
|
"KEY_ZERO" => KeyboardKey::KEY_ZERO,
|
||||||
|
"KEY_ONE" => KeyboardKey::KEY_ONE,
|
||||||
|
"KEY_TWO" => KeyboardKey::KEY_TWO,
|
||||||
|
"KEY_THREE" => KeyboardKey::KEY_THREE,
|
||||||
|
"KEY_FOUR" => KeyboardKey::KEY_FOUR,
|
||||||
|
"KEY_FIVE" => KeyboardKey::KEY_FIVE,
|
||||||
|
"KEY_SIX" => KeyboardKey::KEY_SIX,
|
||||||
|
"KEY_SEVEN" => KeyboardKey::KEY_SEVEN,
|
||||||
|
"KEY_EIGHT" => KeyboardKey::KEY_EIGHT,
|
||||||
|
"KEY_NINE" => KeyboardKey::KEY_NINE,
|
||||||
|
"KEY_SEMICOLON" => KeyboardKey::KEY_SEMICOLON,
|
||||||
|
"KEY_EQUAL" => KeyboardKey::KEY_EQUAL,
|
||||||
|
"KEY_A" => KeyboardKey::KEY_A,
|
||||||
|
"KEY_B" => KeyboardKey::KEY_B,
|
||||||
|
"KEY_C" => KeyboardKey::KEY_C,
|
||||||
|
"KEY_D" => KeyboardKey::KEY_D,
|
||||||
|
"KEY_E" => KeyboardKey::KEY_E,
|
||||||
|
"KEY_F" => KeyboardKey::KEY_F,
|
||||||
|
"KEY_G" => KeyboardKey::KEY_G,
|
||||||
|
"KEY_H" => KeyboardKey::KEY_H,
|
||||||
|
"KEY_I" => KeyboardKey::KEY_I,
|
||||||
|
"KEY_J" => KeyboardKey::KEY_J,
|
||||||
|
"KEY_K" => KeyboardKey::KEY_K,
|
||||||
|
"KEY_L" => KeyboardKey::KEY_L,
|
||||||
|
"KEY_M" => KeyboardKey::KEY_M,
|
||||||
|
"KEY_N" => KeyboardKey::KEY_N,
|
||||||
|
"KEY_O" => KeyboardKey::KEY_O,
|
||||||
|
"KEY_P" => KeyboardKey::KEY_P,
|
||||||
|
"KEY_Q" => KeyboardKey::KEY_Q,
|
||||||
|
"KEY_R" => KeyboardKey::KEY_R,
|
||||||
|
"KEY_S" => KeyboardKey::KEY_S,
|
||||||
|
"KEY_T" => KeyboardKey::KEY_T,
|
||||||
|
"KEY_U" => KeyboardKey::KEY_U,
|
||||||
|
"KEY_V" => KeyboardKey::KEY_V,
|
||||||
|
"KEY_W" => KeyboardKey::KEY_W,
|
||||||
|
"KEY_X" => KeyboardKey::KEY_X,
|
||||||
|
"KEY_Y" => KeyboardKey::KEY_Y,
|
||||||
|
"KEY_Z" => KeyboardKey::KEY_Z,
|
||||||
|
"KEY_LEFT_BRACKET" => KeyboardKey::KEY_LEFT_BRACKET,
|
||||||
|
"KEY_BACKSLASH" => KeyboardKey::KEY_BACKSLASH,
|
||||||
|
"KEY_RIGHT_BRACKET" => KeyboardKey::KEY_RIGHT_BRACKET,
|
||||||
|
"KEY_GRAVE" => KeyboardKey::KEY_GRAVE,
|
||||||
|
"KEY_SPACE" => KeyboardKey::KEY_SPACE,
|
||||||
|
"KEY_ESCAPE" => KeyboardKey::KEY_ESCAPE,
|
||||||
|
"KEY_ENTER" => KeyboardKey::KEY_ENTER,
|
||||||
|
"KEY_TAB" => KeyboardKey::KEY_TAB,
|
||||||
|
"KEY_BACKSPACE" => KeyboardKey::KEY_BACKSPACE,
|
||||||
|
"KEY_INSERT" => KeyboardKey::KEY_INSERT,
|
||||||
|
"KEY_DELETE" => KeyboardKey::KEY_DELETE,
|
||||||
|
"KEY_RIGHT" => KeyboardKey::KEY_RIGHT,
|
||||||
|
"KEY_LEFT" => KeyboardKey::KEY_LEFT,
|
||||||
|
"KEY_DOWN" => KeyboardKey::KEY_DOWN,
|
||||||
|
"KEY_UP" => KeyboardKey::KEY_UP,
|
||||||
|
"KEY_PAGE_UP" => KeyboardKey::KEY_PAGE_UP,
|
||||||
|
"KEY_PAGE_DOWN" => KeyboardKey::KEY_PAGE_DOWN,
|
||||||
|
"KEY_HOME" => KeyboardKey::KEY_HOME,
|
||||||
|
"KEY_END" => KeyboardKey::KEY_END,
|
||||||
|
"KEY_CAPS_LOCK" => KeyboardKey::KEY_CAPS_LOCK,
|
||||||
|
"KEY_SCROLL_LOCK" => KeyboardKey::KEY_SCROLL_LOCK,
|
||||||
|
"KEY_NUM_LOCK" => KeyboardKey::KEY_NUM_LOCK,
|
||||||
|
"KEY_PRINT_SCREEN" => KeyboardKey::KEY_PRINT_SCREEN,
|
||||||
|
"KEY_PAUSE" => KeyboardKey::KEY_PAUSE,
|
||||||
|
"KEY_F1" => KeyboardKey::KEY_F1,
|
||||||
|
"KEY_F2" => KeyboardKey::KEY_F2,
|
||||||
|
"KEY_F3" => KeyboardKey::KEY_F3,
|
||||||
|
"KEY_F4" => KeyboardKey::KEY_F4,
|
||||||
|
"KEY_F5" => KeyboardKey::KEY_F5,
|
||||||
|
"KEY_F6" => KeyboardKey::KEY_F6,
|
||||||
|
"KEY_F7" => KeyboardKey::KEY_F7,
|
||||||
|
"KEY_F8" => KeyboardKey::KEY_F8,
|
||||||
|
"KEY_F9" => KeyboardKey::KEY_F9,
|
||||||
|
"KEY_F10" => KeyboardKey::KEY_F10,
|
||||||
|
"KEY_F11" => KeyboardKey::KEY_F11,
|
||||||
|
"KEY_F12" => KeyboardKey::KEY_F12,
|
||||||
|
"KEY_LEFT_SHIFT" => KeyboardKey::KEY_LEFT_SHIFT,
|
||||||
|
"KEY_LEFT_CONTROL" => KeyboardKey::KEY_LEFT_CONTROL,
|
||||||
|
"KEY_LEFT_ALT" => KeyboardKey::KEY_LEFT_ALT,
|
||||||
|
"KEY_LEFT_SUPER" => KeyboardKey::KEY_LEFT_SUPER,
|
||||||
|
"KEY_RIGHT_SHIFT" => KeyboardKey::KEY_RIGHT_SHIFT,
|
||||||
|
"KEY_RIGHT_CONTROL" => KeyboardKey::KEY_RIGHT_CONTROL,
|
||||||
|
"KEY_RIGHT_ALT" => KeyboardKey::KEY_RIGHT_ALT,
|
||||||
|
"KEY_RIGHT_SUPER" => KeyboardKey::KEY_RIGHT_SUPER,
|
||||||
|
"KEY_KB_MENU" => KeyboardKey::KEY_KB_MENU,
|
||||||
|
"KEY_KP_0" => KeyboardKey::KEY_KP_0,
|
||||||
|
"KEY_KP_1" => KeyboardKey::KEY_KP_1,
|
||||||
|
"KEY_KP_2" => KeyboardKey::KEY_KP_2,
|
||||||
|
"KEY_KP_3" => KeyboardKey::KEY_KP_3,
|
||||||
|
"KEY_KP_4" => KeyboardKey::KEY_KP_4,
|
||||||
|
"KEY_KP_5" => KeyboardKey::KEY_KP_5,
|
||||||
|
"KEY_KP_6" => KeyboardKey::KEY_KP_6,
|
||||||
|
"KEY_KP_7" => KeyboardKey::KEY_KP_7,
|
||||||
|
"KEY_KP_8" => KeyboardKey::KEY_KP_8,
|
||||||
|
"KEY_KP_9" => KeyboardKey::KEY_KP_9,
|
||||||
|
"KEY_KP_DECIMAL" => KeyboardKey::KEY_KP_DECIMAL,
|
||||||
|
"KEY_KP_DIVIDE" => KeyboardKey::KEY_KP_DIVIDE,
|
||||||
|
"KEY_KP_MULTIPLY" => KeyboardKey::KEY_KP_MULTIPLY,
|
||||||
|
"KEY_KP_SUBTRACT" => KeyboardKey::KEY_KP_SUBTRACT,
|
||||||
|
"KEY_KP_ADD" => KeyboardKey::KEY_KP_ADD,
|
||||||
|
"KEY_KP_ENTER" => KeyboardKey::KEY_KP_ENTER,
|
||||||
|
"KEY_KP_EQUAL" => KeyboardKey::KEY_KP_EQUAL,
|
||||||
|
"KEY_BACK" => KeyboardKey::KEY_BACK,
|
||||||
|
"KEY_VOLUME_UP" => KeyboardKey::KEY_VOLUME_UP,
|
||||||
|
"KEY_VOLUME_DOWN" => KeyboardKey::KEY_VOLUME_DOWN,
|
||||||
|
_ => panic!("{key} not a known key name"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue