wrap input bindings in config struct

This commit is contained in:
Crispy 2025-03-30 17:13:33 +02:00
parent 3548679bbb
commit 031736bea6
6 changed files with 80 additions and 51 deletions

8
src/config.rs Normal file
View file

@ -0,0 +1,8 @@
use serde::{Deserialize, Serialize};
use crate::input::Input;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub input: Input,
}

View file

@ -453,12 +453,12 @@ impl Editor {
pub fn update(&mut self, rl: &RaylibHandle, globals: &mut Globals) {
self.tooltip.init_frame(rl);
self.mouse = MouseInput::get(rl);
if self.popup != Popup::None {
self.mouse.clear();
self.mouse.clear();
if self.popup == Popup::None {
self.mouse.update(rl);
}
if globals.input.is_pressed(ActionId::ToggleMenu) {
if globals.is_pressed(ActionId::ToggleMenu) {
self.popup = match self.popup {
Popup::Success | Popup::Failure => {
self.dismissed_end = true;
@ -496,10 +496,10 @@ impl Editor {
self.step_time = avg_step_time;
self.max_step_time = avg_step_time.max(self.max_step_time);
}
if globals.input.is_pressed(ActionId::StepSim) {
if globals.is_pressed(ActionId::StepSim) {
self.step_pressed()
}
if globals.input.is_pressed(ActionId::StartSim) {
if globals.is_pressed(ActionId::StartSim) {
match self.sim_state {
SimState::Editing => {
self.init_sim();
@ -508,7 +508,7 @@ impl Editor {
SimState::Stepping => self.sim_state = SimState::Running,
SimState::Running => (),
}
} else if globals.input.is_pressed(ActionId::StopSim) {
} else if globals.is_pressed(ActionId::StopSim) {
match self.sim_state {
SimState::Running | SimState::Stepping => {
self.sim_state = SimState::Editing;
@ -557,16 +557,16 @@ impl Editor {
if self.sim_state == SimState::Editing {
if let Some(clipboard) = &mut globals.clipboard {
if globals.input.is_pressed(ActionId::Paste) {
if globals.config.input.is_pressed(ActionId::Paste) {
if let Ok(text) = clipboard.get_text() {
let b = Board::from_user_str(&text);
self.pasting_board = Some(b);
}
}
}
if globals.input.is_pressed(ActionId::Undo) {
if globals.is_pressed(ActionId::Undo) {
self.undo();
} else if globals.input.is_pressed(ActionId::Redo) {
} else if globals.is_pressed(ActionId::Redo) {
self.redo();
}
}
@ -627,7 +627,7 @@ impl Editor {
self.draw_blueprint_sidebar(d, textures);
}
self.mouse = MouseInput::get(d);
self.mouse.update(d);
if self.popup != Popup::None {
self.tooltip.reset();
@ -1044,8 +1044,7 @@ impl Editor {
draw_scaled_texture(d, textures.get("save"), 148, y + 4, 2.);
self.tooltip.add(188, y, 40, 40, "Copy");
if simple_button((d, &self.mouse), 188, y, 40, 40)
|| globals.input.is_pressed(ActionId::Copy)
if simple_button((d, &self.mouse), 188, y, 40, 40) || globals.is_pressed(ActionId::Copy)
{
let board = self.get_selected_as_board(selection);
if let Some(clipboard) = &mut globals.clipboard {

View file

@ -26,13 +26,14 @@ impl Default for Input {
use KeyboardKey::*;
let mut bindings = [(); ActionId::SIZE].map(|_| Vec::new());
let mut bind_key = |action, mods, key| {
bindings[action as usize] = vec![Binding {
bindings[action as usize].push(Binding {
modifiers: mods,
trigger: InputTrigger::Key(key),
}];
});
};
bind_key(ActionId::Undo, vec![KEY_LEFT_CONTROL], KEY_Z);
bind_key(ActionId::Redo, vec![KEY_LEFT_CONTROL], KEY_Y);
bind_key(ActionId::Redo, vec![KEY_LEFT_CONTROL, KEY_LEFT_SHIFT], KEY_Z);
bind_key(ActionId::Copy, vec![KEY_LEFT_CONTROL], KEY_C);
bind_key(ActionId::Paste, vec![KEY_LEFT_CONTROL], KEY_V);
bind_key(ActionId::ToggleMenu, vec![], KEY_ESCAPE);

View file

@ -1,5 +1,6 @@
pub mod blueprint;
pub mod board;
pub mod config;
pub mod editor;
pub mod input;
pub mod level;
@ -10,9 +11,31 @@ pub mod ui;
pub mod util;
use arboard::Clipboard;
use input::Input;
use config::Config;
use input::ActionId;
use raylib::RaylibHandle;
// use util::MouseInput;
pub struct Globals {
pub clipboard: Option<Clipboard>,
pub input: Input,
pub config: Config,
// pub mouse: MouseInput,
}
impl Globals {
pub fn update(&mut self, rl: &RaylibHandle) {
self.config.input.update(rl);
}
pub fn is_pressed(&self, action: ActionId) -> bool {
self.config.input.is_pressed(action)
}
pub fn is_held(&self, action: ActionId) -> bool {
self.config.input.is_held(action)
}
pub fn is_released(&self, action: ActionId) -> bool {
self.config.input.is_released(action)
}
}

View file

@ -32,6 +32,7 @@ struct Game {
level_desc_text: ShapedText,
globals: Globals,
show_settings: bool,
mouse: MouseInput,
}
#[derive(Debug)]
@ -62,12 +63,9 @@ impl Game {
let levels = get_levels();
let solutions = get_solutions();
let config_path = userdata_dir().join(CONFIG_FILE_NAME);
let input = fs::read_to_string(config_path)
let config = fs::read_to_string(config_path)
.ok()
.and_then(|s| {
println!("a");
serde_json::from_str(&s).unwrap()
})
.and_then(|s| serde_json::from_str(&s).ok())
.unwrap_or_default();
Self {
@ -85,16 +83,19 @@ impl Game {
clipboard: Clipboard::new()
.map_err(|e| eprintln!("System clipboard error: {e}"))
.ok(),
input,
config,
// mouse: util::MouseInput::default()
},
show_settings: false,
mouse: MouseInput::default(),
}
}
fn run(&mut self, rl: &mut RaylibHandle, thread: &RaylibThread) {
while !rl.window_should_close() {
let mut d = rl.begin_drawing(thread);
self.globals.input.update(&d);
self.globals.update(&d);
self.mouse.update(&d);
if let Some(editor) = &mut self.open_editor {
editor.update(&d, &mut self.globals);
editor.draw(&mut d, &self.textures, &mut self.globals);
@ -141,10 +142,10 @@ impl Game {
let level_list_width = (d.get_screen_width() / 3).min(400);
let screen_height = d.get_screen_height();
d.draw_rectangle(0, 0, level_list_width, screen_height, BG_MEDIUM);
let mouse = MouseInput::get(d);
if text_button(
d,
&mouse,
&self.mouse,
d.get_screen_width() - 50,
d.get_screen_height() - 40,
40,
@ -156,11 +157,11 @@ impl Game {
const ENTRY_SPACING: i32 = 65;
let fit_on_screen = (d.get_screen_height() / ENTRY_SPACING) as usize;
let max_scroll = self.levels.len().saturating_sub(fit_on_screen);
if mouse.pos().x < level_list_width as f32 {
if mouse.scroll() == Some(Scroll::Down) && self.level_scroll < max_scroll {
if self.mouse.pos().x < level_list_width as f32 {
if self.mouse.scroll() == Some(Scroll::Down) && self.level_scroll < max_scroll {
self.level_scroll += 1;
}
if mouse.scroll() == Some(Scroll::Up) && self.level_scroll > 0 {
if self.mouse.scroll() == Some(Scroll::Up) && self.level_scroll > 0 {
self.level_scroll -= 1;
}
}
@ -174,7 +175,7 @@ impl Game {
width: level_list_width as f32 - 10.,
height: ENTRY_SPACING as f32 - 5.,
};
let clicked_this = mouse.left_click() && mouse.is_over(bounds);
let clicked_this = self.mouse.left_click() && self.mouse.is_over(bounds);
match level {
LevelListEntry::Chapter(title, level_count) => {
d.draw_rectangle_rec(bounds, BG_DARK);
@ -235,7 +236,7 @@ impl Game {
let mut solution_y = y;
for (solution_index, solution) in solutions.iter().enumerate() {
if simple_option_button(
(d, &mouse),
(d, &self.mouse),
rect(
level_list_width + 10,
solution_y,
@ -267,7 +268,7 @@ impl Game {
Color::WHITE,
);
if tex32_button(
(d, &mouse),
(d, &self.mouse),
(level_list_width + entry_width + 15, solution_y + 4),
self.textures.get("cancel"),
(&mut tooltip, "delete"),
@ -280,7 +281,7 @@ impl Game {
let next_id = get_free_id(solutions, Solution::id);
if text_button(
d,
&mouse,
&self.mouse,
level_list_width + 10,
solution_y,
entry_width,
@ -295,12 +296,12 @@ impl Game {
let y = (solution_y + 40).max(240);
let x = level_list_width + 10;
d.draw_text(&text, x, y, 20, Color::ORANGE);
if text_button(d, &mouse, x, y + 30, 100, "yes") {
if text_button(d, &self.mouse, x, y + 30, 100, "yes") {
solutions[i].remove_file();
solutions.remove(i);
self.delete_solution = None;
}
if text_button(d, &mouse, x + 110, y + 30, 100, "no") {
if text_button(d, &self.mouse, x + 110, y + 30, 100, "no") {
self.delete_solution = None;
}
}
@ -310,7 +311,7 @@ impl Game {
let bounds = Rectangle::new(column_x as f32, y as f32, 220., 30.);
if text_input(
d,
&mouse,
&self.mouse,
bounds,
&mut solution.name,
&mut self.editing_solution_name,
@ -322,14 +323,14 @@ impl Game {
let id_text = format!("{}", solution.id());
d.draw_text(&id_text, column_x, y + 35, 10, Color::GRAY);
if text_button(d, &mouse, column_x, y + 50, 220, "clone") {
if text_button(d, &self.mouse, column_x, y + 50, 220, "clone") {
let cloned = solution.new_copy(next_id);
self.selected_solution = solutions.len();
solutions.push(cloned);
return;
}
if text_button(d, &mouse, column_x, y + 85, 220, "edit") {
if text_button(d, &self.mouse, column_x, y + 85, 220, "edit") {
let mut editor = Editor::new(solution.clone(), level.clone());
editor.center_view(d);
self.open_editor = Some(editor);
@ -344,11 +345,10 @@ impl Game {
fn draw_settings(&mut self, d: &mut RaylibDrawHandle) {
d.clear_background(BG_DARK);
let mouse = MouseInput::get(d);
if text_button(d, &mouse, 5, 5, 50, "return") {
if text_button(d, &self.mouse, 5, 5, 50, "return") {
self.show_settings = false;
}
if text_button(d, &mouse, 5, 45, 50, "save") {
if text_button(d, &self.mouse, 5, 45, 50, "save") {
self.save_config();
}
}
@ -356,7 +356,7 @@ impl Game {
fn save_config(&self) {
let path = userdata_dir().join(CONFIG_FILE_NAME);
// todo save more than just input
let json = serde_json::to_string_pretty(&self.globals.input).unwrap();
let json = serde_json::to_string_pretty(&self.globals.config).unwrap();
let mut f = File::create(path).unwrap();
f.write_all(json.as_bytes()).unwrap();
}

View file

@ -84,15 +84,13 @@ pub struct MouseInput {
}
impl MouseInput {
pub fn get(rl: &RaylibHandle) -> Self {
Self {
pos: rl.get_mouse_position(),
left_click: rl.is_mouse_button_pressed(MouseButton::MOUSE_BUTTON_LEFT),
left_hold: rl.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT),
left_release: rl.is_mouse_button_released(MouseButton::MOUSE_BUTTON_LEFT),
right_hold: rl.is_mouse_button_down(MouseButton::MOUSE_BUTTON_RIGHT),
scroll: get_scroll(rl),
}
pub fn update(&mut self, rl: &RaylibHandle) {
self.pos = rl.get_mouse_position();
self.left_click = rl.is_mouse_button_pressed(MouseButton::MOUSE_BUTTON_LEFT);
self.left_hold = rl.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT);
self.left_release = rl.is_mouse_button_released(MouseButton::MOUSE_BUTTON_LEFT);
self.right_hold = rl.is_mouse_button_down(MouseButton::MOUSE_BUTTON_RIGHT);
self.scroll = get_scroll(rl);
}
pub fn is_over(&self, rect: Rectangle) -> bool {