From bf82d1455f32f3e70fe371ca8366a87a3b4e8d07 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 5 Oct 2024 17:46:45 +0200 Subject: [PATCH] add more tiles to gui, with controls to rotate between variants in a group --- src/main.rs | 162 ++++++++++++++++++++++++++++++++------ src/marble_engine.rs | 10 +-- src/marble_engine/tile.rs | 95 ++++++++++++---------- 3 files changed, 195 insertions(+), 72 deletions(-) diff --git a/src/main.rs b/src/main.rs index b9c5af7..3e87783 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,12 @@ use std::{ ops::Rem, }; -use marble_engine::{board::Board, parse, tile::Tile, tile_to_char, Machine}; +use marble_engine::{ + board::Board, + parse, + tile::{Direction, GateType, MathOp, MirrorType, PTile, Tile}, + tile_from_char, Machine, +}; use raylib::prelude::*; mod marble_engine; @@ -21,6 +26,10 @@ struct Game { output_as_text: bool, input_as_text: bool, active_tool: Tool, + tool_menu_math: MathOp, + tool_menu_gate: GateType, + tool_menu_arrow: Direction, + tool_menu_mirror: MirrorType, input_text_selected: bool, sim_speed: f32, time_since_step: f32, @@ -30,8 +39,12 @@ struct Game { enum Tool { None, SetTile(Tile), - // Erase, - // Select, + Math, + Gate, + Arrow, + Mirror, + Number, + // SelectArea, } #[derive(Debug, Clone, PartialEq)] @@ -65,6 +78,8 @@ fn main() { .title("good window title") .build(); rl.set_target_fps(60); + rl.set_window_min_size(640, 480); + rl.set_mouse_cursor(MouseCursor::MOUSE_CURSOR_CROSSHAIR); rl.set_exit_key(None); let mut textures: HashMap = HashMap::new(); @@ -97,6 +112,10 @@ impl Game { input_text_selected: false, sim_speed: 8., time_since_step: 0., + tool_menu_math: MathOp::Add, + tool_menu_gate: GateType::Equal, + tool_menu_arrow: Direction::Right, + tool_menu_mirror: MirrorType::Forward, } } @@ -109,6 +128,44 @@ impl Game { self.machine.set_board(self.source_board.clone()); } + fn rotate_tool(&mut self, shift: bool) { + match &self.active_tool { + Tool::Math => { + self.tool_menu_math = match self.tool_menu_math { + MathOp::Add => MathOp::Sub, + MathOp::Sub => MathOp::Mul, + MathOp::Mul => MathOp::Div, + MathOp::Div => MathOp::Rem, + MathOp::Rem => MathOp::Add, + } + } + Tool::Gate => { + self.tool_menu_gate = match self.tool_menu_gate { + GateType::LessThan => GateType::GreaterThan, + GateType::GreaterThan => GateType::Equal, + GateType::Equal => GateType::NotEqual, + GateType::NotEqual => GateType::LessThan, + } + } + Tool::Arrow => { + self.tool_menu_arrow = if shift { + self.tool_menu_arrow.left() + } else { + self.tool_menu_arrow.right() + } + } + Tool::Mirror => { + self.tool_menu_mirror = match self.tool_menu_mirror { + MirrorType::Forward => MirrorType::Back, + MirrorType::Back => MirrorType::Forward, + } + } + Tool::None => (), + Tool::SetTile(_) => (), + Tool::Number => (), + } + } + fn input(&mut self, rl: &RaylibHandle) { if self.sim_state == SimState::Running { self.time_since_step += rl.get_frame_time(); @@ -237,32 +294,53 @@ impl Game { border, ); }; - tool_button((0, -1), "eraser", Tool::SetTile(tile_to_char(' '))); + tool_button((0, -1), "eraser", Tool::SetTile(tile_from_char(' '))); tool_button((1, -1), "", Tool::None); - tool_button((0, 0), "marble", Tool::SetTile(tile_to_char('o'))); - tool_button((0, 1), "block", Tool::SetTile(tile_to_char('#'))); - tool_button((0, 2), "bag_off", Tool::SetTile(tile_to_char('B'))); - tool_button((0, 3), "trigger_off", Tool::SetTile(tile_to_char('*'))); - tool_button((0, 4), "input_off", Tool::SetTile(tile_to_char('I'))); - tool_button((0, 5), "output_off", Tool::SetTile(tile_to_char('P'))); - tool_button((0, 6), "flipper_off", Tool::SetTile(tile_to_char('F'))); + tool_button((0, 0), "marble", Tool::SetTile(tile_from_char('o'))); + tool_button((0, 1), "block", Tool::SetTile(tile_from_char('#'))); + tool_button((0, 2), "bag_off", Tool::SetTile(tile_from_char('B'))); + tool_button((0, 3), "trigger_off", Tool::SetTile(tile_from_char('*'))); + tool_button((0, 4), "input_off", Tool::SetTile(tile_from_char('I'))); + tool_button((0, 5), "output_off", Tool::SetTile(tile_from_char('P'))); + tool_button((0, 6), "flipper_off", Tool::SetTile(tile_from_char('F'))); tool_button( (1, 0), "wire_horizontal_off", - Tool::SetTile(tile_to_char('-')), + Tool::SetTile(tile_from_char('-')), ); tool_button( (1, 1), "wire_vertical_off", - Tool::SetTile(tile_to_char('|')), + Tool::SetTile(tile_from_char('|')), ); - tool_button((1, 2), "wire_cross_off", Tool::SetTile(tile_to_char('+'))); - tool_button((1, 3), "arrow_up", Tool::SetTile(tile_to_char('^'))); - tool_button((1, 4), "arrow_down", Tool::SetTile(tile_to_char('v'))); - tool_button((1, 5), "arrow_left", Tool::SetTile(tile_to_char('<'))); - tool_button((1, 6), "arrow_right", Tool::SetTile(tile_to_char('>'))); + tool_button((1, 2), "wire_cross_off", Tool::SetTile(tile_from_char('+'))); + tool_button( + (1, 3), + &Tile::Arrow(self.tool_menu_arrow).texture(), + Tool::Arrow, + ); + tool_button( + (1, 4), + &Tile::Mirror(self.tool_menu_mirror).texture(), + Tool::Mirror, + ); + tool_button( + (1, 5), + &Tile::Powerable(PTile::Math(self.tool_menu_math), false).texture(), + Tool::Math, + ); + tool_button( + (1, 6), + &Tile::Powerable(PTile::Gate(self.tool_menu_gate), false).texture(), + Tool::Gate, + ); + + let is_shift = d.is_key_down(KeyboardKey::KEY_LEFT_SHIFT); + if d.is_key_pressed(KeyboardKey::KEY_R) { + self.rotate_tool(is_shift); + } let mouse_pos = d.get_mouse_position(); if self.sim_state == SimState::Editing && mouse_pos.y < footer_top { @@ -271,17 +349,53 @@ impl Game { let tile_screen_pos = tile_pos * (16 << self.zoom) as f32 + self.view_offset; - if let Tool::SetTile(tile) = self.active_tool { + if self.active_tool != Tool::None { + let tex = match self.active_tool { + Tool::None => unreachable!(), + Tool::SetTile(t) => { + if t == Tile::Blank { + "selection".into() + } else { + t.texture() + } + } + Tool::Math => format!("{}_off",self.tool_menu_math.texture_name()), + Tool::Gate => format!("{}_off",self.tool_menu_gate.texture_name()), + Tool::Arrow => self.tool_menu_arrow.arrow_texture_name().into(), + Tool::Mirror => self.tool_menu_mirror.texture_name().into(), + Tool::Number => todo!(), + }; + + let tex = textures + .get(&tex) + .unwrap_or_else(|| textures.get("missing").unwrap()); d.draw_texture_ex( - textures.get("selection").unwrap(), + tex, tile_screen_pos, 0., (1 << self.zoom) as f32, - Color::new(255, 255, 255, 150), + Color::new(255, 255, 255, 100), ); - - if d.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT) { - self.source_board.set(tile_pos.into(), tile) + } + if d.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT) { + match self.active_tool { + Tool::None => (), + Tool::SetTile(tile) => self.source_board.set(tile_pos.into(), tile), + Tool::Math => self.source_board.set( + tile_pos.into(), + Tile::Powerable(PTile::Math(self.tool_menu_math), false), + ), + Tool::Gate => self.source_board.set( + tile_pos.into(), + Tile::Powerable(PTile::Gate(self.tool_menu_gate), false), + ), + Tool::Arrow => self + .source_board + .set(tile_pos.into(), Tile::Arrow(self.tool_menu_arrow)), + Tool::Mirror => self + .source_board + .set(tile_pos.into(), Tile::Mirror(self.tool_menu_mirror)), + Tool::Number => todo!(), } } } diff --git a/src/marble_engine.rs b/src/marble_engine.rs index 3e439a7..e82848d 100644 --- a/src/marble_engine.rs +++ b/src/marble_engine.rs @@ -58,10 +58,6 @@ impl Machine { &self.input } - pub fn input_mut(&mut self) -> &mut Vec { - &mut self.input - } - pub fn set_input(&mut self, bytes: Vec) { self.input_index = self.input_index.min(bytes.len()); self.input = bytes; @@ -327,7 +323,7 @@ pub fn parse(source: &str) -> Board { width = width.max(line.len()); let mut tiles = Vec::new(); for char in line.chars() { - tiles.push(tile_to_char(char)); + tiles.push(tile_from_char(char)); } rows.push(tiles); } @@ -338,7 +334,7 @@ pub fn parse(source: &str) -> Board { Board::new(rows) } -pub const fn tile_to_char(c: char) -> Tile { +pub const fn tile_from_char(c: char) -> Tile { match c { 'o' => Tile::Marble { value: 0, @@ -367,7 +363,7 @@ pub const fn tile_to_char(c: char) -> Tile { 'D' => Tile::Powerable(PTile::Math(MathOp::Div), false), 'R' => Tile::Powerable(PTile::Math(MathOp::Rem), false), 'B' => Tile::Powerable(PTile::Bag, false), - d @ '0'..='9' => Tile::Digit(d as u8), + d @ '0'..='9' => Tile::Digit(d as u8 - b'0'), '#' => Tile::Block, ' ' => Tile::Blank, _ => Tile::Blank, diff --git a/src/marble_engine/tile.rs b/src/marble_engine/tile.rs index 11df1ab..a8abcd1 100644 --- a/src/marble_engine/tile.rs +++ b/src/marble_engine/tile.rs @@ -85,50 +85,15 @@ impl Tile { Tile::Blank => "transparent", Tile::Block => "block", Tile::Marble { value: _, dir: _ } => "marble", - Tile::Digit(n) => match n { - b'0' => "digit_0", - b'1' => "digit_1", - b'2' => "digit_2", - b'3' => "digit_3", - b'4' => "digit_4", - b'5' => "digit_5", - b'6' => "digit_6", - b'7' => "digit_7", - b'8' => "digit_8", - b'9' => "digit_9", - _ => unreachable!("invalid digit"), - }, - Tile::Mirror(mirror) => match mirror { - MirrorType::Forward => "mirror_forward", - MirrorType::Back => "mirror_back", - }, - Tile::Arrow(dir) => match dir { - Direction::Up => "arrow_up", - Direction::Down => "arrow_down", - Direction::Left => "arrow_left", - Direction::Right => "arrow_right", - }, + Tile::Digit(n) => return format!("digit_{n}"), + Tile::Mirror(mirror) => mirror.texture_name(), + Tile::Arrow(dir) => dir.arrow_texture_name(), Tile::Powerable(tile, state) => { let root = match tile { PTile::Trigger => "trigger", - PTile::Wire(wire) => match wire { - WireType::Vertical => "wire_vertical", - WireType::Horizontal => "wire_horizontal", - WireType::Cross => "wire_cross", - }, - PTile::Gate(gate) => match gate { - GateType::LessThan => "lt", - GateType::GreaterThan => "gt", - GateType::Equal => "eq", - GateType::NotEqual => "neq", - }, - PTile::Math(math_op) => match math_op { - MathOp::Add => "add", - MathOp::Sub => "sub", - MathOp::Mul => "mul", - MathOp::Div => "div", - MathOp::Rem => "rem", - }, + PTile::Wire(wire) => wire.texture_name(), + PTile::Gate(gate) => gate.texture_name(), + PTile::Math(math_op) => math_op.texture_name(), PTile::Bag => "bag", PTile::Flipper => "flipper", PTile::Input => "input", @@ -180,6 +145,15 @@ impl Direction { } pos } + + pub const fn arrow_texture_name(&self) -> &'static str { + match self { + Direction::Up => "arrow_up", + Direction::Down => "arrow_down", + Direction::Left => "arrow_left", + Direction::Right => "arrow_right", + } + } } impl WireType { @@ -190,6 +164,14 @@ impl WireType { WireType::Cross => &Direction::ALL, } } + + pub const fn texture_name(&self) -> &'static str { + match self { + WireType::Vertical => "wire_vertical", + WireType::Horizontal => "wire_horizontal", + WireType::Cross => "wire_cross", + } + } } impl MirrorType { @@ -209,4 +191,35 @@ impl MirrorType { }, } } + + pub const fn texture_name(&self) -> &'static str { + match self { + MirrorType::Forward => "mirror_forward", + MirrorType::Back => "mirror_back", + } + } +} + +impl MathOp { + pub const fn texture_name(&self) -> &'static str { + match self { + MathOp::Add => "add", + MathOp::Sub => "sub", + MathOp::Mul => "mul", + MathOp::Div => "div", + MathOp::Rem => "rem", + } + } +} + +impl GateType { + pub const fn texture_name(&self) -> &'static str { + match self { + GateType::LessThan => "lt", + GateType::GreaterThan => "gt", + GateType::Equal => "eq", + GateType::NotEqual => "neq", + } + } + }