diff options
| author | Arne Dußin | 2020-11-08 16:00:54 +0100 |
|---|---|---|
| committer | Arne Dußin | 2020-11-08 16:00:54 +0100 |
| commit | e08cb85528e6b72d5f3b2fbeb79b581fa7a4e461 (patch) | |
| tree | 15b443ce0aa82ae662a544523bd91633aafd011e /src | |
| parent | c89592a9de3a9d21082952b8d90584d759ed7ef3 (diff) | |
| download | graf_karto-e08cb85528e6b72d5f3b2fbeb79b581fa7a4e461.tar.gz graf_karto-e08cb85528e6b72d5f3b2fbeb79b581fa7a4e461.zip | |
Make it so icons can rotate
Diffstat (limited to 'src')
| -rw-r--r-- | src/map_data.rs | 7 | ||||
| -rw-r--r-- | src/tool/deletion_tool.rs | 6 | ||||
| -rw-r--r-- | src/tool/icon_tool.rs | 90 |
3 files changed, 71 insertions, 32 deletions
diff --git a/src/map_data.rs b/src/map_data.rs index fa3a389..8d0d926 100644 --- a/src/map_data.rs +++ b/src/map_data.rs @@ -1,4 +1,5 @@ use crate::math::{Rect, Vec2}; +use crate::tool::icon_tool::IconInfo; use ron::de::from_reader; use ron::ser::{to_string_pretty, PrettyConfig}; use serde::{Deserialize, Serialize}; @@ -13,7 +14,7 @@ use std::path::Path; pub struct MapData { rooms: Vec<Rect<f32>>, walls: Vec<(Vec2<f32>, Vec2<f32>)>, - icons: Vec<(usize, Vec2<f32>)>, + icons: Vec<IconInfo>, } impl MapData { @@ -76,10 +77,10 @@ impl MapData { &mut self.walls } - pub fn icons(&self) -> &Vec<(usize, Vec2<f32>)> { + pub fn icons(&self) -> &Vec<IconInfo> { &self.icons } - pub fn icons_mut(&mut self) -> &mut Vec<(usize, Vec2<f32>)> { + pub fn icons_mut(&mut self) -> &mut Vec<IconInfo> { &mut self.icons } } diff --git a/src/tool/deletion_tool.rs b/src/tool/deletion_tool.rs index 24d239f..142e0cb 100644 --- a/src/tool/deletion_tool.rs +++ b/src/tool/deletion_tool.rs @@ -25,7 +25,9 @@ impl DeletionTool { map_data .walls_mut() .retain(|&(pos1, pos2)| !rect.contains(pos1) || !rect.contains(pos2)); - map_data.icons_mut().retain(|&(_, pos)| !rect.contains(pos)); + map_data + .icons_mut() + .retain(|icon| !rect.contains(icon.position)); } } @@ -51,7 +53,7 @@ impl Tool for DeletionTool { } } - fn draw(&self, map_data: &MapData, rld: &mut RaylibDrawHandle, transform: &Transform) { + fn draw(&self, _map_data: &MapData, rld: &mut RaylibDrawHandle, transform: &Transform) { if let Some((pos1, pos2)) = self.deletion_rect { let rect_px = transform.rect_m_to_px(Rect::bounding_rect(pos1, pos2)); rld.draw_rectangle_rec( diff --git a/src/tool/icon_tool.rs b/src/tool/icon_tool.rs index 0ff1dc2..89a07e8 100644 --- a/src/tool/icon_tool.rs +++ b/src/tool/icon_tool.rs @@ -8,13 +8,13 @@ use raylib::core::texture::Texture2D; use raylib::ffi::{Color, KeyboardKey, MouseButton}; use raylib::{RaylibHandle, RaylibThread}; use ron::de::from_reader; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use std::fs::{self, File}; pub const ICON_DIR: &'static str = "assets/icons"; #[derive(Deserialize)] -struct IconInfo { +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<f32>, @@ -22,14 +22,24 @@ struct IconInfo { pixels_per_m: f32, } +#[derive(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<f32>, + /// Rotation of the icon texture in degrees. + pub rotation: f32, +} + pub struct IconTool { // TODO: support svg /// 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, IconInfo)>, - /// The currently active icon, defined by its position in the Vec. - active_icon: usize, - current_icon_pos: Option<Vec2<f32>>, + icon_data: Vec<(Texture2D, IconFileInfo)>, + /// The information of the icon that should be placed / is currently being placed, if it + /// exists. + current_icon: Option<IconInfo>, } impl IconTool { @@ -70,7 +80,7 @@ impl IconTool { 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: IconInfo = + let icon_info: IconFileInfo = from_reader(ron).expect("Could not parse icon info from reader."); icon_data.push((texture, icon_info)); @@ -78,40 +88,61 @@ impl IconTool { Self { icon_data, - active_icon: 0, - current_icon_pos: None, + current_icon: None, } } } impl Tool for IconTool { fn active_update(&mut self, map: &mut MapData, rl: &RaylibHandle, transform: &Transform) { - // Put the currently active icon to where it would be placed. - self.current_icon_pos = Some(snap_to_grid( - transform.point_px_to_m(rl.get_mouse_position().into()), - 0.5, - )); + // Update the position of the icon that should be drawn to the current mouse position, or + // create a new default icon if there was `None`. + let snapped_mouse_pos_m = + snap_to_grid(transform.point_px_to_m(rl.get_mouse_position().into()), 0.5); + self.current_icon = match self.current_icon.take() { + Some(mut icon) => { + icon.position = snapped_mouse_pos_m; + Some(icon) + } + None => Some(IconInfo { + icon_id: 0, + position: snapped_mouse_pos_m, + rotation: 0., + }), + }; - // Activate the next icon when pressing the icon tool key. - if rl.is_key_pressed(KeyboardKey::KEY_I) { - self.active_icon = (self.active_icon + 1) % self.icon_data.len(); + { + // Unwrap the current icon, since it is now definitely set, as we are in the active update. + let active_icon = self.current_icon.as_mut().unwrap(); + // Activate the next icon when pressing the icon tool key. + if rl.is_key_pressed(KeyboardKey::KEY_I) { + active_icon.icon_id = (active_icon.icon_id + 1) % self.icon_data.len(); + } + if rl.is_mouse_button_pressed(MouseButton::MOUSE_RIGHT_BUTTON) { + // Rotate the currently active icon by a quarter rotation. + active_icon.rotation += 45.; + } } // Handle placing the icon on the map if rl.is_mouse_button_pressed(MouseButton::MOUSE_LEFT_BUTTON) { - map.icons_mut() - .push((self.active_icon, self.current_icon_pos.unwrap())); + map.icons_mut().push(self.current_icon.take().unwrap()); } } fn draw(&self, map: &MapData, rld: &mut RaylibDrawHandle, transform: &Transform) { // Draw all icons that have been placed on the map. - for (icon, pos) in map.icons() { - let (texture, info) = &self.icon_data[*icon]; + 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 as i32 as f32; + position_px.y = position_px.y as i32 as f32; rld.draw_texture_ex( texture, - transform.point_m_to_px(*pos - (info.anchor / info.pixels_per_m)), - 0., + position_px, + icon.rotation, transform.pixels_per_m() / info.pixels_per_m, Color { r: 255, @@ -123,12 +154,17 @@ impl Tool for IconTool { } // Draw the icon that would be placed - if let Some(current_icon_pos) = self.current_icon_pos { - let (texture, info) = &self.icon_data[self.active_icon]; + if let Some(current_icon) = &self.current_icon { + let (texture, info) = &self.icon_data[current_icon.icon_id]; + // Round the position to whole pixels to fix rotation problems. + let mut position_px = + transform.point_m_to_px(current_icon.position - (info.anchor / info.pixels_per_m)); + position_px.x = position_px.x as i32 as f32; + position_px.y = position_px.y as i32 as f32; rld.draw_texture_ex( texture, - transform.point_m_to_px(current_icon_pos - (info.anchor / info.pixels_per_m)), - 0., + position_px, + current_icon.rotation, transform.pixels_per_m() / info.pixels_per_m, Color { r: 120, |
