use super::Tool; use crate::button::Button; use crate::config::{ToolKeybindings, WallToolKeybindings}; use crate::grid::{snap_to_grid, SNAP_SIZE}; use crate::map_data::MapData; use crate::math::Vec2; use crate::transform::Transform; use raylib::core::drawing::{RaylibDraw, RaylibDrawHandle}; use raylib::ffi::{Color, Vector2}; use raylib::RaylibHandle; pub struct WallTool { keybindings: WallToolKeybindings, unfinished_wall: Option<(Vec2, Vec2)>, } impl WallTool { pub fn new(keybindings: WallToolKeybindings) -> Self { Self { keybindings, unfinished_wall: None, } } } impl Tool for WallTool { fn deactivate(&mut self) { self.unfinished_wall = None; } fn active_update( &mut self, map_data: &mut MapData, rl: &RaylibHandle, transform: &Transform, mouse_blocked: bool, ) { let mouse_pos_m = transform.point_px_to_m(&rl.get_mouse_position().into()); if let Some((_, ref mut pos2)) = &mut self.unfinished_wall { *pos2 = snap_to_grid(mouse_pos_m, SNAP_SIZE); } if self .keybindings .finish_segment .is_pressed(rl, mouse_blocked) && self.unfinished_wall.is_some() { let (pos1, pos2) = self.unfinished_wall.unwrap(); map_data.walls_mut().push((pos1, pos2)); self.unfinished_wall = Some((pos2, pos2)); } else if self.keybindings.start_wall.is_pressed(rl, mouse_blocked) { let snapped_mouse_pos = snap_to_grid(mouse_pos_m, SNAP_SIZE); self.unfinished_wall = Some((snapped_mouse_pos, snapped_mouse_pos)) } if self.keybindings.abort_segment.is_pressed(rl, false) { self.unfinished_wall = None; } } fn draw(&self, map_data: &MapData, rld: &mut RaylibDrawHandle, transform: &Transform) { for &(pos1, pos2) in map_data.walls() { let pos1_px = transform.point_m_to_px(pos1); let pos2_px = transform.point_m_to_px(pos2); rld.draw_line_ex( pos1_px, pos2_px, transform.length_m_to_px(0.1), Color { r: 200, g: 120, b: 120, a: 255, }, ); /* Find walls that end/start at the start or end of this wall and draw part of a circle * to join these two walls more nicely. */ for &(other1, other2) in map_data.walls() { // Ignore the line segment if it's the same wall if pos1 == other1 && pos2 == other2 { continue; } // TODO: Only draw segments when introducing transparency. for pos in [pos1, pos2].iter() { if *pos == other1 || *pos == other2 { rld.draw_circle_v( transform.point_m_to_px(*pos), transform.length_m_to_px(0.05), Color { r: 200, g: 120, b: 120, a: 255, }, ); } } } } if let Some((pos1, pos2)) = self.unfinished_wall { let pos1: Vector2 = transform.point_m_to_px(&pos1).into(); let pos2: Vector2 = transform.point_m_to_px(&pos2).into(); rld.draw_line_ex( pos1, pos2, transform.length_m_to_px(0.1) as f32, Color { r: 150, g: 200, b: 150, a: 255, }, ); } } fn activation_key(&self) -> Button { self.keybindings.activation_key() } }