From 49917d18a96dc7a4a127710efdb1a265c0e7a571 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Mon, 7 Oct 2024 15:11:53 +0200 Subject: [PATCH] selection tool (selections are not useful yet) --- README.md | 1 - assets/area_corner.png | Bin 0 -> 109 bytes assets/area_full.png | Bin 0 -> 122 bytes src/editor.rs | 59 ++++++++++++++++++++++++++++++------- src/marble_engine/board.rs | 14 +++++++++ src/solution.rs | 4 --- 6 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 assets/area_corner.png create mode 100644 assets/area_full.png diff --git a/README.md b/README.md index 3814c9e..73522cc 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ logic mostly like https://git.crispypin.cc/CrispyPin/marble ## todo cleanup: unpowered texture names x_off -> x -sim/speed control gui (option) display input as numbers scroll output default i/o text modes specified per level diff --git a/assets/area_corner.png b/assets/area_corner.png new file mode 100644 index 0000000000000000000000000000000000000000..11e3d2be8c6d9c676dfa810c8eba8707d999c320 GIT binary patch literal 109 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`CY~;iAr`&KfBygfU(e>naE2j= z?Qc8No+?gFrCY2|nAE&X_?4J7IN7^m4Wzi6k1=>9F){e)>A&F6cK-s@&*16m=d#Wz Gp$P!FJsk@G literal 0 HcmV?d00001 diff --git a/assets/area_full.png b/assets/area_full.png new file mode 100644 index 0000000000000000000000000000000000000000..d5658a0b019c54b62211df52bdf61601e5223082 GIT binary patch literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`j-D=#Ar`&KfBygfU(e>naE2j= z?Qc6%O_fBVj2jRX=^V>4)@(DFxLT5pt&{Od3$qXZQ9X%XR;?pUUyX!!GBC`vkKa|! Ssn-BBjKR~@&t;ucLK6VFIU`yC literal 0 HcmV?d00001 diff --git a/src/editor.rs b/src/editor.rs index cad2508..dee5324 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -61,7 +61,7 @@ enum Tool { Wire, Arrow, Mirror, - // SelectArea, + SelectArea(Option<(Pos, Pos)>, bool), } #[derive(Debug, Clone, PartialEq)] @@ -123,6 +123,10 @@ impl Editor { self.score.clone() } + fn pos_to_screen(&self, pos: Vector2) -> Vector2 { + pos * (16 << self.zoom) as f32 + self.view_offset + } + fn start_sim(&mut self) { self.machine.reset(); self.machine.set_board(self.source_board.clone()); @@ -196,9 +200,7 @@ impl Editor { WireType::Cross => WireType::Vertical, } } - Tool::None => (), - Tool::SetTile(_) => (), - Tool::Digits(_) => (), + Tool::None | Tool::SetTile(_) | Tool::Digits(_) | Tool::SelectArea(_, _) => (), } } @@ -469,6 +471,7 @@ impl Editor { ); }; tool_button((0, -2), "eraser", Tool::SetTile(Tile::from_char(' '))); + tool_button((1, -2), "selection", Tool::SelectArea(None, false)); tool_button((0, -1), "digit_tool", Tool::Digits(None)); tool_button((1, -1), "transparent", Tool::None); @@ -569,14 +572,16 @@ impl Editor { fn board_overlay(&mut self, d: &mut RaylibDrawHandle, textures: &Textures) { let footer_top = (d.get_screen_height() - FOOTER_HEIGHT) as f32; let mouse_pos = d.get_mouse_position(); + let tile_scale = (1 << self.zoom) as f32; + let tile_size = 16 << self.zoom; if self.sim_state == SimState::Editing { if let Tool::Digits(Some(pos)) = &mut self.active_tool { - let tile_screen_pos = pos.to_vec() * (16 << self.zoom) as f32 + self.view_offset; + let tile_screen_pos = pos.to_vec() * tile_size as f32 + self.view_offset; d.draw_texture_ex( textures.get("selection"), tile_screen_pos, 0., - (1 << self.zoom) as f32, + tile_scale, Color::new(255, 180, 20, 255), ); if d.is_key_pressed(KeyboardKey::KEY_LEFT) { @@ -599,10 +604,10 @@ impl Editor { } } if mouse_pos.y < footer_top && mouse_pos.y > HEADER_HEIGHT as f32 { - let tile_pos = (mouse_pos - self.view_offset) / (16 << self.zoom) as f32; + let tile_pos = (mouse_pos - self.view_offset) / tile_size as f32; let tile_pos = Vector2::new(tile_pos.x.floor(), tile_pos.y.floor()); - let tile_screen_pos = tile_pos * (16 << self.zoom) as f32 + self.view_offset; + let tile_screen_pos = self.pos_to_screen(tile_pos); if self.active_tool != Tool::None { let tex = match self.active_tool { @@ -620,17 +625,18 @@ impl Editor { Tool::Arrow => self.tool_menu_arrow.arrow_texture_name().into(), Tool::Mirror => self.tool_menu_mirror.texture_name().into(), Tool::Digits(_) => "selection".into(), + Tool::SelectArea(_, _) => "area_full".into(), }; d.draw_texture_ex( textures.get(&tex), tile_screen_pos, 0., - (1 << self.zoom) as f32, + tile_scale, Color::new(255, 255, 255, 100), ); } - if d.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT) { + if d.is_mouse_button_pressed(MouseButton::MOUSE_BUTTON_LEFT) { match self.active_tool { Tool::None => (), Tool::SetTile(tile) => self.set_tile(tile_pos.into(), tile), @@ -661,8 +667,40 @@ impl Editor { } } } + Tool::SelectArea(_, _) => (), } } + if let Tool::SelectArea(selection, is_selecting) = &mut self.active_tool { + if d.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT) { + if *is_selecting { + if let Some((_start, end)) = selection { + *end = tile_pos.into(); + } else { + *selection = Some((tile_pos.into(), tile_pos.into())); + } + } else { + *selection = Some((tile_pos.into(), tile_pos.into())); + *is_selecting = true; + } + } else if d.is_mouse_button_released(MouseButton::MOUSE_BUTTON_LEFT) { + *is_selecting = false; + } + } + } + // draw selection + if let Tool::SelectArea(Some((start, end)), _) = self.active_tool { + let min = start.min(end); + let max = start.max(end); + let p_min = self.pos_to_screen(min.to_vec()); + let p_max = self.pos_to_screen(max.to_vec()); + let tex = textures.get("area_corner"); + d.draw_texture_ex(tex, p_min, 0., tile_scale, Color::WHITE); + let one_xy = Vector2::new(tile_size as f32, tile_size as f32); + d.draw_texture_ex(tex, p_max + one_xy, 180., tile_scale, Color::WHITE); + let top_right = Vector2::new(p_max.x + tile_size as f32, p_min.y); + d.draw_texture_ex(tex, top_right, 90., tile_scale, Color::WHITE); + let bot_left = Vector2::new(p_min.x, p_max.y + tile_size as f32); + d.draw_texture_ex(tex, bot_left, -90., tile_scale, Color::WHITE); } } } @@ -673,6 +711,7 @@ impl PartialEq for Tool { match (self, other) { (Self::SetTile(l0), Self::SetTile(r0)) => l0 == r0, (Self::Digits(_), Self::Digits(_)) => true, + (Self::SelectArea(_, _), Self::SelectArea(_, _)) => true, _ => ::core::mem::discriminant(self) == ::core::mem::discriminant(other), } } diff --git a/src/marble_engine/board.rs b/src/marble_engine/board.rs index 80ad250..ea4249f 100644 --- a/src/marble_engine/board.rs +++ b/src/marble_engine/board.rs @@ -16,6 +16,20 @@ impl Pos { y: self.y as f32, } } + + pub fn min(self, other: Self) -> Self { + Self { + x: self.x.min(other.x), + y: self.y.min(other.y), + } + } + + pub fn max(self, other: Self) -> Self { + Self { + x: self.x.max(other.x), + y: self.y.max(other.y), + } + } } impl From<(usize, usize)> for Pos { diff --git a/src/solution.rs b/src/solution.rs index ac55307..06f60ef 100644 --- a/src/solution.rs +++ b/src/solution.rs @@ -45,10 +45,6 @@ impl Solution { file.write_all(json.as_bytes()).unwrap(); } - pub fn level_id(&self) -> &str { - &self.level_id - } - pub fn score_text(&self) -> String { if let Some(score) = &self.score { format!(