list bindings in settings menu, allow deleting bindings

This commit is contained in:
Crispy 2025-03-30 21:27:21 +02:00
parent be699aa0ec
commit 14edee5a53
5 changed files with 106 additions and 44 deletions

View file

@ -1,8 +1,36 @@
use raylib::prelude::*;
use serde::{Deserialize, Serialize};
use crate::input::Input;
use crate::{input::Input, theme::FG_CHAPTER_TITLE, ui::text_button, Globals};
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub input: Input,
}
pub enum MenuReturn {
Stay,
StaySave,
ReturnSave,
ReturnCancel,
}
impl Config {
#[must_use]
pub fn draw_edit(&mut self, d: &mut RaylibDrawHandle, globals: &Globals) -> MenuReturn {
d.draw_text("Settings", 16, 16, 30, FG_CHAPTER_TITLE);
if text_button(d, &globals.mouse, 10, 60, 80, "apply") {
return MenuReturn::StaySave;
}
if text_button(d, &globals.mouse, 100, 60, 80, "done") {
return MenuReturn::ReturnSave;
}
if text_button(d, &globals.mouse, 190, 60, 80, "cancel") {
return MenuReturn::ReturnCancel;
}
self.input.draw_edit(d, globals);
MenuReturn::Stay
}
}

View file

