Functional input binding
This commit is contained in:
+92
-13
@@ -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(),
|
||||
_ => (),
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user