diff --git a/CHANGELOG.md b/CHANGELOG.md index f1a4c48..fc9425d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Game store page: https://crispypin.itch.io/marble-machinations ## [unreleased] ### fixed +- keybindings activated even when typing in a text field, making especially renaming blueprints difficult - after removing a binding that was a superset of another, the remaining one did not stop being blocked by the removed ones additional modifiers until another binding was added or edited ## v0.3.2 - 2025-04-14 diff --git a/README.md b/README.md index 4808bb9..f873cb3 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ logic mostly like https://git.crispypin.cc/CrispyPin/marble ## todo ### meta - engine tests -- blag post about marble movement logic +- blag post about marble movement logic? ### bugs -- modifier-less bindings trigger when typing in a text box, makes renaming existing blueprints basically impossible + ### features #### 0.3.x - more levels diff --git a/src/editor.rs b/src/editor.rs index f8fa6a1..ac41159 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -574,27 +574,35 @@ impl Editor { } } - fn draw_board(&self, d: &mut RaylibDrawHandle, textures: &Textures) { + fn draw_board(&self, d: &mut RaylibDrawHandle, globals: &Globals) { if self.sim_state == SimState::Editing { self.source_board .grid - .draw(d, textures, self.view_offset, self.zoom); + .draw(d, &globals.textures, self.view_offset, self.zoom); } else { if self.machine.debug_subticks.is_empty() { self.machine .grid() - .draw(d, textures, self.view_offset, self.zoom); + .draw(d, &globals.textures, self.view_offset, self.zoom); } else { let subframe = &self.machine.debug_subticks[self.machine.subtick_index]; - subframe.grid.draw(d, textures, self.view_offset, self.zoom); + subframe + .grid + .draw(d, &globals.textures, self.view_offset, self.zoom); if let Some(pos) = subframe.pos { let p = self.pos_to_screen(pos.to_vec()); - d.draw_texture_ex(textures.get("selection"), p, 0., self.zoom, Color::ORANGE); + d.draw_texture_ex( + globals.get_tex("selection"), + p, + 0., + self.zoom, + Color::ORANGE, + ); } } if self.draw_overlay { self.machine - .draw_marble_values(d, textures, self.view_offset, self.zoom); + .draw_marble_values(d, &globals.textures, self.view_offset, self.zoom); } } if self.draw_overlay { @@ -620,13 +628,13 @@ impl Editor { } } - self.draw_board(d, &globals.textures); - self.board_overlay(d, &globals.textures); + self.draw_board(d, globals); + self.board_overlay(d, globals); self.draw_bottom_bar(d, globals); self.draw_top_bar(d, globals); if self.active_tool == Tool::Blueprint { - self.draw_blueprint_sidebar(d, &globals.textures); + self.draw_blueprint_sidebar(d, globals); } self.mouse.update(d); @@ -676,7 +684,7 @@ impl Editor { self.tooltip.draw(d); } - fn draw_blueprint_sidebar(&mut self, d: &mut RaylibDrawHandle, textures: &Textures) { + fn draw_blueprint_sidebar(&mut self, d: &mut RaylibDrawHandle, globals: &mut Globals) { let sidebar_height = d.get_screen_height() - FOOTER_HEIGHT - HEADER_HEIGHT - 40; d.draw_rectangle( 0, @@ -700,7 +708,7 @@ impl Editor { if tex32_button( (d, &self.mouse), (5, y), - textures.get("rubbish"), + globals.get_tex("rubbish"), (&mut self.tooltip, "Delete"), ) { b.remove_file(); @@ -711,7 +719,7 @@ impl Editor { let mut text_selected = is_selected && self.blueprint_name_selected; text_input( d, - &self.mouse, + globals, Rectangle::new(42., y as f32, 200., 32.), &mut b.name, &mut text_selected, @@ -730,7 +738,7 @@ impl Editor { ); d.draw_texture_ex( - textures.get("blueprint"), + globals.get_tex("blueprint"), Vector2::new((42 + 205) as f32, y as f32), 0., 2., @@ -789,8 +797,7 @@ impl Editor { } } - fn draw_top_bar(&mut self, d: &mut RaylibDrawHandle, globals: &Globals) { - let textures = &globals.textures; + fn draw_top_bar(&mut self, d: &mut RaylibDrawHandle, globals: &mut Globals) { // background d.draw_rectangle( 0, @@ -803,7 +810,7 @@ impl Editor { if tex32_button( (d, &self.mouse), (4, 4), - textures.get("exit"), + globals.get_tex("exit"), (&mut self.tooltip, "exit"), ) { if self.exit_menu { @@ -816,7 +823,7 @@ impl Editor { if tex32_button( (d, &self.mouse), (40, 4), - textures.get("cancel"), + globals.get_tex("cancel"), (&mut self.tooltip, "cancel"), ) { self.exit_menu = false; @@ -824,7 +831,7 @@ impl Editor { } else if tex32_button( (d, &self.mouse), (40, 4), - textures.get("save"), + globals.get_tex("save"), (&mut self.tooltip, "save"), ) || globals.is_pressed(ActionId::Save) { @@ -844,7 +851,7 @@ impl Editor { if tex32_button( (d, &self.mouse), (150, 4), - textures.get(undo_icon), + globals.get_tex(undo_icon), (&mut self.tooltip, "Undo"), ) { self.undo() @@ -858,7 +865,7 @@ impl Editor { if tex32_button( (d, &self.mouse), (186, 4), - textures.get(redo_icon), + globals.get_tex(redo_icon), (&mut self.tooltip, "Redo"), ) { self.redo() @@ -873,7 +880,7 @@ impl Editor { if tex32_button( (d, &self.mouse), (223, 4), - textures.get(overlay_btn_icon), + globals.get_tex(overlay_btn_icon), (&mut self.tooltip, "Toggle overlay"), ) { self.draw_overlay = !self.draw_overlay; @@ -883,7 +890,7 @@ impl Editor { if tex32_button( (d, &self.mouse), (260, 4), - textures.get("pause"), + globals.get_tex("pause"), (&mut self.tooltip, "Pause"), ) { self.sim_state = SimState::Stepping; @@ -891,7 +898,7 @@ impl Editor { } else if tex32_button( (d, &self.mouse), (260, 4), - textures.get("play"), + globals.get_tex("play"), (&mut self.tooltip, "Start"), ) { if self.sim_state == SimState::Editing { @@ -904,7 +911,7 @@ impl Editor { && tex32_button( (d, &self.mouse), (296, 4), - textures.get("stop"), + globals.get_tex("stop"), (&mut self.tooltip, "Stop"), ) { self.sim_state = SimState::Editing; @@ -914,14 +921,21 @@ impl Editor { if tex32_button( (d, &self.mouse), (332, 4), - textures.get("step"), + globals.get_tex("step"), (&mut self.tooltip, "Step"), ) { self.step_pressed(); } self.tooltip.add(368, 4, 48, 32, "Speed"); - draw_usize(d, textures, 1 << self.sim_speed, (368, 4), SPEED_DIGITS, 1); + draw_usize( + d, + &globals.textures, + 1 << self.sim_speed, + (368, 4), + SPEED_DIGITS, + 1, + ); slider( (d, &self.mouse), rect(368, 24, 48, 12), @@ -931,20 +945,48 @@ impl Editor { ); self.tooltip.add(420, 4, 180, 32, "Steps"); - draw_usize(d, textures, self.machine.step_count(), (420, 4), 9, 2); + draw_usize( + d, + &globals.textures, + self.machine.step_count(), + (420, 4), + 9, + 2, + ); if self.stage > Some(0) { self.tooltip.add(420, 44, 180, 32, "Total steps"); let total_steps = self.total_steps + self.machine.step_count(); - draw_usize(d, textures, total_steps, (420, 44), 9, 2); + draw_usize(d, &globals.textures, total_steps, (420, 44), 9, 2); } - draw_usize(d, textures, self.step_time as usize, (260, 42), 9, 1); - draw_usize(d, textures, self.max_step_time as usize, (260, 60), 9, 1); + draw_usize( + d, + &globals.textures, + self.step_time as usize, + (260, 42), + 9, + 1, + ); + draw_usize( + d, + &globals.textures, + self.max_step_time as usize, + (260, 60), + 9, + 1, + ); #[cfg(debug_assertions)] { - draw_usize(d, textures, self.machine.subtick_index, (260, 80), 9, 1); + draw_usize( + d, + &globals.textures, + self.machine.subtick_index, + (260, 80), + 9, + 1, + ); let subtick_count = self.machine.debug_subticks.len(); - draw_usize(d, textures, subtick_count, (260, 100), 9, 1); + draw_usize(d, &globals.textures, subtick_count, (260, 100), 9, 1); } d.draw_text("input:", 603, 8, 10, Color::WHITE); @@ -967,7 +1009,7 @@ impl Editor { } if text_input( d, - &self.mouse, + globals, Rectangle::new(input_x as f32, 5., (width - input_x - 5) as f32, 30.), &mut input_text, &mut self.input_text_selected, @@ -1021,7 +1063,7 @@ impl Editor { hide_tile_tools = true; text_input( d, - &self.mouse, + globals, Rectangle::new(100., footer_top + 10., 240., 30.), &mut self.new_blueprint_name, &mut self.blueprint_name_selected, @@ -1317,7 +1359,7 @@ impl Editor { } } - fn board_overlay(&mut self, d: &mut RaylibDrawHandle, textures: &Textures) { + fn board_overlay(&mut self, d: &mut RaylibDrawHandle, globals: &Globals) { let footer_top = (d.get_screen_height() - FOOTER_HEIGHT) as f32; let tile_size = TILE_TEXTURE_SIZE * self.zoom; @@ -1336,7 +1378,7 @@ impl Editor { offset.x -= offset.x.rem(tile_size); offset.y -= offset.y.rem(tile_size); offset += view_offset; - board.grid.draw(d, textures, offset, self.zoom); + board.grid.draw(d, &globals.textures, offset, self.zoom); board.draw_comments(d, offset, self.zoom); if self.mouse.left_click() { let tile_pos = (self.mouse.pos() - self.view_offset) / tile_size; @@ -1350,7 +1392,7 @@ impl Editor { if let Tool::Digits(Some(pos)) = &mut self.active_tool { let tile_screen_pos = pos.to_vec() * tile_size + self.view_offset; d.draw_texture_ex( - textures.get("selection"), + globals.get_tex("selection"), tile_screen_pos, 0., self.zoom, @@ -1403,7 +1445,7 @@ impl Editor { }; d.draw_texture_ex( - textures.get(tex), + globals.get_tex(tex), tile_screen_pos, 0., self.zoom, @@ -1473,7 +1515,7 @@ impl Editor { offset.x -= offset.x.rem(tile_size); offset.y -= offset.y.rem(tile_size); offset += view_offset; - bp.board.grid.draw(d, textures, offset, self.zoom); + bp.board.grid.draw(d, &globals.textures, offset, self.zoom); bp.board.draw_comments(d, offset, self.zoom); } if self.mouse.pos().x < SIDEBAR_WIDTH as f32 { diff --git a/src/input.rs b/src/input.rs index 927790d..b8e3f6b 100644 --- a/src/input.rs +++ b/src/input.rs @@ -97,6 +97,7 @@ impl Default for Input { bindings, states: Default::default(), editing_binding: None, + in_text_edit: false, } } } @@ -118,6 +119,7 @@ pub struct Input { bindings: [Vec; ActionId::SIZE], states: [BindingState; ActionId::SIZE], editing_binding: Option<(ActionId, usize, BindingEdit)>, + pub in_text_edit: bool, } #[derive(Clone, Debug)] @@ -284,11 +286,13 @@ impl Input { for i in 0..ActionId::SIZE { let bindings = &self.bindings[i]; let mut is_active = false; - for binding in bindings { - if binding.modifiers.iter().all(|&m| m.is_down(rl)) - && !binding.blocking_modifiers.iter().any(|&m| m.is_down(rl)) - { - is_active |= binding.trigger.is_down(rl); + if !self.in_text_edit { + for binding in bindings { + if binding.modifiers.iter().all(|&m| m.is_down(rl)) + && !binding.blocking_modifiers.iter().any(|&m| m.is_down(rl)) + { + is_active |= binding.trigger.is_down(rl); + } } } let state = &mut self.states[i]; @@ -304,6 +308,7 @@ impl Input { } } } + self.in_text_edit = false; } pub fn is_pressed(&self, action: ActionId) -> bool { diff --git a/src/main.rs b/src/main.rs index 6d0e32c..c0978e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -315,7 +315,7 @@ impl Game { let bounds = Rectangle::new(column_x as f32, y as f32, 220., 30.); if text_input( d, - &self.globals.mouse, + &mut self.globals, bounds, &mut solution.name, &mut self.editing_solution_name, diff --git a/src/ui.rs b/src/ui.rs index 32c80f0..47199b0 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,6 +1,10 @@ use std::ops::Range; -use crate::{theme::*, util::draw_scaled_texture, util::MouseInput, util::Scroll, util::Textures}; +use crate::{ + theme::*, + util::{draw_scaled_texture, MouseInput, Scroll, Textures}, + Globals, +}; use raylib::prelude::*; #[derive(Debug)] @@ -225,7 +229,7 @@ where pub fn text_input( d: &mut RaylibDrawHandle, - mouse: &MouseInput, + globals: &mut Globals, bounds: Rectangle, text: &mut String, is_selected: &mut bool, @@ -262,12 +266,13 @@ pub fn text_input( Color::WHITE, ); }; - if editable && mouse.left_click() && (mouse.is_over(bounds) || *is_selected) { + if editable && globals.mouse.left_click() && (globals.mouse.is_over(bounds) || *is_selected) { *is_selected = !*is_selected; } if *is_selected { - if d.is_key_pressed(KeyboardKey::KEY_ESCAPE) { + globals.config.input.in_text_edit = true; + if d.is_key_pressed(KeyboardKey::KEY_ESCAPE) || d.is_key_pressed(KeyboardKey::KEY_ENTER) { *is_selected = false; } if d.is_key_pressed(KeyboardKey::KEY_BACKSPACE) && !text.is_empty() {