From 9799d3c6a8f0c242668203a1c70d7b6cfed3e855 Mon Sep 17 00:00:00 2001 From: Arne Dußin Date: Tue, 15 Dec 2020 00:46:54 +0100 Subject: Refactor to make interaction between tools easier --- src/tool/icon_tool.rs | 197 ++++++++------------------------------------------ 1 file changed, 30 insertions(+), 167 deletions(-) (limited to 'src/tool/icon_tool.rs') diff --git a/src/tool/icon_tool.rs b/src/tool/icon_tool.rs index e972c1c..09b0ac1 100644 --- a/src/tool/icon_tool.rs +++ b/src/tool/icon_tool.rs @@ -1,115 +1,33 @@ use crate::button::Button; -use crate::config::{IconToolKeybindings, ToolKeybindings}; -use crate::grid::{snap_to_grid, SNAP_SIZE}; -use crate::map_data::MapData; +use crate::config::IconToolKeys; +use crate::map::icon_renderer::IconRenderer; +use crate::map::{Icon, Map, Mappable}; use crate::math::Vec2; use crate::tool::Tool; use crate::transform::Transform; -use raylib::core::drawing::{RaylibDraw, RaylibDrawHandle}; -use raylib::core::texture::Texture2D; -use raylib::ffi::Color; -use raylib::{RaylibHandle, RaylibThread}; -use ron::de::from_reader; -use serde::{Deserialize, Serialize}; -use std::fs::{self, File}; +use raylib::core::drawing::RaylibDrawHandle; +use std::rc::Rc; pub const ICON_DIR: &str = "assets/icons"; -#[derive(Deserialize)] -struct IconFileInfo { - /// The position the icon should be anchored in pixels. This is the Vector it will be moved by - /// relative to the mouse pointer (to the left and up). - anchor: Vec2, - /// The scale of the icon as expressed in image pixels per real meter. - pixels_per_m: f64, -} - -#[derive(Clone, Serialize, Deserialize)] -pub struct IconInfo { - /// The id of the icon is the icons position in the currently loaded icon_data vector. - pub icon_id: usize, - /// The position of the icon on the map, given by the vector in meters. - pub position: Vec2, - /// Rotation of the icon texture in degrees. - pub rotation: f64, -} - pub struct IconTool { // TODO: support svg - keybindings: IconToolKeybindings, - /// The icon data, containing the image texture and the info for that image texture like the - /// scale the image actually has. - icon_data: Vec<(Texture2D, IconFileInfo)>, + keybindings: IconToolKeys, /// Saves whether the IconTool is the currently active tool or not. active: bool, /// The information of the icon that should be placed / is currently being placed, if it /// exists. - current_icon: IconInfo, -} - -impl Default for IconInfo { - fn default() -> Self { - Self { - icon_id: 0, - position: Vec2::new(0., 0.), - rotation: 0., - } - } + current_icon: Icon, + renderer: Rc, } impl IconTool { - pub fn new( - rl: &mut RaylibHandle, - rlt: &RaylibThread, - keybindings: IconToolKeybindings, - ) -> Self { - /* Read all available icons from the icon directory. SVGs do not need any special scale - * file, but pixel-based file formats require a RON-file declaring what the scale of the - * picture is right beside them. - */ - let mut image_files = Vec::new(); - for entry in fs::read_dir(ICON_DIR).expect("Could not open icon directory") { - let entry = entry.expect("Failed to read file from icon directory"); - - // Ignore the RON-files for now and put the image files into the vec - if entry - .path() - .extension() - .expect("Entry does not have a file extension") - != "ron" - { - image_files.push(entry); - } - } - - // Read the RON-files where it is necessary. - let mut icon_data = Vec::with_capacity(image_files.len()); - for file in image_files { - // TODO: Handle svg - - let texture = rl - .load_texture( - rlt, - file.path() - .to_str() - .expect("Unable to convert path to string."), - ) - .expect("Could not read image file"); - - let mut file = file.path(); - file.set_extension("ron"); - let ron = File::open(file).expect("Could not read ron file for icon information."); - let icon_info: IconFileInfo = - from_reader(ron).expect("Could not parse icon info from reader."); - - icon_data.push((texture, icon_info)); - } - + pub fn new(keybindings: IconToolKeys, renderer: Rc) -> Self { Self { keybindings, - icon_data, active: false, - current_icon: IconInfo::default(), + current_icon: Icon::new(0, Vec2::default(), 0., renderer.clone()), + renderer, } } } @@ -123,85 +41,30 @@ impl Tool for IconTool { self.active = false; } - fn active_update( - &mut self, - map: &mut MapData, - rl: &RaylibHandle, - transform: &Transform, - mouse_blocked: bool, - ) { - // Update the position of the icon that should be drawn to the current mouse position. - let snapped_mouse_pos_m = snap_to_grid( - transform.point_px_to_m(&rl.get_mouse_position().into()), - SNAP_SIZE, - ); - self.current_icon.position = snapped_mouse_pos_m; - - // Unwrap the current icon, since it is now definitely set, as we are in the active update. - if self.keybindings.next.is_pressed(rl, mouse_blocked) { - self.current_icon.icon_id = (self.current_icon.icon_id + 1) % self.icon_data.len(); - } - if self - .keybindings - .rotate_clockwise - .is_pressed(rl, mouse_blocked) - { - self.current_icon.rotation += 45.; - } - - // Handle placing the icon on the map - if self.keybindings.place.is_pressed(rl, mouse_blocked) { - map.icons_mut().push(self.current_icon.clone()); - } + fn update(&mut self, _map: &Map, mouse_pos_m: &Vec2) { + self.current_icon.position = *mouse_pos_m; } - fn draw(&self, map: &MapData, rld: &mut RaylibDrawHandle, transform: &Transform) { - // Draw all icons that have been placed on the map. - for icon in map.icons() { - let (texture, info) = &self.icon_data[icon.icon_id]; - // Round the position to whole pixels to fix rotation problems. - let mut position_px = - transform.point_m_to_px(&(icon.position - (info.anchor / info.pixels_per_m))); - position_px.x = position_px.x.floor(); - position_px.y = position_px.y.floor(); - rld.draw_texture_ex( - texture, - position_px, - icon.rotation as f32, - (transform.pixels_per_m() / info.pixels_per_m) as f32, - Color { - r: 255, - g: 255, - b: 255, - a: 255, - }, - ); - } - - // Draw the icon that would be placed + fn draw(&self, rld: &mut RaylibDrawHandle, transform: &Transform) { if self.active { - let (texture, info) = &self.icon_data[self.current_icon.icon_id]; - // Round the position to whole pixels to fix rotation problems. - let mut position_px = transform - .point_m_to_px(&(self.current_icon.position - (info.anchor / info.pixels_per_m))); - position_px.x = position_px.x.floor(); - position_px.y = position_px.y.floor(); - rld.draw_texture_ex( - texture, - position_px, - self.current_icon.rotation as f32, - (transform.pixels_per_m() / info.pixels_per_m) as f32, - Color { - r: 120, - g: 200, - b: 120, - a: 255, - }, - ); + self.current_icon.draw(rld, transform); } } - fn activation_key(&self) -> Button { - self.keybindings.activation_key() + fn place_single(&mut self, map: &mut Map, _mouse_pos_m: &Vec2) { + map.push_icon(self.current_icon.clone()); + } + + fn on_button_pressed(&mut self, _map: &mut Map, button: Button) { + if button == self.keybindings.next { + self.current_icon.id = (self.current_icon.id + 1) % self.renderer.num_icons(); + } else if button == self.keybindings.previous { + self.current_icon.id = + (self.current_icon.id + self.renderer.num_icons() - 1) % self.renderer.num_icons(); + } else if button == self.keybindings.rotate_clockwise { + self.current_icon.rotation += 45.; + } else if button == self.keybindings.rotate_counterclockwise { + self.current_icon.rotation -= 45.; + } } } -- cgit v1.2.3-70-g09d2