lemur/src/window/input.rs

134 lines
4.4 KiB
Rust
Raw Normal View History

2024-11-26 05:38:03 +00:00
use egui::{
Button, CentralPanel, Context, Label, Layout, TopBottomPanel, Ui, ViewportBuilder, ViewportId,
};
use egui_extras::{Column, TableBuilder};
use crate::{
emulator::{SimId, VBKey},
input::MappingProvider,
};
use super::AppWindow;
pub struct InputWindow {
mappings: MappingProvider,
now_binding: Option<(SimId, VBKey)>,
active_tab: InputTab,
}
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(mappings: MappingProvider) -> Self {
Self {
mappings,
now_binding: None,
active_tab: InputTab::Player1,
}
}
fn render_key_bindings(&mut self, ui: &mut Ui, sim_id: SimId) {
let mappings = self.mappings.for_sim(sim_id);
let binding_names = {
let mapping = mappings.read().unwrap();
mapping.keyboard_mapping_names()
};
TableBuilder::new(ui)
.column(Column::remainder())
.column(Column::remainder())
.cell_layout(Layout::left_to_right(egui::Align::Center))
.body(|mut body| {
for keys in KEY_NAMES.chunks_exact(2) {
body.row(20.0, |mut row| {
for (key, name) in keys {
let binding = binding_names.get(key).map(|s| s.as_str());
row.col(|ui| {
let size = ui.available_size_before_wrap();
let width = size.x;
let height = size.y;
ui.add_sized((width * 0.2, height), Label::new(*name));
let label_text = if self.now_binding == Some((sim_id, *key)) {
"Press any input"
} else {
binding.unwrap_or("")
};
if ui
.add_sized((width * 0.6, height), Button::new(label_text))
.clicked()
{
self.now_binding = Some((sim_id, *key))
}
if ui
.add_sized(ui.available_size(), Button::new("Clear"))
.clicked()
{
let mut mapping = mappings.write().unwrap();
mapping.clear_keyboard_mappings(*key);
}
});
}
});
}
});
}
}
impl AppWindow for InputWindow {
fn viewport_id(&self) -> ViewportId {
ViewportId::from_hash_of("input")
}
fn initial_viewport(&self) -> ViewportBuilder {
ViewportBuilder::default()
.with_title("Bind Inputs")
.with_inner_size((600.0, 400.0))
}
fn show(&mut self, ctx: &Context) {
TopBottomPanel::top("options").show(ctx, |ui| {
ui.horizontal(|ui| {
ui.selectable_value(&mut self.active_tab, InputTab::Player1, "Player 1");
ui.selectable_value(&mut self.active_tab, InputTab::Player2, "Player 2");
});
});
CentralPanel::default().show(ctx, |ui| {
match self.active_tab {
InputTab::Player1 => self.render_key_bindings(ui, SimId::Player1),
InputTab::Player2 => self.render_key_bindings(ui, SimId::Player2),
};
});
}
fn handle_key_event(&mut self, event: &winit::event::KeyEvent) {
if !event.state.is_pressed() {
return;
}
let Some((sim_id, vb)) = self.now_binding.take() else {
return;
};
let mut mappings = self.mappings.for_sim(sim_id).write().unwrap();
mappings.add_keyboard_mapping(vb, event.physical_key);
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
enum InputTab {
Player1,
Player2,
}