Functional input binding

This commit is contained in:
2024-11-10 14:05:10 -05:00
parent a69247dd33
commit 5cb36d0bcc
8 changed files with 254 additions and 81 deletions
+92 -13
View File
@@ -1,29 +1,62 @@
use std::time::Instant;
use winit::{
event::{Event, WindowEvent},
event_loop::{ActiveEventLoop, EventLoopProxy},
use std::{
sync::{Arc, RwLock},
time::Instant,
};
use winit::{
dpi::LogicalSize,
event::{Event, KeyEvent, WindowEvent},
event_loop::{ActiveEventLoop, EventLoopProxy},
platform::modifier_supplement::KeyEventExtModifierSupplement,
};
use crate::{input::InputMapper, shrooms_vb_core::VBKey};
use super::{
common::{ImguiState, UiExt as _, WindowState, WindowStateBuilder},
common::{ImguiState, UiExt, WindowState, WindowStateBuilder},
AppWindow, UserEvent,
};
pub struct InputWindow {
window: WindowState,
imgui: Option<ImguiState>,
input_mapper: Arc<RwLock<InputMapper>>,
proxy: EventLoopProxy<UserEvent>,
now_binding: Option<VBKey>,
}
const KEY_NAMES: [(VBKey, &str); 14] = [
(VBKey::LU, "Up"),
(VBKey::LD, "Down"),
(VBKey::LL, "Left"),
(VBKey::LR, "Right"),
(VBKey::SEL, "Select"),
(VBKey::STA, "Start"),
(VBKey::B, "B"),
(VBKey::A, "A"),
(VBKey::LT, "L-Trigger"),
(VBKey::RT, "R-Trigger"),
(VBKey::RU, "R-Up"),
(VBKey::RD, "R-Down"),
(VBKey::RL, "R-Left"),
(VBKey::RR, "R-Right"),
];
impl InputWindow {
pub fn new(event_loop: &ActiveEventLoop, proxy: EventLoopProxy<UserEvent>) -> Self {
pub fn new(
event_loop: &ActiveEventLoop,
input_mapper: Arc<RwLock<InputMapper>>,
proxy: EventLoopProxy<UserEvent>,
) -> Self {
let window = WindowStateBuilder::new(event_loop)
.with_title("Map Inputs")
.with_title("Bind Inputs")
.with_inner_size(LogicalSize::new(600, 400))
.build();
Self {
window,
imgui: None,
input_mapper,
now_binding: None,
proxy,
}
}
@@ -50,17 +83,50 @@ impl InputWindow {
.expect("Failed to prepare frame");
let ui = context.new_frame();
if let Some(window) = ui.fullscreen_window() {
let mut render_key_bindings = || {
if let Some(table) = ui.begin_table("controls", 2) {
let binding_names = {
let mapper = self.input_mapper.read().unwrap();
mapper.binding_names()
};
ui.table_next_row();
ui.table_next_column();
ui.text("Key");
for (key, name) in KEY_NAMES {
let binding = binding_names.get(&key).map(|s| s.as_str());
ui.table_next_column();
let [space, _] = ui.content_region_avail();
ui.group(|| {
ui.right_align_text(name, space * 0.20);
ui.same_line();
let label_text = if self.now_binding == Some(key) {
"Press any input"
} else {
binding.unwrap_or("")
};
let label = format!("{}##{}", label_text, name);
if ui.button_with_size(label, [space * 0.60, 0.0]) {
self.now_binding = Some(key);
}
});
ui.same_line();
if ui.button(format!("Clear##{name}")) {
let mut mapper = self.input_mapper.write().unwrap();
mapper.clear_binding(key);
}
}
ui.table_next_column();
ui.text("Value");
table.end();
}
};
if let Some(window) = ui.fullscreen_window() {
if let Some(tabs) = ui.tab_bar("tabs") {
if let Some(tab) = ui.tab_item("Player 1") {
render_key_bindings();
tab.end();
}
tabs.end();
}
window.end();
}
let mut encoder: wgpu::CommandEncoder = window
@@ -102,6 +168,17 @@ impl InputWindow {
frame.present();
}
fn try_bind_key(&mut self, event: &KeyEvent) {
if !event.state.is_pressed() {
return;
}
let Some(vb) = self.now_binding.take() else {
return;
};
let mut mapper = self.input_mapper.write().unwrap();
mapper.bind_key(vb, event.key_without_modifiers());
}
}
impl AppWindow for InputWindow {
@@ -111,6 +188,7 @@ impl AppWindow for InputWindow {
fn init(&mut self) {
self.imgui = Some(ImguiState::new(&self.window));
self.window.window.request_redraw();
}
fn handle_event(&mut self, _: &ActiveEventLoop, event: &Event<UserEvent>) {
@@ -121,6 +199,7 @@ impl AppWindow for InputWindow {
.proxy
.send_event(UserEvent::CloseWindow(self.id()))
.unwrap(),
WindowEvent::KeyboardInput { event, .. } => self.try_bind_key(event),
WindowEvent::RedrawRequested => self.draw(),
_ => (),
},