use crate::button::{Button, MouseButton}; use crate::config::Config; use crate::map::Map; use crate::tool::*; use crate::transform::Transform; use raylib::core::drawing::RaylibDrawHandle; use raylib::{RaylibHandle, RaylibThread}; use std::collections::HashMap; use crate::grid::{snap_to_grid, SNAP_SIZE}; pub struct Editor { map: Map, /// HashMap that matches the ToolType with its proper activation key and of course the tool /// itself. tools: HashMap, Button)>, active: ToolType, config: Config } impl Editor { pub fn new(rl: &mut RaylibHandle, rlt: &RaylibThread, config: Config) -> Self { let map = Map::new(rl, rlt); let mut tools: HashMap, Button)> = HashMap::with_capacity(ToolType::NumTools as usize); tools.insert( ToolType::RectRoomTool, ( Box::new(RectRoomTool::new()), config.tool_activation_keys.rect_room, ), ); tools.insert( ToolType::PolygonRoomTool, ( Box::new(PolygonRoomTool::new()), config.tool_activation_keys.polygon_room, ), ); tools.insert( ToolType::WallTool, (Box::new(WallTool::new()), config.tool_activation_keys.wall), ); tools.insert( ToolType::IconTool, ( Box::new(IconTool::new(config.icon_keys.clone(), map.icon_renderer())), config.tool_activation_keys.icon, ), ); tools.insert( ToolType::DeletionTool, ( Box::new(DeletionTool::new()), config.tool_activation_keys.deletion, ), ); assert_eq!(ToolType::NumTools as usize, tools.len()); Self { map, tools, active: ToolType::RectRoomTool, config } } /// Get the currently active tool. pub fn active(&self) -> ToolType { self.active } /// Set the currently active tool. Any process currently going on in a different tool will be /// aborted. pub fn set_active(&mut self, tool: ToolType) { if tool != self.active { self.tools.get_mut(&self.active).unwrap().0.deactivate(); self.active = tool; self.tools .get_mut(&self.active) .expect("{:?} is not a Tool in the Editor. Maybe you forgot to register it?") .0 .activate(); } } pub fn update(&mut self, rl: &mut RaylibHandle, transform: &Transform, mouse_blocked: bool) { // Handle keybindings for tool change for (&tool_type, (_, activation_key)) in self.tools.iter() { if activation_key.is_pressed(rl, false) { // Don't do anything if the tool does not change. if tool_type == self.active { break; } // Activate the tool of which the key binding has been pressed. self.set_active(tool_type); break; } } /* TODO: reintroduce saving and loading // Handle saving and loading the editor contents to the swap file if rl.is_key_pressed(KeyboardKey::KEY_S) { self.map_data .write_file("swap.ron") .expect("Unable to write buffer file"); } else if rl.is_key_pressed(KeyboardKey::KEY_L) { self.map_data .load_file("swap.ron") .expect("Unable to read buffer file"); } */ let mouse_pos_m = transform.point_px_to_m(&rl.get_mouse_position().into()); let snapped_mouse_pos = snap_to_grid(mouse_pos_m, SNAP_SIZE); // Update the currently active tool let active_tool = &mut self.tools.get_mut(&self.active).unwrap().0; active_tool.update(&self.map, &snapped_mouse_pos); // Handle common keybindings many of the tools have. if self.config.tool_general_keys.place_single.is_pressed(rl, mouse_blocked) { active_tool.place_single(&mut self.map, &snapped_mouse_pos); } if self.config.tool_general_keys.finish.is_pressed(rl, mouse_blocked) { active_tool.finish(&mut self.map); } if self.config.tool_general_keys.abort.is_pressed(rl, mouse_blocked) { active_tool.abort(); } // Handle custom keybindings in case the tool has any. let latest_button = if let Some(keyboard_key) = rl.get_key_pressed() { Some(Button::Keyboard(keyboard_key.into())) } else { let mouse_buttons = [Button::Mouse(MouseButton::Left), Button::Mouse(MouseButton::Middle), Button::Mouse(MouseButton::Right)]; mouse_buttons.iter().find(|button| button.is_pressed(rl, mouse_blocked)).copied() }; if let Some(latest_button) = latest_button { active_tool.on_button_pressed(&mut self.map, latest_button); } } pub fn draw_tools(&self, rld: &mut RaylibDrawHandle, transform: &Transform) { for (tool, _) in self.tools.values() { tool.draw(rld, transform); } } pub fn map(&self) -> &Map { &self.map } }