@ -893,16 +893,15 @@ impl Editor {
self.sim_state = SimState::Running;
}
if self.sim_state != SimState::Editing {
if tex32_button(
if self.sim_state != SimState::Editing
&& tex32_button(
(d, &self.mouse),
(296, 4),
textures.get("stop"),
(&mut self.tooltip, "Stop"),
) {
self.sim_state = SimState::Editing;
self.popup = Popup::None;
}
self.sim_state = SimState::Editing;
self.popup = Popup::None;
}
if tex32_button(

View file

@ -1,11 +1,15 @@
use std::{collections::BTreeMap, mem::transmute};
use raylib::{
color::Color,
drawing::{RaylibDraw, RaylibDrawHandle},
ffi::{KeyboardKey, MouseButton},
RaylibHandle,
};
use serde::{Deserialize, Serialize};
use crate::{ui::text_button, Globals};
#[derive(Debug, Clone, Copy, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u8)]
pub enum ActionId {
@ -33,7 +37,11 @@ impl Default for Input {
};
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::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);
@ -67,6 +75,30 @@ pub struct Input {
}
impl Input {
pub fn draw_edit(&mut self, d: &mut RaylibDrawHandle, globals: &Globals) {
let mut y = 96;
for action_index in 0..ActionId::SIZE {
let action = ActionId::from_usize(action_index).unwrap();
d.draw_text(&format!("{action:?}"), 16, y, 20, Color::ORANGE);
if self.bindings[action_index].is_empty() {
y += 32;
}
for (binding_index, binding) in self.bindings[action_index].iter().enumerate() {
if text_button(d, &globals.mouse, 160, y, 80, "remove") {
self.bindings[action_index].remove(binding_index);
return;
}
let trigger = format!("{:?}", binding.trigger);
d.draw_text(&trigger, 256, y, 20, Color::LIMEGREEN);
let x = 264 + d.measure_text(&trigger, 20);
let modifiers = format!("{:?}", binding.modifiers);
d.draw_text(&modifiers, x, y, 20, Color::LIGHTBLUE);
y += 32;
}
}
}
pub fn update(&mut self, rl: &RaylibHandle) {
for i in 0..ActionId::SIZE {
let bindings = &self.bindings[i];

View file

@ -16,7 +16,7 @@ use arboard::Clipboard;
use config::Config;
use input::ActionId;
use raylib::{texture::Texture2D, RaylibHandle};
use util::{userdata_dir, Textures};
use util::{userdata_dir, MouseInput, Textures};
// use util::MouseInput;
pub const CONFIG_FILE_NAME: &str = "config.json";
@ -25,7 +25,7 @@ pub struct Globals {
pub clipboard: Option<Clipboard>,
pub config: Config,
textures: Textures,
// pub mouse: MouseInput,
pub mouse: MouseInput,
}
impl Globals {
@ -47,12 +47,13 @@ impl Globals {
.ok(),
config,
textures,
// mouse: util::MouseInput::default()
mouse: MouseInput::default(),
}
}
pub fn update(&mut self, rl: &RaylibHandle) {
self.config.input.update(rl);
self.mouse.update(rl);
}
pub fn is_pressed(&self, action: ActionId) -> bool {

View file

@ -8,6 +8,7 @@ use raylib::prelude::*;
use marble_machinations::*;
use config::Config;
use editor::{Editor, ExitState};
use level::{Chapter, Level};
use solution::Solution;
@ -28,8 +29,7 @@ struct Game {
editing_solution_name: bool,
level_desc_text: ShapedText,
globals: Globals,
show_settings: bool,
mouse: MouseInput,
edit_settings: Option<Config>,
}
#[derive(Debug)]
@ -66,8 +66,7 @@ impl Game {
editing_solution_name: false,
level_desc_text: ShapedText::new(20),
globals: Globals::new(rl, thread),
show_settings: false,
mouse: MouseInput::default(),
edit_settings: None,
}
}
@ -75,7 +74,6 @@ impl Game {
while !rl.window_should_close() {
let mut d = rl.begin_drawing(thread);
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, &mut self.globals);
@ -97,8 +95,21 @@ impl Game {
solution.save();
}
}
} else if self.show_settings {
self.draw_settings(&mut d);
} else if let Some(config) = &mut self.edit_settings {
d.clear_background(BG_DARK);
match config.draw_edit(&mut d, &self.globals) {
config::MenuReturn::Stay => (),
config::MenuReturn::StaySave => {
self.globals.config = config.clone();
self.save_config();
}
config::MenuReturn::ReturnSave => {
self.globals.config = config.clone();
self.save_config();
self.edit_settings = None;
}
config::MenuReturn::ReturnCancel => self.edit_settings = None,
}
} else {
self.draw(&mut d);
}
@ -125,23 +136,23 @@ impl Game {
if text_button(
d,
&self.mouse,
d.get_screen_width() - 50,
d.get_screen_height() - 40,
40,
&self.globals.mouse,
d.get_screen_width() - 100,
d.get_screen_height() - 70,
90,
"settings",
) {
self.show_settings = true;
self.edit_settings = Some(self.globals.config.clone());
}
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 self.mouse.pos().x < level_list_width as f32 {
if self.mouse.scroll() == Some(Scroll::Down) && self.level_scroll < max_scroll {
if self.globals.mouse.pos().x < level_list_width as f32 {
if self.globals.mouse.scroll() == Some(Scroll::Down) && self.level_scroll < max_scroll {
self.level_scroll += 1;
}
if self.mouse.scroll() == Some(Scroll::Up) && self.level_scroll > 0 {
if self.globals.mouse.scroll() == Some(Scroll::Up) && self.level_scroll > 0 {
self.level_scroll -= 1;
}
}
@ -155,7 +166,8 @@ impl Game {
width: level_list_width as f32 - 10.,
height: ENTRY_SPACING as f32 - 5.,
};
let clicked_this = self.mouse.left_click() && self.mouse.is_over(bounds);
let clicked_this =
self.globals.mouse.left_click() && self.globals.mouse.is_over(bounds);
match level {
LevelListEntry::Chapter(title, level_count) => {
d.draw_rectangle_rec(bounds, BG_DARK);
@ -216,7 +228,7 @@ impl Game {
let mut solution_y = y;
for (solution_index, solution) in solutions.iter().enumerate() {
if simple_option_button(
(d, &self.mouse),
(d, &self.globals.mouse),
rect(
level_list_width + 10,
solution_y,
@ -248,7 +260,7 @@ impl Game {
Color::WHITE,
);
if tex32_button(
(d, &self.mouse),
(d, &self.globals.mouse),
(level_list_width + entry_width + 15, solution_y + 4),
self.globals.get_tex("cancel"),
(&mut tooltip, "delete"),
@ -261,7 +273,7 @@ impl Game {
let next_id = get_free_id(solutions, Solution::id);
if text_button(
d,
&self.mouse,
&self.globals.mouse,
level_list_width + 10,
solution_y,
entry_width,
@ -276,12 +288,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, &self.mouse, x, y + 30, 100, "yes") {
if text_button(d, &self.globals.mouse, x, y + 30, 100, "yes") {
solutions[i].remove_file();
solutions.remove(i);
self.delete_solution = None;
}
if text_button(d, &self.mouse, x + 110, y + 30, 100, "no") {
if text_button(d, &self.globals.mouse, x + 110, y + 30, 100, "no") {
self.delete_solution = None;
}
}
@ -291,7 +303,7 @@ impl Game {
let bounds = Rectangle::new(column_x as f32, y as f32, 220., 30.);
if text_input(
d,
&self.mouse,
&self.globals.mouse,
bounds,
&mut solution.name,
&mut self.editing_solution_name,
@ -303,14 +315,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, &self.mouse, column_x, y + 50, 220, "clone") {
if text_button(d, &self.globals.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, &self.mouse, column_x, y + 85, 220, "edit") {
if text_button(d, &self.globals.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);
@ -323,16 +335,6 @@ impl Game {
tooltip.draw(d);
}
fn draw_settings(&mut self, d: &mut RaylibDrawHandle) {
d.clear_background(BG_DARK);
if text_button(d, &self.mouse, 5, 5, 50, "return") {
self.show_settings = false;
}
if text_button(d, &self.mouse, 5, 45, 50, "save") {
self.save_config();
}
}
fn save_config(&self) {
let path = userdata_dir().join(CONFIG_FILE_NAME);
let json = serde_json::to_string_pretty(&self.globals.config).unwrap();